[PATCH] x86: Disable MMCONFIG on Intel SDV using DMI blacklist
[deliverable/linux.git] / arch / i386 / pci / mmconfig.c
index f77d7f8b9bf6ca53f4536e5a1d38a1135c3e2d58..ef5a2faa7d824728d4c44cade01a2f2c023adca2 100644 (file)
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <asm/e820.h>
 #include "pci.h"
 
-#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN      (2 * 1024*1024)
+#define MMCONFIG_APER_MAX      (256 * 1024*1024)
 
 /* Assume systems with more busses have correct MCFG */
 #define MAX_CHECK_BUS 16
@@ -80,7 +83,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
        unsigned long flags;
        u32 base;
 
-       if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) {
+       if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
                *value = -1;
                return -EINVAL;
        }
@@ -176,7 +179,7 @@ static __init void unreachable_devices(void)
                                pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
                        if (addr == 0 ||
                            readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
-                               set_bit(i, fallback_slots);
+                               set_bit(i + 32*k, fallback_slots);
                                printk(KERN_NOTICE
                        "PCI: No mmconfig possible on %x:%x\n", k, i);
                        }
@@ -185,9 +188,31 @@ static __init void unreachable_devices(void)
        }
 }
 
+static int disable_mcfg(struct dmi_system_id *d)
+{
+       printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+       pci_probe &= ~PCI_PROBE_MMCONF;
+       return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+       /* Has broken MCFG table that makes the system hang when used */
+        {
+         .callback = disable_mcfg,
+         .ident = "Intel D3C5105 SDV",
+         .matches = {
+                     DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+                     DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+                     },
+         },
+         {}
+};
+
 void __init pci_mmcfg_init(void)
 {
-       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+       dmi_check_system(dmi_bad_mcfg);
+
+       if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
                return;
 
        acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -196,14 +221,6 @@ void __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return;
 
-       if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-                       pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
-                       E820_RESERVED)) {
-               printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
-               printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-               return;
-       }
-
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
This page took 0.040195 seconds and 5 git commands to generate.