aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-22 15:55:20 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-22 15:55:20 -0500
commit3338db0057ed9f554050bd06863731c515d79672 (patch)
tree6837d33aa7deba306990e8c89413a38d44f77368 /drivers/acpi/pci_root.c
parentc27b2c33b6215eeb3d5c290ac889ab6d543f6207 (diff)
ACPI / hotplug: Make ACPI PCI root hotplug use common hotplug code
Rework the common ACPI device hotplug code so that it is suitable for PCI host bridge hotplug and switch the PCI host bridge scan handler to using the common hotplug code. This allows quite a few lines of code that are not necessary any more to be dropped from the PCI host bridge scan handler and removes arbitrary differences in behavior between PCI host bridge hotplug and ACPI-based hotplug of other components, like CPUs and memory. Also acpi_device_hotplug() can be static now. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r--drivers/acpi/pci_root.c125
1 files changed, 11 insertions, 114 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index ca05064f3ff7..2dd11e0bac24 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -51,6 +51,12 @@ static int acpi_pci_root_add(struct acpi_device *device,
51 const struct acpi_device_id *not_used); 51 const struct acpi_device_id *not_used);
52static void acpi_pci_root_remove(struct acpi_device *device); 52static void acpi_pci_root_remove(struct acpi_device *device);
53 53
54static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
55{
56 acpiphp_check_host_bridge(adev->handle);
57 return 0;
58}
59
54#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ 60#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \
55 | OSC_PCI_ASPM_SUPPORT \ 61 | OSC_PCI_ASPM_SUPPORT \
56 | OSC_PCI_CLOCK_PM_SUPPORT \ 62 | OSC_PCI_CLOCK_PM_SUPPORT \
@@ -66,7 +72,8 @@ static struct acpi_scan_handler pci_root_handler = {
66 .attach = acpi_pci_root_add, 72 .attach = acpi_pci_root_add,
67 .detach = acpi_pci_root_remove, 73 .detach = acpi_pci_root_remove,
68 .hotplug = { 74 .hotplug = {
69 .ignore = true, 75 .enabled = true,
76 .scan_dependent = acpi_pci_root_scan_dependent,
70 }, 77 },
71}; 78};
72 79
@@ -624,119 +631,9 @@ static void acpi_pci_root_remove(struct acpi_device *device)
624void __init acpi_pci_root_init(void) 631void __init acpi_pci_root_init(void)
625{ 632{
626 acpi_hest_init(); 633 acpi_hest_init();
627 634 if (acpi_pci_disabled)
628 if (!acpi_pci_disabled) {
629 pci_acpi_crs_quirks();
630 acpi_scan_add_handler(&pci_root_handler);
631 }
632}
633/* Support root bridge hotplug */
634
635static void handle_root_bridge_insertion(acpi_handle handle)
636{
637 struct acpi_device *device = NULL;
638
639 acpi_bus_get_device(handle, &device);
640 if (acpi_device_enumerated(device)) {
641 dev_printk(KERN_DEBUG, &device->dev,
642 "acpi device already exists; ignoring notify\n");
643 return;
644 }
645
646 if (acpi_bus_scan(handle))
647 acpi_handle_err(handle, "cannot add bridge to acpi list\n");
648}
649
650static void hotplug_event_root(void *data, u32 type)
651{
652 acpi_handle handle = data;
653 struct acpi_pci_root *root;
654
655 acpi_scan_lock_acquire();
656
657 root = acpi_pci_find_root(handle);
658
659 switch (type) {
660 case ACPI_NOTIFY_BUS_CHECK:
661 /* bus enumerate */
662 acpi_handle_printk(KERN_DEBUG, handle,
663 "Bus check notify on %s\n", __func__);
664 if (root)
665 acpiphp_check_host_bridge(handle);
666 else
667 handle_root_bridge_insertion(handle);
668
669 break;
670
671 case ACPI_NOTIFY_DEVICE_CHECK:
672 /* device check */
673 acpi_handle_printk(KERN_DEBUG, handle,
674 "Device check notify on %s\n", __func__);
675 if (!root)
676 handle_root_bridge_insertion(handle);
677 break;
678
679 case ACPI_NOTIFY_EJECT_REQUEST:
680 /* request device eject */
681 acpi_handle_printk(KERN_DEBUG, handle,
682 "Device eject notify on %s\n", __func__);
683 if (!root)
684 break;
685
686 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
687 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
688 get_device(&root->device->dev);
689
690 acpi_scan_lock_release();
691
692 acpi_device_hotplug(root->device, ACPI_NOTIFY_EJECT_REQUEST);
693 return; 635 return;
694 default:
695 acpi_handle_warn(handle,
696 "notify_handler: unknown event type 0x%x\n",
697 type);
698 break;
699 }
700
701 acpi_scan_lock_release();
702}
703
704static void handle_hotplug_event_root(acpi_handle handle, u32 type,
705 void *context)
706{
707 acpi_hotplug_execute(hotplug_event_root, handle, type);
708}
709
710static acpi_status __init
711find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
712{
713 acpi_status status;
714 int *count = (int *)context;
715
716 if (!acpi_is_root_bridge(handle))
717 return AE_OK;
718
719 (*count)++;
720
721 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
722 handle_hotplug_event_root, NULL);
723 if (ACPI_FAILURE(status))
724 acpi_handle_printk(KERN_DEBUG, handle,
725 "notify handler is not installed, exit status: %u\n",
726 (unsigned int)status);
727 else
728 acpi_handle_printk(KERN_DEBUG, handle,
729 "notify handler is installed\n");
730
731 return AE_OK;
732}
733
734void __init acpi_pci_root_hp_init(void)
735{
736 int num = 0;
737
738 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
739 ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
740 636
741 printk(KERN_DEBUG "Found %d acpi root devices\n", num); 637 pci_acpi_crs_quirks();
638 acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
742} 639}