diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-03-16 20:04:57 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-03-17 18:39:58 -0400 |
commit | 1531a6a6b81a4e6f9eec9a5608758a6ea14b96e0 (patch) | |
tree | 3b1523516192fdd19b286879376b4d3d7c827b0d | |
parent | eba67e5da6e971993b2899d2cdf459ce77d3dbc5 (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.c | 5 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 29 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 17 | ||||
-rw-r--r-- | 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 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) |
985 | static irqreturn_t dmar_fault(int irq, void *dev_id) | 985 | irqreturn_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) |
29 | struct intel_iommu; | 30 | struct intel_iommu; |
@@ -125,6 +126,7 @@ extern void dmar_msi_mask(unsigned int irq); | |||
125 | extern void dmar_msi_read(int irq, struct msi_msg *msg); | 126 | extern void dmar_msi_read(int irq, struct msi_msg *msg); |
126 | extern void dmar_msi_write(int irq, struct msi_msg *msg); | 127 | extern void dmar_msi_write(int irq, struct msi_msg *msg); |
127 | extern int dmar_set_interrupt(struct intel_iommu *iommu); | 128 | extern int dmar_set_interrupt(struct intel_iommu *iommu); |
129 | extern irqreturn_t dmar_fault(int irq, void *dev_id); | ||
128 | extern int arch_setup_dmar_msi(unsigned int irq); | 130 | extern int arch_setup_dmar_msi(unsigned int irq); |
129 | 131 | ||
130 | #ifdef CONFIG_DMAR | 132 | #ifdef CONFIG_DMAR |