[tip:x86/x2apic] x86, dmar: start with sane state while enabling dma and interrupt-remapping

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit-ID:  1531a6a6b81a4e6f9eec9a5608758a6ea14b96e0
Gitweb:     http://git.kernel.org/tip/1531a6a6b81a4e6f9eec9a5608758a6ea14b96e0
Author:     Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
AuthorDate: Mon, 16 Mar 2009 17:04:57 -0700
Commit:     H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>
CommitDate: Tue, 17 Mar 2009 15:39:58 -0700

x86, dmar: start with sane state while enabling dma and interrupt-remapping

Impact: cleanup/sanitization

Start from a sane state while enabling dma and interrupt-remapping, by
clearing the previous recorded faults and disabling previously
enabled queued invalidation and interrupt-remapping.

Signed-off-by: Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
Signed-off-by: H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>


---
 drivers/pci/dmar.c           |    5 +----
 drivers/pci/intel-iommu.c    |   29 +++++++++++++++++++++++++++++
 drivers/pci/intr_remapping.c |   17 +++++++++++++++++
 include/linux/dmar.h         |    2 ++
 4 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 932e5e3..f180500 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -982,7 +982,7 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
 }
 
 #define PRIMARY_FAULT_REG_LEN (16)
-static irqreturn_t dmar_fault(int irq, void *dev_id)
+irqreturn_t dmar_fault(int irq, void *dev_id)
 {
 	struct intel_iommu *iommu = dev_id;
 	int reg, fault_index;
@@ -1074,9 +1074,6 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 		return 0;
 	}
 
-	/* Force fault register is cleared */
-	dmar_fault(irq, iommu);
-
 	ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu);
 	if (ret)
 		printk(KERN_ERR "IOMMU: can't request irq\n");
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 25fc1df..ef167b8 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1855,11 +1855,40 @@ static int __init init_dmars(void)
 		}
 	}
 
+	/*
+	 * Start from the sane iommu hardware state.
+	 */
 	for_each_drhd_unit(drhd) {
 		if (drhd->ignored)
 			continue;
 
 		iommu = drhd->iommu;
+
+		/*
+		 * If the queued invalidation is already initialized by us
+		 * (for example, while enabling interrupt-remapping) then
+		 * we got the things already rolling from a sane state.
+		 */
+		if (iommu->qi)
+			continue;
+
+		/*
+		 * Clear any previous faults.
+		 */
+		dmar_fault(-1, iommu);
+		/*
+		 * Disable queued invalidation if supported and already enabled
+		 * before OS handover.
+		 */
+		dmar_disable_qi(iommu);
+	}
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+
+		iommu = drhd->iommu;
+
 		if (dmar_enable_qi(iommu)) {
 			/*
 			 * Queued Invalidate not enabled, use Register Based
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 0d202d7..a84686b 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -499,6 +499,23 @@ int __init enable_intr_remapping(int eim)
 	struct dmar_drhd_unit *drhd;
 	int setup = 0;
 
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		/*
+		 * Clear previous faults.
+		 */
+		dmar_fault(-1, iommu);
+
+		/*
+		 * Disable intr remapping and queued invalidation, if already
+		 * enabled prior to OS handover.
+		 */
+		disable_intr_remapping(iommu);
+
+		dmar_disable_qi(iommu);
+	}
+
 	/*
 	 * check for the Interrupt-remapping support
 	 */
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index c776833..8a035ae 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/types.h>
 #include <linux/msi.h>
+#include <linux/irqreturn.h>
 
 #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
 struct intel_iommu;
@@ -125,6 +126,7 @@ extern void dmar_msi_mask(unsigned int irq);
 extern void dmar_msi_read(int irq, struct msi_msg *msg);
 extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
+extern irqreturn_t dmar_fault(int irq, void *dev_id);
 extern int arch_setup_dmar_msi(unsigned int irq);
 
 #ifdef CONFIG_DMAR
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux