diff options
Diffstat (limited to 'arch/i386/pci')
-rw-r--r-- | arch/i386/pci/common.c | 5 | ||||
-rw-r--r-- | arch/i386/pci/init.c | 8 | ||||
-rw-r--r-- | arch/i386/pci/mmconfig.c | 36 | ||||
-rw-r--r-- | arch/i386/pci/pci.h | 3 |
4 files changed, 38 insertions, 14 deletions
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 0a362e3aeac5..1220dd828ce3 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
@@ -237,6 +237,11 @@ char * __devinit pcibios_setup(char *str) | |||
237 | pci_probe &= ~PCI_PROBE_MMCONF; | 237 | pci_probe &= ~PCI_PROBE_MMCONF; |
238 | return NULL; | 238 | return NULL; |
239 | } | 239 | } |
240 | /* override DMI blacklist */ | ||
241 | else if (!strcmp(str, "mmconf")) { | ||
242 | pci_probe |= PCI_PROBE_MMCONF_FORCE; | ||
243 | return NULL; | ||
244 | } | ||
240 | #endif | 245 | #endif |
241 | else if (!strcmp(str, "noacpi")) { | 246 | else if (!strcmp(str, "noacpi")) { |
242 | acpi_noirq_set(); | 247 | acpi_noirq_set(); |
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c index c7650a7e0b07..51087a9d9172 100644 --- a/arch/i386/pci/init.c +++ b/arch/i386/pci/init.c | |||
@@ -14,8 +14,12 @@ static __init int pci_access_init(void) | |||
14 | #ifdef CONFIG_PCI_BIOS | 14 | #ifdef CONFIG_PCI_BIOS |
15 | pci_pcbios_init(); | 15 | pci_pcbios_init(); |
16 | #endif | 16 | #endif |
17 | if (raw_pci_ops) | 17 | /* |
18 | return 0; | 18 | * don't check for raw_pci_ops here because we want pcbios as last |
19 | * fallback, yet it's needed to run first to set pcibios_last_bus | ||
20 | * in case legacy PCI probing is used. otherwise detecting peer busses | ||
21 | * fails. | ||
22 | */ | ||
19 | #ifdef CONFIG_PCI_DIRECT | 23 | #ifdef CONFIG_PCI_DIRECT |
20 | pci_direct_init(); | 24 | pci_direct_init(); |
21 | #endif | 25 | #endif |
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; |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index bf4e79335388..49a849b3a241 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
@@ -16,7 +16,8 @@ | |||
16 | #define PCI_PROBE_CONF1 0x0002 | 16 | #define PCI_PROBE_CONF1 0x0002 |
17 | #define PCI_PROBE_CONF2 0x0004 | 17 | #define PCI_PROBE_CONF2 0x0004 |
18 | #define PCI_PROBE_MMCONF 0x0008 | 18 | #define PCI_PROBE_MMCONF 0x0008 |
19 | #define PCI_PROBE_MASK 0x000f | 19 | #define PCI_PROBE_MMCONF_FORCE 0x0010 |
20 | #define PCI_PROBE_MASK 0x00ff | ||
20 | 21 | ||
21 | #define PCI_NO_SORT 0x0100 | 22 | #define PCI_NO_SORT 0x0100 |
22 | #define PCI_BIOS_SORT 0x0200 | 23 | #define PCI_BIOS_SORT 0x0200 |