diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 00:18:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 00:18:18 -0500 |
commit | 556f12f602ac0a18a82ca83e9f8e8547688fc633 (patch) | |
tree | d4051f6dd57968c8e8e660ad117c5bedc2aa7e8e /drivers/acpi/pci_root.c | |
parent | fffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (diff) | |
parent | 018ba0a6efada61b9bc17500101d81c3d35807c2 (diff) |
Merge tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas:
"Host bridge hotplug
- Major overhaul of ACPI host bridge add/start (Rafael Wysocki, Yinghai Lu)
- Major overhaul of PCI/ACPI binding (Rafael Wysocki, Yinghai Lu)
- Split out ACPI host bridge and ACPI PCI device hotplug (Yinghai Lu)
- Stop caching _PRT and make independent of bus numbers (Yinghai Lu)
PCI device hotplug
- Clean up cpqphp dead code (Sasha Levin)
- Disable ARI unless device and upstream bridge support it (Yijing Wang)
- Initialize all hot-added devices (not functions 0-7) (Yijing Wang)
Power management
- Don't touch ASPM if disabled (Joe Lawrence)
- Fix ASPM link state management (Myron Stowe)
Miscellaneous
- Fix PCI_EXP_FLAGS accessor (Alex Williamson)
- Disable Bus Master in pci_device_shutdown (Konstantin Khlebnikov)
- Document hotplug resource and MPS parameters (Yijing Wang)
- Add accessor for PCIe capabilities (Myron Stowe)
- Drop pciehp suspend/resume messages (Paul Bolle)
- Make pci_slot built-in only (not a module) (Jiang Liu)
- Remove unused PCI/ACPI bind ops (Jiang Liu)
- Removed used pci_root_bus (Bjorn Helgaas)"
* tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (51 commits)
PCI/ACPI: Don't cache _PRT, and don't associate them with bus numbers
PCI: Fix PCI Express Capability accessors for PCI_EXP_FLAGS
ACPI / PCI: Make pci_slot built-in only, not a module
PCI/PM: Clear state_saved during suspend
PCI: Use atomic_inc_return() rather than atomic_add_return()
PCI: Catch attempts to disable already-disabled devices
PCI: Disable Bus Master unconditionally in pci_device_shutdown()
PCI: acpiphp: Remove dead code for PCI host bridge hotplug
PCI: acpiphp: Create companion ACPI devices before creating PCI devices
PCI: Remove unused "rc" in virtfn_add_bus()
PCI: pciehp: Drop suspend/resume ENTRY messages
PCI/ASPM: Don't touch ASPM if forcibly disabled
PCI/ASPM: Deallocate upstream link state even if device is not PCIe
PCI: Document MPS parameters pci=pcie_bus_safe, pci=pcie_bus_perf, etc
PCI: Document hpiosize= and hpmemsize= resource reservation parameters
PCI: Use PCI Express Capability accessor
PCI: Introduce accessor to retrieve PCIe Capabilities Register
PCI: Put pci_dev in device tree as early as possible
PCI: Skip attaching driver in device_add()
PCI: acpiphp: Keep driver loaded even if no slots found
...
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r-- | drivers/acpi/pci_root.c | 170 |
1 files changed, 133 insertions, 37 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b3cc69c5caf1..0ac546d5e53f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -103,24 +103,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | |||
103 | } | 103 | } |
104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
105 | 105 | ||
106 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | ||
107 | { | ||
108 | struct acpi_pci_root *root; | ||
109 | acpi_handle handle = NULL; | ||
110 | |||
111 | mutex_lock(&acpi_pci_root_lock); | ||
112 | list_for_each_entry(root, &acpi_pci_roots, node) | ||
113 | if ((root->segment == (u16) seg) && | ||
114 | (root->secondary.start == (u16) bus)) { | ||
115 | handle = root->device->handle; | ||
116 | break; | ||
117 | } | ||
118 | mutex_unlock(&acpi_pci_root_lock); | ||
119 | return handle; | ||
120 | } | ||
121 | |||
122 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | ||
123 | |||
124 | /** | 106 | /** |
125 | * 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 |
126 | * @handle - the ACPI CA node in question. | 108 | * @handle - the ACPI CA node in question. |
@@ -431,7 +413,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
431 | acpi_status status; | 413 | acpi_status status; |
432 | int result; | 414 | int result; |
433 | struct acpi_pci_root *root; | 415 | struct acpi_pci_root *root; |
434 | acpi_handle handle; | ||
435 | struct acpi_pci_driver *driver; | 416 | struct acpi_pci_driver *driver; |
436 | u32 flags, base_flags; | 417 | u32 flags, base_flags; |
437 | bool is_osc_granted = false; | 418 | bool is_osc_granted = false; |
@@ -486,16 +467,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
486 | acpi_device_name(device), acpi_device_bid(device), | 467 | acpi_device_name(device), acpi_device_bid(device), |
487 | root->segment, &root->secondary); | 468 | root->segment, &root->secondary); |
488 | 469 | ||
489 | /* | ||
490 | * PCI Routing Table | ||
491 | * ----------------- | ||
492 | * Evaluate and parse _PRT, if exists. | ||
493 | */ | ||
494 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
495 | if (ACPI_SUCCESS(status)) | ||
496 | result = acpi_pci_irq_add_prt(device->handle, root->segment, | ||
497 | root->secondary.start); | ||
498 | |||
499 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); | 470 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); |
500 | 471 | ||
501 | /* | 472 | /* |
@@ -597,8 +568,10 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
597 | if (device->wakeup.flags.run_wake) | 568 | if (device->wakeup.flags.run_wake) |
598 | device_set_run_wake(root->bus->bridge, true); | 569 | device_set_run_wake(root->bus->bridge, true); |
599 | 570 | ||
600 | if (system_state != SYSTEM_BOOTING) | 571 | if (system_state != SYSTEM_BOOTING) { |
572 | pcibios_resource_survey_bus(root->bus); | ||
601 | pci_assign_unassigned_bus_resources(root->bus); | 573 | pci_assign_unassigned_bus_resources(root->bus); |
574 | } | ||
602 | 575 | ||
603 | mutex_lock(&acpi_pci_root_lock); | 576 | mutex_lock(&acpi_pci_root_lock); |
604 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 577 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
@@ -618,7 +591,6 @@ out_del_root: | |||
618 | list_del(&root->node); | 591 | list_del(&root->node); |
619 | mutex_unlock(&acpi_pci_root_lock); | 592 | mutex_unlock(&acpi_pci_root_lock); |
620 | 593 | ||
621 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
622 | end: | 594 | end: |
623 | kfree(root); | 595 | kfree(root); |
624 | return result; | 596 | return result; |
@@ -626,8 +598,6 @@ end: | |||
626 | 598 | ||
627 | static void acpi_pci_root_remove(struct acpi_device *device) | 599 | static void acpi_pci_root_remove(struct acpi_device *device) |
628 | { | 600 | { |
629 | acpi_status status; | ||
630 | acpi_handle handle; | ||
631 | struct acpi_pci_root *root = acpi_driver_data(device); | 601 | struct acpi_pci_root *root = acpi_driver_data(device); |
632 | struct acpi_pci_driver *driver; | 602 | struct acpi_pci_driver *driver; |
633 | 603 | ||
@@ -642,10 +612,6 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
642 | device_set_run_wake(root->bus->bridge, false); | 612 | device_set_run_wake(root->bus->bridge, false); |
643 | pci_acpi_remove_bus_pm_notifier(device); | 613 | pci_acpi_remove_bus_pm_notifier(device); |
644 | 614 | ||
645 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
646 | if (ACPI_SUCCESS(status)) | ||
647 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
648 | |||
649 | pci_remove_root_bus(root->bus); | 615 | pci_remove_root_bus(root->bus); |
650 | 616 | ||
651 | mutex_lock(&acpi_pci_root_lock); | 617 | mutex_lock(&acpi_pci_root_lock); |
@@ -663,3 +629,133 @@ void __init acpi_pci_root_init(void) | |||
663 | acpi_scan_add_handler(&pci_root_handler); | 629 | acpi_scan_add_handler(&pci_root_handler); |
664 | } | 630 | } |
665 | } | 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 | struct acpi_eject_event *ej_event; | ||
650 | |||
651 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
652 | if (!ej_event) { | ||
653 | /* Inform firmware the hot-remove operation has error */ | ||
654 | (void) acpi_evaluate_hotplug_ost(device->handle, | ||
655 | ACPI_NOTIFY_EJECT_REQUEST, | ||
656 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
657 | NULL); | ||
658 | return; | ||
659 | } | ||
660 | |||
661 | ej_event->device = device; | ||
662 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
663 | |||
664 | acpi_bus_hot_remove_device(ej_event); | ||
665 | } | ||
666 | |||
667 | static void _handle_hotplug_event_root(struct work_struct *work) | ||
668 | { | ||
669 | struct acpi_pci_root *root; | ||
670 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; | ||
671 | struct acpi_hp_work *hp_work; | ||
672 | acpi_handle handle; | ||
673 | u32 type; | ||
674 | |||
675 | hp_work = container_of(work, struct acpi_hp_work, work); | ||
676 | handle = hp_work->handle; | ||
677 | type = hp_work->type; | ||
678 | |||
679 | root = acpi_pci_find_root(handle); | ||
680 | |||
681 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
682 | |||
683 | switch (type) { | ||
684 | case ACPI_NOTIFY_BUS_CHECK: | ||
685 | /* bus enumerate */ | ||
686 | printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, | ||
687 | (char *)buffer.pointer); | ||
688 | if (!root) | ||
689 | handle_root_bridge_insertion(handle); | ||
690 | |||
691 | break; | ||
692 | |||
693 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
694 | /* device check */ | ||
695 | printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__, | ||
696 | (char *)buffer.pointer); | ||
697 | if (!root) | ||
698 | handle_root_bridge_insertion(handle); | ||
699 | break; | ||
700 | |||
701 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
702 | /* request device eject */ | ||
703 | printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__, | ||
704 | (char *)buffer.pointer); | ||
705 | if (root) | ||
706 | handle_root_bridge_removal(root->device); | ||
707 | break; | ||
708 | default: | ||
709 | printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n", | ||
710 | type, (char *)buffer.pointer); | ||
711 | break; | ||
712 | } | ||
713 | |||
714 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | ||
715 | kfree(buffer.pointer); | ||
716 | } | ||
717 | |||
718 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | ||
719 | void *context) | ||
720 | { | ||
721 | alloc_acpi_hp_work(handle, type, context, | ||
722 | _handle_hotplug_event_root); | ||
723 | } | ||
724 | |||
725 | static acpi_status __init | ||
726 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
727 | { | ||
728 | acpi_status status; | ||
729 | char objname[64]; | ||
730 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
731 | .pointer = objname }; | ||
732 | int *count = (int *)context; | ||
733 | |||
734 | if (!acpi_is_root_bridge(handle)) | ||
735 | return AE_OK; | ||
736 | |||
737 | (*count)++; | ||
738 | |||
739 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
740 | |||
741 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
742 | handle_hotplug_event_root, NULL); | ||
743 | if (ACPI_FAILURE(status)) | ||
744 | printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n", | ||
745 | objname, (unsigned int)status); | ||
746 | else | ||
747 | printk(KERN_DEBUG "acpi root: %s notify handler is installed\n", | ||
748 | objname); | ||
749 | |||
750 | return AE_OK; | ||
751 | } | ||
752 | |||
753 | void __init acpi_pci_root_hp_init(void) | ||
754 | { | ||
755 | int num = 0; | ||
756 | |||
757 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
758 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
759 | |||
760 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | ||
761 | } | ||