diff options
Diffstat (limited to 'arch/i386/pci/mmconfig.c')
-rw-r--r-- | arch/i386/pci/mmconfig.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index e545b0992c48..ef5a2faa7d82 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <linux/dmi.h> | ||
15 | #include <asm/e820.h> | 16 | #include <asm/e820.h> |
16 | #include "pci.h" | 17 | #include "pci.h" |
17 | 18 | ||
@@ -178,7 +179,7 @@ static __init void unreachable_devices(void) | |||
178 | pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0)); | 179 | pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0)); |
179 | if (addr == 0 || | 180 | if (addr == 0 || |
180 | readl((u32 __iomem *)mmcfg_virt_addr) != val1) { | 181 | readl((u32 __iomem *)mmcfg_virt_addr) != val1) { |
181 | set_bit(i, fallback_slots); | 182 | set_bit(i + 32*k, fallback_slots); |
182 | printk(KERN_NOTICE | 183 | printk(KERN_NOTICE |
183 | "PCI: No mmconfig possible on %x:%x\n", k, i); | 184 | "PCI: No mmconfig possible on %x:%x\n", k, i); |
184 | } | 185 | } |
@@ -187,9 +188,31 @@ static __init void unreachable_devices(void) | |||
187 | } | 188 | } |
188 | } | 189 | } |
189 | 190 | ||
191 | static int disable_mcfg(struct dmi_system_id *d) | ||
192 | { | ||
193 | printk("PCI: %s detected. Disabling MCFG.\n", d->ident); | ||
194 | pci_probe &= ~PCI_PROBE_MMCONF; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static struct dmi_system_id __initdata dmi_bad_mcfg[] = { | ||
199 | /* Has broken MCFG table that makes the system hang when used */ | ||
200 | { | ||
201 | .callback = disable_mcfg, | ||
202 | .ident = "Intel D3C5105 SDV", | ||
203 | .matches = { | ||
204 | DMI_MATCH(DMI_BIOS_VENDOR, "Intel"), | ||
205 | DMI_MATCH(DMI_BOARD_NAME, "D26928"), | ||
206 | }, | ||
207 | }, | ||
208 | {} | ||
209 | }; | ||
210 | |||
190 | void __init pci_mmcfg_init(void) | 211 | void __init pci_mmcfg_init(void) |
191 | { | 212 | { |
192 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 213 | dmi_check_system(dmi_bad_mcfg); |
214 | |||
215 | if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0) | ||
193 | return; | 216 | return; |
194 | 217 | ||
195 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | 218 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); |
@@ -198,15 +221,6 @@ void __init pci_mmcfg_init(void) | |||
198 | (pci_mmcfg_config[0].base_address == 0)) | 221 | (pci_mmcfg_config[0].base_address == 0)) |
199 | return; | 222 | return; |
200 | 223 | ||
201 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
202 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, | ||
203 | E820_RESERVED)) { | ||
204 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", | ||
205 | pci_mmcfg_config[0].base_address); | ||
206 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); | 224 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); |
211 | raw_pci_ops = &pci_mmcfg; | 225 | raw_pci_ops = &pci_mmcfg; |
212 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 226 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |