diff options
Diffstat (limited to 'drivers/acpi/pci_root.c')
| -rw-r--r-- | drivers/acpi/pci_root.c | 268 |
1 files changed, 159 insertions, 109 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7928d4dc7056..5ff173066127 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -45,9 +45,9 @@ | |||
| 45 | ACPI_MODULE_NAME("pci_root"); | 45 | ACPI_MODULE_NAME("pci_root"); |
| 46 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" | 46 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" |
| 47 | #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" | 47 | #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" |
| 48 | static int acpi_pci_root_add(struct acpi_device *device); | 48 | static int acpi_pci_root_add(struct acpi_device *device, |
| 49 | static int acpi_pci_root_remove(struct acpi_device *device, int type); | 49 | const struct acpi_device_id *not_used); |
| 50 | static int acpi_pci_root_start(struct acpi_device *device); | 50 | static void acpi_pci_root_remove(struct acpi_device *device); |
| 51 | 51 | ||
| 52 | #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | 52 | #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ |
| 53 | | OSC_ACTIVE_STATE_PWR_SUPPORT \ | 53 | | OSC_ACTIVE_STATE_PWR_SUPPORT \ |
| @@ -58,17 +58,11 @@ static const struct acpi_device_id root_device_ids[] = { | |||
| 58 | {"PNP0A03", 0}, | 58 | {"PNP0A03", 0}, |
| 59 | {"", 0}, | 59 | {"", 0}, |
| 60 | }; | 60 | }; |
| 61 | MODULE_DEVICE_TABLE(acpi, root_device_ids); | ||
| 62 | 61 | ||
| 63 | static struct acpi_driver acpi_pci_root_driver = { | 62 | static struct acpi_scan_handler pci_root_handler = { |
| 64 | .name = "pci_root", | ||
| 65 | .class = ACPI_PCI_ROOT_CLASS, | ||
| 66 | .ids = root_device_ids, | 63 | .ids = root_device_ids, |
| 67 | .ops = { | 64 | .attach = acpi_pci_root_add, |
| 68 | .add = acpi_pci_root_add, | 65 | .detach = acpi_pci_root_remove, |
| 69 | .remove = acpi_pci_root_remove, | ||
| 70 | .start = acpi_pci_root_start, | ||
| 71 | }, | ||
| 72 | }; | 66 | }; |
| 73 | 67 | ||
| 74 | /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ | 68 | /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ |
| @@ -109,24 +103,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | |||
| 109 | } | 103 | } |
| 110 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
| 111 | 105 | ||
| 112 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | ||
| 113 | { | ||
| 114 | struct acpi_pci_root *root; | ||
| 115 | acpi_handle handle = NULL; | ||
| 116 | |||
| 117 | mutex_lock(&acpi_pci_root_lock); | ||
| 118 | list_for_each_entry(root, &acpi_pci_roots, node) | ||
| 119 | if ((root->segment == (u16) seg) && | ||
| 120 | (root->secondary.start == (u16) bus)) { | ||
| 121 | handle = root->device->handle; | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | mutex_unlock(&acpi_pci_root_lock); | ||
| 125 | return handle; | ||
| 126 | } | ||
| 127 | |||
| 128 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | ||
| 129 | |||
| 130 | /** | 106 | /** |
| 131 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | 107 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge |
| 132 | * @handle - the ACPI CA node in question. | 108 | * @handle - the ACPI CA node in question. |
| @@ -188,21 +164,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, | |||
| 188 | return AE_OK; | 164 | return AE_OK; |
| 189 | } | 165 | } |
| 190 | 166 | ||
| 191 | static void acpi_pci_bridge_scan(struct acpi_device *device) | ||
| 192 | { | ||
| 193 | int status; | ||
| 194 | struct acpi_device *child = NULL; | ||
| 195 | |||
| 196 | if (device->flags.bus_address) | ||
| 197 | if (device->parent && device->parent->ops.bind) { | ||
| 198 | status = device->parent->ops.bind(device); | ||
| 199 | if (!status) { | ||
| 200 | list_for_each_entry(child, &device->children, node) | ||
| 201 | acpi_pci_bridge_scan(child); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; | 167 | static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; |
| 207 | 168 | ||
| 208 | static acpi_status acpi_pci_run_osc(acpi_handle handle, | 169 | static acpi_status acpi_pci_run_osc(acpi_handle handle, |
| @@ -445,14 +406,14 @@ out: | |||
| 445 | } | 406 | } |
| 446 | EXPORT_SYMBOL(acpi_pci_osc_control_set); | 407 | EXPORT_SYMBOL(acpi_pci_osc_control_set); |
| 447 | 408 | ||
| 448 | static int acpi_pci_root_add(struct acpi_device *device) | 409 | static int acpi_pci_root_add(struct acpi_device *device, |
| 410 | const struct acpi_device_id *not_used) | ||
| 449 | { | 411 | { |
| 450 | unsigned long long segment, bus; | 412 | unsigned long long segment, bus; |
| 451 | acpi_status status; | 413 | acpi_status status; |
| 452 | int result; | 414 | int result; |
| 453 | struct acpi_pci_root *root; | 415 | struct acpi_pci_root *root; |
| 454 | acpi_handle handle; | 416 | struct acpi_pci_driver *driver; |
| 455 | struct acpi_device *child; | ||
| 456 | u32 flags, base_flags; | 417 | u32 flags, base_flags; |
| 457 | bool is_osc_granted = false; | 418 | bool is_osc_granted = false; |
| 458 | 419 | ||
| @@ -506,16 +467,6 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
| 506 | acpi_device_name(device), acpi_device_bid(device), | 467 | acpi_device_name(device), acpi_device_bid(device), |
| 507 | root->segment, &root->secondary); | 468 | root->segment, &root->secondary); |
| 508 | 469 | ||
| 509 | /* | ||
| 510 | * PCI Routing Table | ||
| 511 | * ----------------- | ||
| 512 | * Evaluate and parse _PRT, if exists. | ||
| 513 | */ | ||
| 514 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
| 515 | if (ACPI_SUCCESS(status)) | ||
| 516 | result = acpi_pci_irq_add_prt(device->handle, root->segment, | ||
| 517 | root->secondary.start); | ||
| 518 | |||
| 519 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); | 470 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); |
| 520 | 471 | ||
| 521 | /* | 472 | /* |
| @@ -603,21 +554,6 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
| 603 | goto out_del_root; | 554 | goto out_del_root; |
| 604 | } | 555 | } |
| 605 | 556 | ||
| 606 | /* | ||
| 607 | * Attach ACPI-PCI Context | ||
| 608 | * ----------------------- | ||
| 609 | * Thus binding the ACPI and PCI devices. | ||
| 610 | */ | ||
| 611 | result = acpi_pci_bind_root(device); | ||
| 612 | if (result) | ||
| 613 | goto out_del_root; | ||
| 614 | |||
| 615 | /* | ||
| 616 | * Scan and bind all _ADR-Based Devices | ||
| 617 | */ | ||
| 618 | list_for_each_entry(child, &device->children, node) | ||
| 619 | acpi_pci_bridge_scan(child); | ||
| 620 | |||
| 621 | /* ASPM setting */ | 557 | /* ASPM setting */ |
| 622 | if (is_osc_granted) { | 558 | if (is_osc_granted) { |
| 623 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) | 559 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) |
| @@ -632,26 +568,10 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
| 632 | if (device->wakeup.flags.run_wake) | 568 | if (device->wakeup.flags.run_wake) |
| 633 | device_set_run_wake(root->bus->bridge, true); | 569 | device_set_run_wake(root->bus->bridge, true); |
| 634 | 570 | ||
| 635 | return 0; | 571 | if (system_state != SYSTEM_BOOTING) { |
| 636 | 572 | pcibios_resource_survey_bus(root->bus); | |
| 637 | out_del_root: | ||
| 638 | mutex_lock(&acpi_pci_root_lock); | ||
| 639 | list_del(&root->node); | ||
| 640 | mutex_unlock(&acpi_pci_root_lock); | ||
| 641 | |||
| 642 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
| 643 | end: | ||
| 644 | kfree(root); | ||
| 645 | return result; | ||
| 646 | } | ||
| 647 | |||
| 648 | static int acpi_pci_root_start(struct acpi_device *device) | ||
| 649 | { | ||
| 650 | struct acpi_pci_root *root = acpi_driver_data(device); | ||
| 651 | struct acpi_pci_driver *driver; | ||
| 652 | |||
| 653 | if (system_state != SYSTEM_BOOTING) | ||
| 654 | pci_assign_unassigned_bus_resources(root->bus); | 573 | pci_assign_unassigned_bus_resources(root->bus); |
| 574 | } | ||
| 655 | 575 | ||
| 656 | mutex_lock(&acpi_pci_root_lock); | 576 | mutex_lock(&acpi_pci_root_lock); |
| 657 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 577 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
| @@ -664,14 +584,20 @@ static int acpi_pci_root_start(struct acpi_device *device) | |||
| 664 | pci_enable_bridges(root->bus); | 584 | pci_enable_bridges(root->bus); |
| 665 | 585 | ||
| 666 | pci_bus_add_devices(root->bus); | 586 | pci_bus_add_devices(root->bus); |
| 587 | return 1; | ||
| 588 | |||
| 589 | out_del_root: | ||
| 590 | mutex_lock(&acpi_pci_root_lock); | ||
| 591 | list_del(&root->node); | ||
| 592 | mutex_unlock(&acpi_pci_root_lock); | ||
| 667 | 593 | ||
| 668 | return 0; | 594 | end: |
| 595 | kfree(root); | ||
| 596 | return result; | ||
| 669 | } | 597 | } |
| 670 | 598 | ||
| 671 | static int acpi_pci_root_remove(struct acpi_device *device, int type) | 599 | static void acpi_pci_root_remove(struct acpi_device *device) |
| 672 | { | 600 | { |
| 673 | acpi_status status; | ||
| 674 | acpi_handle handle; | ||
| 675 | struct acpi_pci_root *root = acpi_driver_data(device); | 601 | struct acpi_pci_root *root = acpi_driver_data(device); |
| 676 | struct acpi_pci_driver *driver; | 602 | struct acpi_pci_driver *driver; |
| 677 | 603 | ||
| @@ -686,31 +612,155 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
| 686 | device_set_run_wake(root->bus->bridge, false); | 612 | device_set_run_wake(root->bus->bridge, false); |
| 687 | pci_acpi_remove_bus_pm_notifier(device); | 613 | pci_acpi_remove_bus_pm_notifier(device); |
| 688 | 614 | ||
| 689 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
| 690 | if (ACPI_SUCCESS(status)) | ||
| 691 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
| 692 | |||
| 693 | pci_remove_root_bus(root->bus); | 615 | pci_remove_root_bus(root->bus); |
| 694 | 616 | ||
| 695 | mutex_lock(&acpi_pci_root_lock); | 617 | mutex_lock(&acpi_pci_root_lock); |
| 696 | list_del(&root->node); | 618 | list_del(&root->node); |
| 697 | mutex_unlock(&acpi_pci_root_lock); | 619 | mutex_unlock(&acpi_pci_root_lock); |
| 698 | kfree(root); | 620 | kfree(root); |
| 699 | return 0; | ||
| 700 | } | 621 | } |
| 701 | 622 | ||
| 702 | static int __init acpi_pci_root_init(void) | 623 | void __init acpi_pci_root_init(void) |
| 703 | { | 624 | { |
| 704 | acpi_hest_init(); | 625 | acpi_hest_init(); |
| 705 | 626 | ||
| 706 | if (acpi_pci_disabled) | 627 | if (!acpi_pci_disabled) { |
| 707 | return 0; | 628 | pci_acpi_crs_quirks(); |
| 629 | acpi_scan_add_handler(&pci_root_handler); | ||
| 630 | } | ||
| 631 | } | ||
| 632 | /* Support root bridge hotplug */ | ||
| 633 | |||
| 634 | static void handle_root_bridge_insertion(acpi_handle handle) | ||
| 635 | { | ||
| 636 | struct acpi_device *device; | ||
| 637 | |||
| 638 | if (!acpi_bus_get_device(handle, &device)) { | ||
| 639 | printk(KERN_DEBUG "acpi device exists...\n"); | ||
| 640 | return; | ||
| 641 | } | ||
| 642 | |||
| 643 | if (acpi_bus_scan(handle)) | ||
| 644 | printk(KERN_ERR "cannot add bridge to acpi list\n"); | ||
| 645 | } | ||
| 646 | |||
| 647 | static void handle_root_bridge_removal(struct acpi_device *device) | ||
| 648 | { | ||
| 649 | acpi_status status; | ||
| 650 | struct acpi_eject_event *ej_event; | ||
| 651 | |||
| 652 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
| 653 | if (!ej_event) { | ||
| 654 | /* Inform firmware the hot-remove operation has error */ | ||
| 655 | (void) acpi_evaluate_hotplug_ost(device->handle, | ||
| 656 | ACPI_NOTIFY_EJECT_REQUEST, | ||
| 657 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
| 658 | NULL); | ||
| 659 | return; | ||
| 660 | } | ||
| 661 | |||
| 662 | ej_event->device = device; | ||
| 663 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
| 664 | |||
| 665 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | ||
| 666 | if (ACPI_FAILURE(status)) | ||
| 667 | kfree(ej_event); | ||
| 668 | } | ||
| 669 | |||
| 670 | static void _handle_hotplug_event_root(struct work_struct *work) | ||
| 671 | { | ||
| 672 | struct acpi_pci_root *root; | ||
| 673 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; | ||
| 674 | struct acpi_hp_work *hp_work; | ||
| 675 | acpi_handle handle; | ||
| 676 | u32 type; | ||
| 677 | |||
| 678 | hp_work = container_of(work, struct acpi_hp_work, work); | ||
| 679 | handle = hp_work->handle; | ||
| 680 | type = hp_work->type; | ||
| 708 | 681 | ||
| 709 | pci_acpi_crs_quirks(); | 682 | acpi_scan_lock_acquire(); |
| 710 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) | ||
| 711 | return -ENODEV; | ||
| 712 | 683 | ||
| 713 | return 0; | 684 | root = acpi_pci_find_root(handle); |
| 685 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
| 686 | |||
| 687 | switch (type) { | ||
| 688 | case ACPI_NOTIFY_BUS_CHECK: | ||
| 689 | /* bus enumerate */ | ||
| 690 | printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, | ||
| 691 | (char *)buffer.pointer); | ||
| 692 | if (!root) | ||
| 693 | handle_root_bridge_insertion(handle); | ||
| 694 | |||
| 695 | break; | ||
| 696 | |||
| 697 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
| 698 | /* device check */ | ||
| 699 | printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__, | ||
| 700 | (char *)buffer.pointer); | ||
| 701 | if (!root) | ||
| 702 | handle_root_bridge_insertion(handle); | ||
| 703 | break; | ||
| 704 | |||
| 705 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
| 706 | /* request device eject */ | ||
| 707 | printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__, | ||
| 708 | (char *)buffer.pointer); | ||
| 709 | if (root) | ||
| 710 | handle_root_bridge_removal(root->device); | ||
| 711 | break; | ||
| 712 | default: | ||
| 713 | printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n", | ||
| 714 | type, (char *)buffer.pointer); | ||
| 715 | break; | ||
| 716 | } | ||
| 717 | |||
| 718 | acpi_scan_lock_release(); | ||
| 719 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | ||
| 720 | kfree(buffer.pointer); | ||
| 714 | } | 721 | } |
| 715 | 722 | ||
| 716 | subsys_initcall(acpi_pci_root_init); | 723 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, |
| 724 | void *context) | ||
| 725 | { | ||
| 726 | alloc_acpi_hp_work(handle, type, context, | ||
| 727 | _handle_hotplug_event_root); | ||
| 728 | } | ||
| 729 | |||
| 730 | static acpi_status __init | ||
| 731 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
| 732 | { | ||
| 733 | acpi_status status; | ||
| 734 | char objname[64]; | ||
| 735 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
| 736 | .pointer = objname }; | ||
| 737 | int *count = (int *)context; | ||
| 738 | |||
| 739 | if (!acpi_is_root_bridge(handle)) | ||
| 740 | return AE_OK; | ||
| 741 | |||
| 742 | (*count)++; | ||
| 743 | |||
| 744 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
| 745 | |||
| 746 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
| 747 | handle_hotplug_event_root, NULL); | ||
| 748 | if (ACPI_FAILURE(status)) | ||
| 749 | printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n", | ||
| 750 | objname, (unsigned int)status); | ||
| 751 | else | ||
| 752 | printk(KERN_DEBUG "acpi root: %s notify handler is installed\n", | ||
| 753 | objname); | ||
| 754 | |||
| 755 | return AE_OK; | ||
| 756 | } | ||
| 757 | |||
| 758 | void __init acpi_pci_root_hp_init(void) | ||
| 759 | { | ||
| 760 | int num = 0; | ||
| 761 | |||
| 762 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 763 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
| 764 | |||
| 765 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | ||
| 766 | } | ||
