aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYouquan Song <youquan.song@intel.com>2009-09-09 12:05:39 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-09-11 11:40:10 -0400
commit074835f0143b83845af5044af2739c52c9f53808 (patch)
treef573860163fda805b97656f7bc400f148179e1a9
parente936d0773df172ec8600777fdd72bbc1f75f22ad (diff)
intel-iommu: Fix kernel hang if interrupt remapping disabled in BIOS
BIOS clear DMAR table INTR_REMAP flag to disable interrupt remapping. Current kernel only check interrupt remapping(IR) flag in DRHD's extended capability register to decide interrupt remapping support or not. But IR flag will not change when BIOS disable/enable interrupt remapping. When user disable interrupt remapping in BIOS or BIOS often defaultly disable interrupt remapping feature when BIOS is not mature.Though BIOS disable interrupt remapping but intr_remapping_supported function will always report to OS support interrupt remapping if VT-d2 chipset populated. On this cases, kernel will continue enable interrupt remapping and result kernel panic. This bug exist on almost all platforms with interrupt remapping support. This patch add DMAR table INTR_REMAP flag check before enable interrupt remapping. Signed-off-by: Youquan Song <youquan.song@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/pci/dmar.c10
-rw-r--r--drivers/pci/intr_remapping.c3
-rw-r--r--include/linux/intel-iommu.h2
3 files changed, 15 insertions, 0 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index fba4f6891680..270ed222a075 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -1316,3 +1316,13 @@ int dmar_reenable_qi(struct intel_iommu *iommu)
1316 1316
1317 return 0; 1317 return 0;
1318} 1318}
1319
1320/*
1321 * Check interrupt remapping support in DMAR table description.
1322 */
1323int dmar_ir_support(void)
1324{
1325 struct acpi_table_dmar *dmar;
1326 dmar = (struct acpi_table_dmar *)dmar_tbl;
1327 return dmar->flags & 0x1;
1328}
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index ebfa47b79c5b..ac065144c01c 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -611,6 +611,9 @@ int __init intr_remapping_supported(void)
611 if (disable_intremap) 611 if (disable_intremap)
612 return 0; 612 return 0;
613 613
614 if (!dmar_ir_support())
615 return 0;
616
614 for_each_drhd_unit(drhd) { 617 for_each_drhd_unit(drhd) {
615 struct intel_iommu *iommu = drhd->iommu; 618 struct intel_iommu *iommu = drhd->iommu;
616 619
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 482dc91fd53a..4f0a72a9740c 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -360,4 +360,6 @@ extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
360 360
361extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); 361extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
362 362
363extern int dmar_ir_support(void);
364
363#endif 365#endif