diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/setup.c | 32 | ||||
-rw-r--r-- | arch/i386/pci/common.c | 5 | ||||
-rw-r--r-- | arch/i386/pci/mmconfig.c | 34 | ||||
-rw-r--r-- | arch/i386/pci/pci.h | 3 |
4 files changed, 43 insertions, 31 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 345ffb7d904d..f1682206d304 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -956,6 +956,38 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) | |||
956 | return 0; | 956 | return 0; |
957 | } | 957 | } |
958 | 958 | ||
959 | /* | ||
960 | * This function checks if the entire range <start,end> is mapped with type. | ||
961 | * | ||
962 | * Note: this function only works correct if the e820 table is sorted and | ||
963 | * not-overlapping, which is the case | ||
964 | */ | ||
965 | int __init | ||
966 | e820_all_mapped(unsigned long s, unsigned long e, unsigned type) | ||
967 | { | ||
968 | u64 start = s; | ||
969 | u64 end = e; | ||
970 | int i; | ||
971 | for (i = 0; i < e820.nr_map; i++) { | ||
972 | struct e820entry *ei = &e820.map[i]; | ||
973 | if (type && ei->type != type) | ||
974 | continue; | ||
975 | /* is the region (part) in overlap with the current region ?*/ | ||
976 | if (ei->addr >= end || ei->addr + ei->size <= start) | ||
977 | continue; | ||
978 | /* if the region is at the beginning of <start,end> we move | ||
979 | * start to the end of the region since it's ok until there | ||
980 | */ | ||
981 | if (ei->addr <= start) | ||
982 | start = ei->addr + ei->size; | ||
983 | /* if start is now at or beyond end, we're done, full | ||
984 | * coverage */ | ||
985 | if (start >= end) | ||
986 | return 1; /* we're done */ | ||
987 | } | ||
988 | return 0; | ||
989 | } | ||
990 | |||
959 | /* | 991 | /* |
960 | * Find the highest page frame number we have available | 992 | * Find the highest page frame number we have available |
961 | */ | 993 | */ |
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 1220dd828ce3..0a362e3aeac5 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
@@ -237,11 +237,6 @@ 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 | } | ||
245 | #endif | 240 | #endif |
246 | else if (!strcmp(str, "noacpi")) { | 241 | else if (!strcmp(str, "noacpi")) { |
247 | acpi_noirq_set(); | 242 | acpi_noirq_set(); |
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index ef5a2faa7d82..972180f738d9 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -12,7 +12,6 @@ | |||
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> | ||
16 | #include <asm/e820.h> | 15 | #include <asm/e820.h> |
17 | #include "pci.h" | 16 | #include "pci.h" |
18 | 17 | ||
@@ -188,31 +187,9 @@ static __init void unreachable_devices(void) | |||
188 | } | 187 | } |
189 | } | 188 | } |
190 | 189 | ||
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 | |||
211 | void __init pci_mmcfg_init(void) | 190 | void __init pci_mmcfg_init(void) |
212 | { | 191 | { |
213 | dmi_check_system(dmi_bad_mcfg); | 192 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
214 | |||
215 | if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0) | ||
216 | return; | 193 | return; |
217 | 194 | ||
218 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | 195 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); |
@@ -221,6 +198,15 @@ void __init pci_mmcfg_init(void) | |||
221 | (pci_mmcfg_config[0].base_address == 0)) | 198 | (pci_mmcfg_config[0].base_address == 0)) |
222 | return; | 199 | return; |
223 | 200 | ||
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 | |||
224 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); | 210 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); |
225 | raw_pci_ops = &pci_mmcfg; | 211 | raw_pci_ops = &pci_mmcfg; |
226 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 212 | 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 49a849b3a241..bf4e79335388 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
@@ -16,8 +16,7 @@ | |||
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_MMCONF_FORCE 0x0010 | 19 | #define PCI_PROBE_MASK 0x000f |
20 | #define PCI_PROBE_MASK 0x00ff | ||
21 | 20 | ||
22 | #define PCI_NO_SORT 0x0100 | 21 | #define PCI_NO_SORT 0x0100 |
23 | #define PCI_BIOS_SORT 0x0200 | 22 | #define PCI_BIOS_SORT 0x0200 |