|
@@ -1086,6 +1086,11 @@ static void free_iommu(struct intel_iommu *iommu)
|
|
|
iommu_device_destroy(iommu->iommu_dev);
|
|
|
|
|
|
if (iommu->irq) {
|
|
|
+ if (iommu->pr_irq) {
|
|
|
+ free_irq(iommu->pr_irq, iommu);
|
|
|
+ dmar_free_hwirq(iommu->pr_irq);
|
|
|
+ iommu->pr_irq = 0;
|
|
|
+ }
|
|
|
free_irq(iommu->irq, iommu);
|
|
|
dmar_free_hwirq(iommu->irq);
|
|
|
iommu->irq = 0;
|
|
@@ -1493,53 +1498,68 @@ static const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static inline int dmar_msi_reg(struct intel_iommu *iommu, int irq)
|
|
|
+{
|
|
|
+ if (iommu->irq == irq)
|
|
|
+ return DMAR_FECTL_REG;
|
|
|
+ else if (iommu->pr_irq == irq)
|
|
|
+ return DMAR_PECTL_REG;
|
|
|
+ else
|
|
|
+ BUG();
|
|
|
+}
|
|
|
+
|
|
|
void dmar_msi_unmask(struct irq_data *data)
|
|
|
{
|
|
|
struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
|
|
|
+ int reg = dmar_msi_reg(iommu, data->irq);
|
|
|
unsigned long flag;
|
|
|
|
|
|
/* unmask it */
|
|
|
raw_spin_lock_irqsave(&iommu->register_lock, flag);
|
|
|
- writel(0, iommu->reg + DMAR_FECTL_REG);
|
|
|
+ writel(0, iommu->reg + reg);
|
|
|
/* Read a reg to force flush the post write */
|
|
|
- readl(iommu->reg + DMAR_FECTL_REG);
|
|
|
+ readl(iommu->reg + reg);
|
|
|
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
|
|
|
}
|
|
|
|
|
|
void dmar_msi_mask(struct irq_data *data)
|
|
|
{
|
|
|
- unsigned long flag;
|
|
|
struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
|
|
|
+ int reg = dmar_msi_reg(iommu, data->irq);
|
|
|
+ unsigned long flag;
|
|
|
|
|
|
/* mask it */
|
|
|
raw_spin_lock_irqsave(&iommu->register_lock, flag);
|
|
|
- writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
|
|
|
+ writel(DMA_FECTL_IM, iommu->reg + reg);
|
|
|
/* Read a reg to force flush the post write */
|
|
|
- readl(iommu->reg + DMAR_FECTL_REG);
|
|
|
+ readl(iommu->reg + reg);
|
|
|
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
|
|
|
}
|
|
|
|
|
|
void dmar_msi_write(int irq, struct msi_msg *msg)
|
|
|
{
|
|
|
struct intel_iommu *iommu = irq_get_handler_data(irq);
|
|
|
+ int reg = dmar_msi_reg(iommu, irq);
|
|
|
unsigned long flag;
|
|
|
|
|
|
raw_spin_lock_irqsave(&iommu->register_lock, flag);
|
|
|
- writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
|
|
|
- writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
|
|
|
- writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
|
|
|
+ writel(msg->data, iommu->reg + reg + 4);
|
|
|
+ writel(msg->address_lo, iommu->reg + reg + 8);
|
|
|
+ writel(msg->address_hi, iommu->reg + reg + 12);
|
|
|
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
|
|
|
}
|
|
|
|
|
|
void dmar_msi_read(int irq, struct msi_msg *msg)
|
|
|
{
|
|
|
struct intel_iommu *iommu = irq_get_handler_data(irq);
|
|
|
+ int reg = dmar_msi_reg(iommu, irq);
|
|
|
unsigned long flag;
|
|
|
|
|
|
raw_spin_lock_irqsave(&iommu->register_lock, flag);
|
|
|
- msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
|
|
|
- msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
|
|
|
- msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
|
|
|
+ msg->data = readl(iommu->reg + reg + 4);
|
|
|
+ msg->address_lo = readl(iommu->reg + reg + 8);
|
|
|
+ msg->address_hi = readl(iommu->reg + reg + 12);
|
|
|
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
|
|
|
}
|
|
|
|