diff options
author | Yinghai Lu <Yinghai.Lu@Sun.COM> | 2008-02-15 04:30:14 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-26 17:41:03 -0400 |
commit | 05c58b8ac77639c17205f0b2a2d9eb1971dc47ad (patch) | |
tree | 89dd703cb0905f981dd322e04f55f0c7905f385b /arch/x86/pci/mmconfig-shared.c | |
parent | 0b64ad7123eb013c3de26750f2d4c356cd566231 (diff) |
x86: mmconf enable mcfg early
Patch
"x86: validate against ACPI motherboard resources"
changed the mmconf init sequence, and init MMCONF late in acpi_init.
here change it back to old sequence:
1. check hostbridge in early
2. check MCFG with e820 in early
3. if all fail, will check MCFg with acpi _CRS in acpi_init
So we can make MCONF working again when acpi=off is set if hostbridge
support that.
Signed-off-by: Yinghai Lu <yinghai.lu@sun.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Greg KH <greg@kroah.com>
Cc: Greg KH <greg@kroah.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/pci/mmconfig-shared.c')
-rw-r--r-- | arch/x86/pci/mmconfig-shared.c | 101 |
1 files changed, 55 insertions, 46 deletions
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 8f204955427c..36a4a7514b05 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -241,7 +241,7 @@ static int __init is_acpi_reserved(unsigned long start, unsigned long end) | |||
241 | return mcfg_res.flags; | 241 | return mcfg_res.flags; |
242 | } | 242 | } |
243 | 243 | ||
244 | static void __init pci_mmcfg_reject_broken(void) | 244 | static void __init pci_mmcfg_reject_broken(int type, int early) |
245 | { | 245 | { |
246 | typeof(pci_mmcfg_config[0]) *cfg; | 246 | typeof(pci_mmcfg_config[0]) *cfg; |
247 | int i; | 247 | int i; |
@@ -266,34 +266,43 @@ static void __init pci_mmcfg_reject_broken(void) | |||
266 | } | 266 | } |
267 | 267 | ||
268 | for (i = 0; i < pci_mmcfg_config_num; i++) { | 268 | for (i = 0; i < pci_mmcfg_config_num; i++) { |
269 | int valid = 0; | ||
269 | u32 size = (cfg->end_bus_number + 1) << 20; | 270 | u32 size = (cfg->end_bus_number + 1) << 20; |
270 | cfg = &pci_mmcfg_config[i]; | 271 | cfg = &pci_mmcfg_config[i]; |
271 | printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lu " | 272 | printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " |
272 | "segment %hu buses %u - %u\n", | 273 | "segment %hu buses %u - %u\n", |
273 | i, (unsigned long)cfg->address, cfg->pci_segment, | 274 | i, (unsigned long)cfg->address, cfg->pci_segment, |
274 | (unsigned int)cfg->start_bus_number, | 275 | (unsigned int)cfg->start_bus_number, |
275 | (unsigned int)cfg->end_bus_number); | 276 | (unsigned int)cfg->end_bus_number); |
276 | if (is_acpi_reserved(cfg->address, cfg->address + size - 1)) { | 277 | |
278 | if (!early && | ||
279 | is_acpi_reserved(cfg->address, cfg->address + size - 1)) { | ||
277 | printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved " | 280 | printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved " |
278 | "in ACPI motherboard resources\n", | 281 | "in ACPI motherboard resources\n", |
279 | cfg->address); | 282 | cfg->address); |
280 | } else { | 283 | valid = 1; |
284 | } | ||
285 | |||
286 | if (valid) | ||
287 | continue; | ||
288 | |||
289 | if (!early) | ||
281 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" | 290 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" |
282 | " reserved in ACPI motherboard resources\n", | 291 | " reserved in ACPI motherboard resources\n", |
283 | cfg->address); | 292 | cfg->address); |
284 | /* Don't try to do this check unless configuration | 293 | /* Don't try to do this check unless configuration |
285 | type 1 is available. */ | 294 | type 1 is available. */ |
286 | if ((pci_probe & PCI_PROBE_CONF1) && | 295 | if (type == 1 && e820_all_mapped(cfg->address, |
287 | e820_all_mapped(cfg->address, | 296 | cfg->address + size - 1, |
288 | cfg->address + size - 1, | 297 | E820_RESERVED)) { |
289 | E820_RESERVED)) | 298 | printk(KERN_NOTICE |
290 | printk(KERN_NOTICE | 299 | "PCI: MCFG area at %Lx reserved in E820\n", |
291 | "PCI: MCFG area at %Lx reserved in " | 300 | cfg->address); |
292 | "E820\n", | 301 | valid = 1; |
293 | cfg->address); | ||
294 | else | ||
295 | goto reject; | ||
296 | } | 302 | } |
303 | |||
304 | if (!valid) | ||
305 | goto reject; | ||
297 | } | 306 | } |
298 | 307 | ||
299 | return; | 308 | return; |
@@ -306,46 +315,31 @@ reject: | |||
306 | pci_mmcfg_config_num = 0; | 315 | pci_mmcfg_config_num = 0; |
307 | } | 316 | } |
308 | 317 | ||
309 | void __init pci_mmcfg_early_init(int type) | 318 | static int __initdata known_bridge; |
310 | { | ||
311 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | ||
312 | return; | ||
313 | |||
314 | /* If type 1 access is available, no need to enable MMCONFIG yet, we can | ||
315 | defer until later when the ACPI interpreter is available to better | ||
316 | validate things. */ | ||
317 | if (type == 1) | ||
318 | return; | ||
319 | |||
320 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
321 | |||
322 | if ((pci_mmcfg_config_num == 0) || | ||
323 | (pci_mmcfg_config == NULL) || | ||
324 | (pci_mmcfg_config[0].address == 0)) | ||
325 | return; | ||
326 | 319 | ||
327 | if (pci_mmcfg_arch_init()) | 320 | void __init __pci_mmcfg_init(int type, int early) |
328 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | ||
329 | } | ||
330 | |||
331 | void __init pci_mmcfg_late_init(void) | ||
332 | { | 321 | { |
333 | int known_bridge = 0; | ||
334 | |||
335 | /* MMCONFIG disabled */ | 322 | /* MMCONFIG disabled */ |
336 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 323 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
337 | return; | 324 | return; |
338 | 325 | ||
339 | /* MMCONFIG already enabled */ | 326 | /* MMCONFIG already enabled */ |
340 | if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF)) | 327 | if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF)) |
341 | return; | 328 | return; |
342 | 329 | ||
343 | if ((pci_probe & PCI_PROBE_CONF1) && pci_mmcfg_check_hostbridge()) | 330 | /* for late to exit */ |
344 | known_bridge = 1; | 331 | if (known_bridge) |
345 | else | 332 | return; |
346 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
347 | 333 | ||
348 | pci_mmcfg_reject_broken(); | 334 | if (early && type == 1) { |
335 | if (pci_mmcfg_check_hostbridge()) | ||
336 | known_bridge = 1; | ||
337 | } | ||
338 | |||
339 | if (!known_bridge) { | ||
340 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
341 | pci_mmcfg_reject_broken(type, early); | ||
342 | } | ||
349 | 343 | ||
350 | if ((pci_mmcfg_config_num == 0) || | 344 | if ((pci_mmcfg_config_num == 0) || |
351 | (pci_mmcfg_config == NULL) || | 345 | (pci_mmcfg_config == NULL) || |
@@ -365,6 +359,21 @@ void __init pci_mmcfg_late_init(void) | |||
365 | } | 359 | } |
366 | } | 360 | } |
367 | 361 | ||
362 | void __init pci_mmcfg_early_init(int type) | ||
363 | { | ||
364 | __pci_mmcfg_init(type, 1); | ||
365 | } | ||
366 | |||
367 | void __init pci_mmcfg_late_init(void) | ||
368 | { | ||
369 | int type = 0; | ||
370 | |||
371 | if (pci_probe & PCI_PROBE_CONF1) | ||
372 | type = 1; | ||
373 | |||
374 | __pci_mmcfg_init(type, 0); | ||
375 | } | ||
376 | |||
368 | static int __init pci_mmcfg_late_insert_resources(void) | 377 | static int __init pci_mmcfg_late_insert_resources(void) |
369 | { | 378 | { |
370 | /* | 379 | /* |