aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@hauwei.com>2012-06-22 02:55:14 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-06-22 17:16:38 -0400
commit95c5e92f4f691bbaba40bbf3decfc8e13b6ea897 (patch)
tree0f7e180f2e7b743cb2260e5cf6f88b351cf760e0 /arch/x86/pci
parent9cf0105da5a315677d8f91043fb87fdade0d8b39 (diff)
x86/PCI: prepare pci_mmcfg_check_reserved() to be called at runtime
Prepare function pci_mmcfg_check_reserved() to be called at runtime for PCI host bridge hot-plugging Reviewed-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jiang Liu <liuj97@gmail.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'arch/x86/pci')
-rw-r--r--arch/x86/pci/mmconfig-shared.c104
1 files changed, 68 insertions, 36 deletions
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 0ac97d54bcac..15a7abf5139c 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -27,6 +27,7 @@
27 27
28/* Indicate if the mmcfg resources have been placed into the resource table. */ 28/* Indicate if the mmcfg resources have been placed into the resource table. */
29static int __initdata pci_mmcfg_resources_inserted; 29static int __initdata pci_mmcfg_resources_inserted;
30static bool pci_mmcfg_running_state;
30static DEFINE_MUTEX(pci_mmcfg_lock); 31static DEFINE_MUTEX(pci_mmcfg_lock);
31 32
32LIST_HEAD(pci_mmcfg_list); 33LIST_HEAD(pci_mmcfg_list);
@@ -375,14 +376,15 @@ static void __init pci_mmcfg_insert_resources(void)
375 struct pci_mmcfg_region *cfg; 376 struct pci_mmcfg_region *cfg;
376 377
377 list_for_each_entry(cfg, &pci_mmcfg_list, list) 378 list_for_each_entry(cfg, &pci_mmcfg_list, list)
378 insert_resource(&iomem_resource, &cfg->res); 379 if (!cfg->res.parent)
380 insert_resource(&iomem_resource, &cfg->res);
379 381
380 /* Mark that the resources have been inserted. */ 382 /* Mark that the resources have been inserted. */
381 pci_mmcfg_resources_inserted = 1; 383 pci_mmcfg_resources_inserted = 1;
382} 384}
383 385
384static acpi_status __init check_mcfg_resource(struct acpi_resource *res, 386static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
385 void *data) 387 void *data)
386{ 388{
387 struct resource *mcfg_res = data; 389 struct resource *mcfg_res = data;
388 struct acpi_resource_address64 address; 390 struct acpi_resource_address64 address;
@@ -418,8 +420,8 @@ static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
418 return AE_OK; 420 return AE_OK;
419} 421}
420 422
421static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, 423static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl,
422 void *context, void **rv) 424 void *context, void **rv)
423{ 425{
424 struct resource *mcfg_res = context; 426 struct resource *mcfg_res = context;
425 427
@@ -432,7 +434,7 @@ static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
432 return AE_OK; 434 return AE_OK;
433} 435}
434 436
435static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) 437static int __devinit is_acpi_reserved(u64 start, u64 end, unsigned not_used)
436{ 438{
437 struct resource mcfg_res; 439 struct resource mcfg_res;
438 440
@@ -451,13 +453,15 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
451 453
452typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); 454typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
453 455
454static int __init is_mmconf_reserved(check_reserved_t is_reserved, 456static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
455 struct pci_mmcfg_region *cfg, int with_e820) 457 struct pci_mmcfg_region *cfg,
458 struct device *dev, int with_e820)
456{ 459{
457 u64 addr = cfg->res.start; 460 u64 addr = cfg->res.start;
458 u64 size = resource_size(&cfg->res); 461 u64 size = resource_size(&cfg->res);
459 u64 old_size = size; 462 u64 old_size = size;
460 int valid = 0, num_buses; 463 int num_buses;
464 char *method = with_e820 ? "E820" : "ACPI motherboard resources";
461 465
462 while (!is_reserved(addr, addr + size, E820_RESERVED)) { 466 while (!is_reserved(addr, addr + size, E820_RESERVED)) {
463 size >>= 1; 467 size >>= 1;
@@ -465,49 +469,75 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
465 break; 469 break;
466 } 470 }
467 471
468 if (size >= (16UL<<20) || size == old_size) { 472 if (size < (16UL<<20) && size != old_size)
469 printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n", 473 return 0;
470 &cfg->res, 474
471 with_e820 ? "E820" : "ACPI motherboard resources"); 475 if (dev)
472 valid = 1; 476 dev_info(dev, "MMCONFIG at %pR reserved in %s\n",
473 477 &cfg->res, method);
474 if (old_size != size) { 478 else
475 /* update end_bus */ 479 printk(KERN_INFO PREFIX
476 cfg->end_bus = cfg->start_bus + ((size>>20) - 1); 480 "MMCONFIG at %pR reserved in %s\n",
477 num_buses = cfg->end_bus - cfg->start_bus + 1; 481 &cfg->res, method);
478 cfg->res.end = cfg->res.start + 482
479 PCI_MMCFG_BUS_OFFSET(num_buses) - 1; 483 if (old_size != size) {
480 snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN, 484 /* update end_bus */
481 "PCI MMCONFIG %04x [bus %02x-%02x]", 485 cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
482 cfg->segment, cfg->start_bus, cfg->end_bus); 486 num_buses = cfg->end_bus - cfg->start_bus + 1;
487 cfg->res.end = cfg->res.start +
488 PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
489 snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
490 "PCI MMCONFIG %04x [bus %02x-%02x]",
491 cfg->segment, cfg->start_bus, cfg->end_bus);
492
493 if (dev)
494 dev_info(dev,
495 "MMCONFIG "
496 "at %pR (base %#lx) (size reduced!)\n",
497 &cfg->res, (unsigned long) cfg->address);
498 else
483 printk(KERN_INFO PREFIX 499 printk(KERN_INFO PREFIX
484 "MMCONFIG for %04x [bus%02x-%02x] " 500 "MMCONFIG for %04x [bus%02x-%02x] "
485 "at %pR (base %#lx) (size reduced!)\n", 501 "at %pR (base %#lx) (size reduced!)\n",
486 cfg->segment, cfg->start_bus, cfg->end_bus, 502 cfg->segment, cfg->start_bus, cfg->end_bus,
487 &cfg->res, (unsigned long) cfg->address); 503 &cfg->res, (unsigned long) cfg->address);
488 }
489 } 504 }
490 505
491 return valid; 506 return 1;
492} 507}
493 508
494static int __devinit pci_mmcfg_check_reserved(struct pci_mmcfg_region *cfg, 509static int __ref pci_mmcfg_check_reserved(struct device *dev,
495 int early) 510 struct pci_mmcfg_region *cfg, int early)
496{ 511{
497 if (!early && !acpi_disabled) { 512 if (!early && !acpi_disabled) {
498 if (is_mmconf_reserved(is_acpi_reserved, cfg, 0)) 513 if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0))
499 return 1; 514 return 1;
515
516 if (dev)
517 dev_info(dev, FW_INFO
518 "MMCONFIG at %pR not reserved in "
519 "ACPI motherboard resources\n",
520 &cfg->res);
500 else 521 else
501 printk(KERN_ERR FW_BUG PREFIX 522 printk(KERN_INFO FW_INFO PREFIX
502 "MMCONFIG at %pR not reserved in " 523 "MMCONFIG at %pR not reserved in "
503 "ACPI motherboard resources\n", 524 "ACPI motherboard resources\n",
504 &cfg->res); 525 &cfg->res);
505 } 526 }
506 527
528 /*
529 * e820_all_mapped() is marked as __init.
530 * All entries from ACPI MCFG table have been checked at boot time.
531 * For MCFG information constructed from hotpluggable host bridge's
532 * _CBA method, just assume it's reserved.
533 */
534 if (pci_mmcfg_running_state)
535 return 1;
536
507 /* Don't try to do this check unless configuration 537 /* Don't try to do this check unless configuration
508 type 1 is available. how about type 2 ?*/ 538 type 1 is available. how about type 2 ?*/
509 if (raw_pci_ops) 539 if (raw_pci_ops)
510 return is_mmconf_reserved(e820_all_mapped, cfg, 1); 540 return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1);
511 541
512 return 0; 542 return 0;
513} 543}
@@ -517,7 +547,7 @@ static void __init pci_mmcfg_reject_broken(int early)
517 struct pci_mmcfg_region *cfg; 547 struct pci_mmcfg_region *cfg;
518 548
519 list_for_each_entry(cfg, &pci_mmcfg_list, list) { 549 list_for_each_entry(cfg, &pci_mmcfg_list, list) {
520 if (pci_mmcfg_check_reserved(cfg, early) == 0) { 550 if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) {
521 printk(KERN_INFO PREFIX "not using MMCONFIG\n"); 551 printk(KERN_INFO PREFIX "not using MMCONFIG\n");
522 free_all_mmcfg(); 552 free_all_mmcfg();
523 return; 553 return;
@@ -656,6 +686,8 @@ void __init pci_mmcfg_late_init(void)
656 686
657static int __init pci_mmcfg_late_insert_resources(void) 687static int __init pci_mmcfg_late_insert_resources(void)
658{ 688{
689 pci_mmcfg_running_state = true;
690
659 /* 691 /*
660 * If resources are already inserted or we are not using MMCONFIG, 692 * If resources are already inserted or we are not using MMCONFIG,
661 * don't insert the resources. 693 * don't insert the resources.