aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2009-03-16 20:04:57 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2009-03-17 18:39:58 -0400
commit1531a6a6b81a4e6f9eec9a5608758a6ea14b96e0 (patch)
tree3b1523516192fdd19b286879376b4d3d7c827b0d
parenteba67e5da6e971993b2899d2cdf459ce77d3dbc5 (diff)
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@intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--drivers/pci/dmar.c5
-rw-r--r--drivers/pci/intel-iommu.c29
-rw-r--r--drivers/pci/intr_remapping.c17
-rw-r--r--include/linux/dmar.h2
4 files changed, 49 insertions, 4 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 932e5e3930fc..f1805002e436 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,
982} 982}
983 983
984#define PRIMARY_FAULT_REG_LEN (16) 984#define PRIMARY_FAULT_REG_LEN (16)
985static irqreturn_t dmar_fault(int irq, void *dev_id) 985irqreturn_t dmar_fault(int irq, void *dev_id)
986{ 986{
987 struct intel_iommu *iommu = dev_id; 987 struct intel_iommu *iommu = dev_id;
988 int reg, fault_index; 988 int reg, fault_index;
@@ -1074,9 +1074,6 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
1074 return 0; 1074 return 0;
1075 } 1075 }
1076 1076
1077 /* Force fault register is cleared */
1078 dmar_fault(irq, iommu);
1079
1080 ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu); 1077 ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu);
1081 if (ret) 1078 if (ret)
1082 printk(KERN_ERR "IOMMU: can't request irq\n"); 1079 printk(KERN_ERR "IOMMU: can't request irq\n");
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 25fc1df486bb..ef167b8b047d 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1855,11 +1855,40 @@ static int __init init_dmars(void)
1855 } 1855 }
1856 } 1856 }
1857 1857
1858 /*
1859 * Start from the sane iommu hardware state.
1860 */
1858 for_each_drhd_unit(drhd) { 1861 for_each_drhd_unit(drhd) {
1859 if (drhd->ignored) 1862 if (drhd->ignored)
1860 continue; 1863 continue;
1861 1864
1862 iommu = drhd->iommu; 1865 iommu = drhd->iommu;
1866
1867 /*
1868 * If the queued invalidation is already initialized by us
1869 * (for example, while enabling interrupt-remapping) then
1870 * we got the things already rolling from a sane state.
1871 */
1872 if (iommu->qi)
1873 continue;
1874
1875 /*
1876 * Clear any previous faults.
1877 */
1878 dmar_fault(-1, iommu);
1879 /*
1880 * Disable queued invalidation if supported and already enabled
1881 * before OS handover.
1882 */
1883 dmar_disable_qi(iommu);
1884 }
1885
1886 for_each_drhd_unit(drhd) {
1887 if (drhd->ignored)
1888 continue;
1889
1890 iommu = drhd->iommu;
1891
1863 if (dmar_enable_qi(iommu)) { 1892 if (dmar_enable_qi(iommu)) {
1864 /* 1893 /*
1865 * Queued Invalidate not enabled, use Register Based 1894 * Queued Invalidate not enabled, use Register Based
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 0d202d73a1ac..a84686b2478b 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -499,6 +499,23 @@ int __init enable_intr_remapping(int eim)
499 struct dmar_drhd_unit *drhd; 499 struct dmar_drhd_unit *drhd;
500 int setup = 0; 500 int setup = 0;
501 501
502 for_each_drhd_unit(drhd) {
503 struct intel_iommu *iommu = drhd->iommu;
504
505 /*
506 * Clear previous faults.
507 */
508 dmar_fault(-1, iommu);
509
510 /*
511 * Disable intr remapping and queued invalidation, if already
512 * enabled prior to OS handover.
513 */
514 disable_intr_remapping(iommu);
515
516 dmar_disable_qi(iommu);
517 }
518
502 /* 519 /*
503 * check for the Interrupt-remapping support 520 * check for the Interrupt-remapping support
504 */ 521 */
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index c7768330c11d..8a035aec14a9 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -24,6 +24,7 @@
24#include <linux/acpi.h> 24#include <linux/acpi.h>
25#include <linux/types.h> 25#include <linux/types.h>
26#include <linux/msi.h> 26#include <linux/msi.h>
27#include <linux/irqreturn.h>
27 28
28#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) 29#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
29struct intel_iommu; 30struct intel_iommu;
@@ -125,6 +126,7 @@ extern void dmar_msi_mask(unsigned int irq);
125extern void dmar_msi_read(int irq, struct msi_msg *msg); 126extern void dmar_msi_read(int irq, struct msi_msg *msg);
126extern void dmar_msi_write(int irq, struct msi_msg *msg); 127extern void dmar_msi_write(int irq, struct msi_msg *msg);
127extern int dmar_set_interrupt(struct intel_iommu *iommu); 128extern int dmar_set_interrupt(struct intel_iommu *iommu);
129extern irqreturn_t dmar_fault(int irq, void *dev_id);
128extern int arch_setup_dmar_msi(unsigned int irq); 130extern int arch_setup_dmar_msi(unsigned int irq);
129 131
130#ifdef CONFIG_DMAR 132#ifdef CONFIG_DMAR