aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-07-05 05:58:02 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-09-28 11:31:09 -0400
commiteb1eb7ae65a9d32f6c16a90419caf01221f94734 (patch)
treefd57fa0d4fe3a201882d840dc94682a7656efb6a /drivers/iommu
parent0ea2c422bc8da99d14baa46d4789861a4f8d4ec0 (diff)
iommu/amd: Check if IOAPIC information is correct
When the IOAPIC information provided in the IVRS table is not correct or not complete the system may not boot at all when interrupt remapping is enabled. So check if this information is correct and print out a firmware bug message when it is not. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/Kconfig2
-rw-r--r--drivers/iommu/amd_iommu_init.c27
2 files changed, 25 insertions, 4 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 9f69b561f5db..e39f9dbf297b 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -42,7 +42,7 @@ config AMD_IOMMU
42 select PCI_PRI 42 select PCI_PRI
43 select PCI_PASID 43 select PCI_PASID
44 select IOMMU_API 44 select IOMMU_API
45 depends on X86_64 && PCI && ACPI 45 depends on X86_64 && PCI && ACPI && X86_IO_APIC
46 ---help--- 46 ---help---
47 With this option you can enable support for AMD IOMMU hardware in 47 With this option you can enable support for AMD IOMMU hardware in
48 your system. An IOMMU is a hardware component which provides 48 your system. An IOMMU is a hardware component which provides
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 2d923fe7c2a1..f8a222b0ac3f 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -33,6 +33,7 @@
33#include <asm/gart.h> 33#include <asm/gart.h>
34#include <asm/x86_init.h> 34#include <asm/x86_init.h>
35#include <asm/iommu_table.h> 35#include <asm/iommu_table.h>
36#include <asm/io_apic.h>
36 37
37#include "amd_iommu_proto.h" 38#include "amd_iommu_proto.h"
38#include "amd_iommu_types.h" 39#include "amd_iommu_types.h"
@@ -1575,6 +1576,23 @@ static void __init free_on_init_error(void)
1575#endif 1576#endif
1576} 1577}
1577 1578
1579static bool __init check_ioapic_information(void)
1580{
1581 int idx;
1582
1583 for (idx = 0; idx < nr_ioapics; idx++) {
1584 int id = mpc_ioapic_id(idx);
1585
1586 if (get_ioapic_devid(id) < 0) {
1587 pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id);
1588 pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n");
1589 return false;
1590 }
1591 }
1592
1593 return true;
1594}
1595
1578/* 1596/*
1579 * This is the hardware init function for AMD IOMMU in the system. 1597 * This is the hardware init function for AMD IOMMU in the system.
1580 * This function is called either from amd_iommu_init or from the interrupt 1598 * This function is called either from amd_iommu_init or from the interrupt
@@ -1661,9 +1679,6 @@ static int __init early_amd_iommu_init(void)
1661 if (amd_iommu_pd_alloc_bitmap == NULL) 1679 if (amd_iommu_pd_alloc_bitmap == NULL)
1662 goto out; 1680 goto out;
1663 1681
1664 /* init the device table */
1665 init_device_table();
1666
1667 /* 1682 /*
1668 * let all alias entries point to itself 1683 * let all alias entries point to itself
1669 */ 1684 */
@@ -1686,6 +1701,9 @@ static int __init early_amd_iommu_init(void)
1686 if (ret) 1701 if (ret)
1687 goto out; 1702 goto out;
1688 1703
1704 if (amd_iommu_irq_remap)
1705 amd_iommu_irq_remap = check_ioapic_information();
1706
1689 if (amd_iommu_irq_remap) { 1707 if (amd_iommu_irq_remap) {
1690 /* 1708 /*
1691 * Interrupt remapping enabled, create kmem_cache for the 1709 * Interrupt remapping enabled, create kmem_cache for the
@@ -1709,6 +1727,9 @@ static int __init early_amd_iommu_init(void)
1709 if (ret) 1727 if (ret)
1710 goto out; 1728 goto out;
1711 1729
1730 /* init the device table */
1731 init_device_table();
1732
1712out: 1733out:
1713 /* Don't leak any ACPI memory */ 1734 /* Don't leak any ACPI memory */
1714 early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); 1735 early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size);