aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-10-16 08:52:51 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-10-16 08:52:51 -0400
commitc2ff5cf5294bcbd7fa50f7d860e90a66db7e5059 (patch)
tree2ec5e407ddd6cd4bb563b41f8c7d5026c4a3358c
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
iommu/amd: Work around wrong IOAPIC device-id in IVRS table
On some systems the BIOS puts the wrong device-id for the IO-APIC into the IVRS table. The result is that interrupt remapping is not working for the IO-APIC irqs. This usually means a kernel panic at boot because the timer is not working. Fix this kernel panic by disabling interrupt remapping if this problem is discovered in the IVRS table. Reported-by: Andrew Oakley <andrew@ado.is-a-geek.net> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r--drivers/iommu/amd_iommu_init.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 18b0d99bd4d..81837b0710a 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void)
1599#endif 1599#endif
1600} 1600}
1601 1601
1602/* SB IOAPIC is always on this device in AMD systems */
1603#define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0))
1604
1602static bool __init check_ioapic_information(void) 1605static bool __init check_ioapic_information(void)
1603{ 1606{
1607 bool ret, has_sb_ioapic;
1604 int idx; 1608 int idx;
1605 1609
1606 for (idx = 0; idx < nr_ioapics; idx++) { 1610 has_sb_ioapic = false;
1607 int id = mpc_ioapic_id(idx); 1611 ret = false;
1608 1612
1609 if (get_ioapic_devid(id) < 0) { 1613 for (idx = 0; idx < nr_ioapics; idx++) {
1610 pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id); 1614 int devid, id = mpc_ioapic_id(idx);
1611 pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n"); 1615
1612 return false; 1616 devid = get_ioapic_devid(id);
1617 if (devid < 0) {
1618 pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id);
1619 ret = false;
1620 } else if (devid == IOAPIC_SB_DEVID) {
1621 has_sb_ioapic = true;
1622 ret = true;
1613 } 1623 }
1614 } 1624 }
1615 1625
1616 return true; 1626 if (!has_sb_ioapic) {
1627 /*
1628 * We expect the SB IOAPIC to be listed in the IVRS
1629 * table. The system timer is connected to the SB IOAPIC
1630 * and if we don't have it in the list the system will
1631 * panic at boot time. This situation usually happens
1632 * when the BIOS is buggy and provides us the wrong
1633 * device id for the IOAPIC in the system.
1634 */
1635 pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n");
1636 }
1637
1638 if (!ret)
1639 pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n");
1640
1641 return ret;
1617} 1642}
1618 1643
1619static void __init free_dma_resources(void) 1644static void __init free_dma_resources(void)