aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/acpi/internal.h2
-rw-r--r--drivers/acpi/pci_root.c125
-rw-r--r--drivers/acpi/scan.c42
-rw-r--r--include/acpi/acpi_bus.h2
4 files changed, 37 insertions, 134 deletions
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index a0d42cf5b0c5..f4aa467c407e 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -28,7 +28,6 @@ int init_acpi_device_notify(void);
28int acpi_scan_init(void); 28int acpi_scan_init(void);
29void acpi_pci_root_init(void); 29void acpi_pci_root_init(void);
30void acpi_pci_link_init(void); 30void acpi_pci_link_init(void);
31void acpi_pci_root_hp_init(void);
32void acpi_processor_init(void); 31void acpi_processor_init(void);
33void acpi_platform_init(void); 32void acpi_platform_init(void);
34int acpi_sysfs_init(void); 33int acpi_sysfs_init(void);
@@ -89,7 +88,6 @@ void acpi_device_add_finalize(struct acpi_device *device);
89void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); 88void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
90int acpi_bind_one(struct device *dev, acpi_handle handle); 89int acpi_bind_one(struct device *dev, acpi_handle handle);
91int acpi_unbind_one(struct device *dev); 90int acpi_unbind_one(struct device *dev);
92void acpi_device_hotplug(void *data, u32 ost_src);
93bool acpi_device_is_present(struct acpi_device *adev); 91bool acpi_device_is_present(struct acpi_device *adev);
94 92
95/* -------------------------------------------------------------------------- 93/* --------------------------------------------------------------------------
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}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index dd0ff9de9277..18865c86c463 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -283,17 +283,6 @@ static int acpi_scan_device_check(struct acpi_device *adev)
283{ 283{
284 int error; 284 int error;
285 285
286 /*
287 * This function is only called for device objects for which matching
288 * scan handlers exist. The only situation in which the scan handler is
289 * not attached to this device object yet is when the device has just
290 * appeared (either it wasn't present at all before or it was removed
291 * and then added again).
292 */
293 if (adev->handler) {
294 dev_warn(&adev->dev, "Already enumerated\n");
295 return -EBUSY;
296 }
297 error = acpi_bus_scan(adev->handle); 286 error = acpi_bus_scan(adev->handle);
298 if (error) { 287 if (error) {
299 dev_warn(&adev->dev, "Namespace scan failure\n"); 288 dev_warn(&adev->dev, "Namespace scan failure\n");
@@ -309,10 +298,11 @@ static int acpi_scan_device_check(struct acpi_device *adev)
309 return 0; 298 return 0;
310} 299}
311 300
312void acpi_device_hotplug(void *data, u32 src) 301static void acpi_device_hotplug(void *data, u32 src)
313{ 302{
314 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; 303 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
315 struct acpi_device *adev = data; 304 struct acpi_device *adev = data;
305 struct acpi_scan_handler *handler;
316 int error; 306 int error;
317 307
318 lock_device_hotplug(); 308 lock_device_hotplug();
@@ -326,12 +316,32 @@ void acpi_device_hotplug(void *data, u32 src)
326 if (adev->handle == INVALID_ACPI_HANDLE) 316 if (adev->handle == INVALID_ACPI_HANDLE)
327 goto out; 317 goto out;
328 318
319 handler = adev->handler;
320
329 switch (src) { 321 switch (src) {
330 case ACPI_NOTIFY_BUS_CHECK: 322 case ACPI_NOTIFY_BUS_CHECK:
331 error = acpi_bus_scan(adev->handle); 323 if (handler) {
324 error = handler->hotplug.scan_dependent ?
325 handler->hotplug.scan_dependent(adev) :
326 acpi_bus_scan(adev->handle);
327 } else {
328 error = acpi_scan_device_check(adev);
329 }
332 break; 330 break;
333 case ACPI_NOTIFY_DEVICE_CHECK: 331 case ACPI_NOTIFY_DEVICE_CHECK:
334 error = acpi_scan_device_check(adev); 332 /*
333 * This code is only run for device objects for which matching
334 * scan handlers exist. The only situation in which the scan
335 * handler is not attached to this device object yet is when the
336 * device has just appeared (either it wasn't present at all
337 * before or it was removed and then added again).
338 */
339 if (adev->handler) {
340 dev_warn(&adev->dev, "Already enumerated\n");
341 error = -EBUSY;
342 } else {
343 error = acpi_scan_device_check(adev);
344 }
335 break; 345 break;
336 case ACPI_NOTIFY_EJECT_REQUEST: 346 case ACPI_NOTIFY_EJECT_REQUEST:
337 case ACPI_OST_EC_OSPM_EJECT: 347 case ACPI_OST_EC_OSPM_EJECT:
@@ -1805,7 +1815,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type)
1805 */ 1815 */
1806 list_for_each_entry(hwid, &pnp.ids, list) { 1816 list_for_each_entry(hwid, &pnp.ids, list) {
1807 handler = acpi_scan_match_handler(hwid->id, NULL); 1817 handler = acpi_scan_match_handler(hwid->id, NULL);
1808 if (handler && !handler->hotplug.ignore) { 1818 if (handler) {
1809 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 1819 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
1810 acpi_hotplug_notify_cb, handler); 1820 acpi_hotplug_notify_cb, handler);
1811 break; 1821 break;
@@ -2083,8 +2093,6 @@ int __init acpi_scan_init(void)
2083 2093
2084 acpi_update_all_gpes(); 2094 acpi_update_all_gpes();
2085 2095
2086 acpi_pci_root_hp_init();
2087
2088 out: 2096 out:
2089 mutex_unlock(&acpi_scan_lock); 2097 mutex_unlock(&acpi_scan_lock);
2090 return result; 2098 return result;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index e748dbfca9d5..2359c69f1680 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -100,8 +100,8 @@ enum acpi_hotplug_mode {
100struct acpi_hotplug_profile { 100struct acpi_hotplug_profile {
101 struct kobject kobj; 101 struct kobject kobj;
102 bool enabled:1; 102 bool enabled:1;
103 bool ignore:1;
104 enum acpi_hotplug_mode mode; 103 enum acpi_hotplug_mode mode;
104 int (*scan_dependent)(struct acpi_device *adev);
105}; 105};
106 106
107static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( 107static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile(