aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-06 11:31:37 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-06 11:31:37 -0500
commit3c2cc7ff9e2522e42468f8e81a7277be386c5ec4 (patch)
treee8a8405373896d0ff02a7d41a244fa81547c6f73
parente525506fcb67a9bbd94f01eac84af802139004eb (diff)
ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its hotplug context objects directly to ACPI namespace nodes representing hotplug devices. However, after recent changes causing struct acpi_device to be created for every namespace node representing a device (regardless of its status), that is not necessary any more. Moreover, it's vulnerable to the theoretical issue that the ACPI handle passed in the context between handle_hotplug_event() and hotplug_event_work() may become invalid in the meantime (as a result of a concurrent table unload). In principle, this issue might be addressed by adding a non-empty release handler for ACPIPHP hotplug context objects analogous to acpi_scan_drop_device(), but that would duplicate the code in that function and in acpi_device_del_work_fn(). For this reason, it's better to modify ACPIPHP to attach its device hotplug contexts to struct device objects representing hotplug devices and make it use acpi_hotplug_notify_cb() as its notify handler. At the same time, acpi_device_hotplug() can be modified to dispatch the new .hp.event() callback pointing to acpiphp_hotplug_event() from ACPI device objects associated with PCI devices or use the generic ACPI device hotplug code for device objects with matching scan handlers. This allows the existing code duplication between ACPIPHP and the ACPI core to be reduced too and makes further ACPI-based device hotplug consolidation possible. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/scan.c137
-rw-r--r--drivers/pci/hotplug/acpiphp.h9
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c168
-rw-r--r--include/acpi/acpi_bus.h25
4 files changed, 158 insertions, 181 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d64a5826ef35..984eaff235df 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -450,43 +450,61 @@ static int acpi_scan_bus_check(struct acpi_device *adev)
450 return 0; 450 return 0;
451} 451}
452 452
453static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
454{
455 switch (type) {
456 case ACPI_NOTIFY_BUS_CHECK:
457 return acpi_scan_bus_check(adev);
458 case ACPI_NOTIFY_DEVICE_CHECK:
459 return acpi_scan_device_check(adev);
460 case ACPI_NOTIFY_EJECT_REQUEST:
461 case ACPI_OST_EC_OSPM_EJECT:
462 return acpi_scan_hot_remove(adev);
463 }
464 return -EINVAL;
465}
466
453static void acpi_device_hotplug(void *data, u32 src) 467static void acpi_device_hotplug(void *data, u32 src)
454{ 468{
455 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; 469 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
456 struct acpi_device *adev = data; 470 struct acpi_device *adev = data;
457 int error; 471 int error = -ENODEV;
458 472
459 lock_device_hotplug(); 473 lock_device_hotplug();
460 mutex_lock(&acpi_scan_lock); 474 mutex_lock(&acpi_scan_lock);
461 475
462 /* 476 /*
463 * The device object's ACPI handle cannot become invalid as long as we 477 * The device object's ACPI handle cannot become invalid as long as we
464 * are holding acpi_scan_lock, but it may have become invalid before 478 * are holding acpi_scan_lock, but it might have become invalid before
465 * that lock was acquired. 479 * that lock was acquired.
466 */ 480 */
467 if (adev->handle == INVALID_ACPI_HANDLE) 481 if (adev->handle == INVALID_ACPI_HANDLE)
468 goto out; 482 goto err_out;
469 483
470 switch (src) { 484 if (adev->flags.hotplug_notify) {
471 case ACPI_NOTIFY_BUS_CHECK: 485 error = acpi_generic_hotplug_event(adev, src);
472 error = acpi_scan_bus_check(adev); 486 } else {
473 break; 487 int (*event)(struct acpi_device *, u32);
474 case ACPI_NOTIFY_DEVICE_CHECK: 488
475 error = acpi_scan_device_check(adev); 489 acpi_lock_hp_context();
476 break; 490 event = adev->hp ? adev->hp->event : NULL;
477 case ACPI_NOTIFY_EJECT_REQUEST: 491 acpi_unlock_hp_context();
478 case ACPI_OST_EC_OSPM_EJECT: 492 /*
479 error = acpi_scan_hot_remove(adev); 493 * There may be additional notify handlers for device objects
480 break; 494 * without the .event() callback, so ignore them here.
481 default: 495 */
482 error = -EINVAL; 496 if (event)
483 break; 497 error = event(adev, src);
498 else
499 goto out;
484 } 500 }
485 if (!error) 501 if (!error)
486 ost_code = ACPI_OST_SC_SUCCESS; 502 ost_code = ACPI_OST_SC_SUCCESS;
487 503
488 out: 504 err_out:
489 acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); 505 acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
506
507 out:
490 acpi_bus_put_acpi_device(adev); 508 acpi_bus_put_acpi_device(adev);
491 mutex_unlock(&acpi_scan_lock); 509 mutex_unlock(&acpi_scan_lock);
492 unlock_device_hotplug(); 510 unlock_device_hotplug();
@@ -494,8 +512,8 @@ static void acpi_device_hotplug(void *data, u32 src)
494 512
495static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) 513static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
496{ 514{
497 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
498 struct acpi_scan_handler *handler = data; 515 struct acpi_scan_handler *handler = data;
516 u32 ost_code = ACPI_OST_SC_SUCCESS;
499 struct acpi_device *adev; 517 struct acpi_device *adev;
500 acpi_status status; 518 acpi_status status;
501 519
@@ -503,26 +521,49 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
503 case ACPI_NOTIFY_BUS_CHECK: 521 case ACPI_NOTIFY_BUS_CHECK:
504 acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); 522 acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
505 break; 523 break;
524
506 case ACPI_NOTIFY_DEVICE_CHECK: 525 case ACPI_NOTIFY_DEVICE_CHECK:
507 acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); 526 acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
508 break; 527 break;
528
509 case ACPI_NOTIFY_EJECT_REQUEST: 529 case ACPI_NOTIFY_EJECT_REQUEST:
510 acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); 530 acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
511 if (!handler->hotplug.enabled) { 531 if (handler && !handler->hotplug.enabled) {
512 acpi_handle_err(handle, "Eject disabled\n"); 532 acpi_handle_err(handle, "Eject disabled\n");
513 ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; 533 ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
514 goto err_out; 534 goto out;
515 } 535 }
516 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, 536 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
517 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); 537 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
518 break; 538 break;
519 default: 539
520 /* non-hotplug event; possibly handled by other handler */ 540 case ACPI_NOTIFY_DEVICE_WAKE:
521 return; 541 return;
542
543 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
544 acpi_handle_err(handle, "Device cannot be configured due "
545 "to a frequency mismatch\n");
546 goto out;
547
548 case ACPI_NOTIFY_BUS_MODE_MISMATCH:
549 acpi_handle_err(handle, "Device cannot be configured due "
550 "to a bus mode mismatch\n");
551 goto out;
552
553 case ACPI_NOTIFY_POWER_FAULT:
554 acpi_handle_err(handle, "Device has suffered a power fault\n");
555 goto out;
556
557 default:
558 acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
559 ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
560 goto out;
522 } 561 }
562
563 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
523 adev = acpi_bus_get_acpi_device(handle); 564 adev = acpi_bus_get_acpi_device(handle);
524 if (!adev) 565 if (!adev)
525 goto err_out; 566 goto out;
526 567
527 status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); 568 status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
528 if (ACPI_SUCCESS(status)) 569 if (ACPI_SUCCESS(status))
@@ -530,10 +571,22 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
530 571
531 acpi_bus_put_acpi_device(adev); 572 acpi_bus_put_acpi_device(adev);
532 573
533 err_out: 574 out:
534 acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); 575 acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
535} 576}
536 577
578void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
579{
580 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
581 acpi_hotplug_notify_cb, data);
582}
583
584void acpi_remove_hotplug_notify_handler(acpi_handle handle)
585{
586 acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
587 acpi_hotplug_notify_cb);
588}
589
537static ssize_t real_power_state_show(struct device *dev, 590static ssize_t real_power_state_show(struct device *dev,
538 struct device_attribute *attr, char *buf) 591 struct device_attribute *attr, char *buf)
539{ 592{
@@ -1976,33 +2029,21 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
1976 mutex_unlock(&acpi_scan_lock); 2029 mutex_unlock(&acpi_scan_lock);
1977} 2030}
1978 2031
1979static void acpi_scan_init_hotplug(acpi_handle handle, int type) 2032static void acpi_scan_init_hotplug(struct acpi_device *adev)
1980{ 2033{
1981 struct acpi_device_pnp pnp = {};
1982 struct acpi_hardware_id *hwid; 2034 struct acpi_hardware_id *hwid;
1983 struct acpi_scan_handler *handler;
1984 2035
1985 INIT_LIST_HEAD(&pnp.ids); 2036 list_for_each_entry(hwid, &adev->pnp.ids, list) {
1986 acpi_set_pnp_ids(handle, &pnp, type); 2037 struct acpi_scan_handler *handler;
1987
1988 if (!pnp.type.hardware_id)
1989 goto out;
1990 2038
1991 /*
1992 * This relies on the fact that acpi_install_notify_handler() will not
1993 * install the same notify handler routine twice for the same handle.
1994 */
1995 list_for_each_entry(hwid, &pnp.ids, list) {
1996 handler = acpi_scan_match_handler(hwid->id, NULL); 2039 handler = acpi_scan_match_handler(hwid->id, NULL);
1997 if (handler) { 2040 if (!handler)
1998 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 2041 continue;
1999 acpi_hotplug_notify_cb, handler);
2000 break;
2001 }
2002 }
2003 2042
2004out: 2043 acpi_install_hotplug_notify_handler(adev->handle, handler);
2005 acpi_free_pnp_ids(&pnp); 2044 adev->flags.hotplug_notify = true;
2045 break;
2046 }
2006} 2047}
2007 2048
2008static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, 2049static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
@@ -2026,12 +2067,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
2026 return AE_OK; 2067 return AE_OK;
2027 } 2068 }
2028 2069
2029 acpi_scan_init_hotplug(handle, type);
2030
2031 acpi_add_single_object(&device, handle, type, sta); 2070 acpi_add_single_object(&device, handle, type, sta);
2032 if (!device) 2071 if (!device)
2033 return AE_CTRL_DEPTH; 2072 return AE_CTRL_DEPTH;
2034 2073
2074 acpi_scan_init_hotplug(device);
2075
2035 out: 2076 out:
2036 if (!*return_value) 2077 if (!*return_value)
2037 *return_value = device; 2078 *return_value = device;
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 373c7aa3b4a6..d7c1fc9712ad 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
116}; 116};
117 117
118struct acpiphp_context { 118struct acpiphp_context {
119 struct acpi_hotplug_context hp;
119 struct acpiphp_func func; 120 struct acpiphp_func func;
120 struct acpi_device *adev;
121 struct acpiphp_bridge *bridge; 121 struct acpiphp_bridge *bridge;
122 unsigned int refcount; 122 unsigned int refcount;
123}; 123};
124 124
125static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
126{
127 return container_of(hp, struct acpiphp_context, hp);
128}
129
125static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func) 130static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
126{ 131{
127 return container_of(func, struct acpiphp_context, func); 132 return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
129 134
130static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func) 135static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
131{ 136{
132 return func_to_context(func)->adev; 137 return func_to_context(func)->hp.self;
133} 138}
134 139
135static inline acpi_handle func_to_handle(struct acpiphp_func *func) 140static inline acpi_handle func_to_handle(struct acpiphp_func *func)
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 8139a4b0d389..7c498d663eb3 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -59,17 +59,12 @@
59static LIST_HEAD(bridge_list); 59static LIST_HEAD(bridge_list);
60static DEFINE_MUTEX(bridge_mutex); 60static DEFINE_MUTEX(bridge_mutex);
61 61
62static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); 62static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
63static void acpiphp_sanitize_bus(struct pci_bus *bus); 63static void acpiphp_sanitize_bus(struct pci_bus *bus);
64static void acpiphp_set_hpp_values(struct pci_bus *bus); 64static void acpiphp_set_hpp_values(struct pci_bus *bus);
65static void hotplug_event(u32 type, struct acpiphp_context *context); 65static void hotplug_event(u32 type, struct acpiphp_context *context);
66static void free_bridge(struct kref *kref); 66static void free_bridge(struct kref *kref);
67 67
68static void acpiphp_context_handler(acpi_handle handle, void *context)
69{
70 /* Intentionally empty. */
71}
72
73/** 68/**
74 * acpiphp_init_context - Create hotplug context and grab a reference to it. 69 * acpiphp_init_context - Create hotplug context and grab a reference to it.
75 * @adev: ACPI device object to create the context for. 70 * @adev: ACPI device object to create the context for.
@@ -79,39 +74,31 @@ static void acpiphp_context_handler(acpi_handle handle, void *context)
79static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev) 74static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
80{ 75{
81 struct acpiphp_context *context; 76 struct acpiphp_context *context;
82 acpi_status status;
83 77
84 context = kzalloc(sizeof(*context), GFP_KERNEL); 78 context = kzalloc(sizeof(*context), GFP_KERNEL);
85 if (!context) 79 if (!context)
86 return NULL; 80 return NULL;
87 81
88 context->adev = adev;
89 context->refcount = 1; 82 context->refcount = 1;
90 status = acpi_attach_data(adev->handle, acpiphp_context_handler, context); 83 acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_event);
91 if (ACPI_FAILURE(status)) {
92 kfree(context);
93 return NULL;
94 }
95 return context; 84 return context;
96} 85}
97 86
98/** 87/**
99 * acpiphp_get_context - Get hotplug context and grab a reference to it. 88 * acpiphp_get_context - Get hotplug context and grab a reference to it.
100 * @handle: ACPI object handle to get the context for. 89 * @adev: ACPI device object to get the context for.
101 * 90 *
102 * Call under acpi_hp_context_lock. 91 * Call under acpi_hp_context_lock.
103 */ 92 */
104static struct acpiphp_context *acpiphp_get_context(acpi_handle handle) 93static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
105{ 94{
106 struct acpiphp_context *context = NULL; 95 struct acpiphp_context *context;
107 acpi_status status;
108 void *data;
109 96
110 status = acpi_get_data(handle, acpiphp_context_handler, &data); 97 if (!adev->hp)
111 if (ACPI_SUCCESS(status)) { 98 return NULL;
112 context = data; 99
113 context->refcount++; 100 context = to_acpiphp_context(adev->hp);
114 } 101 context->refcount++;
115 return context; 102 return context;
116} 103}
117 104
@@ -129,7 +116,7 @@ static void acpiphp_put_context(struct acpiphp_context *context)
129 return; 116 return;
130 117
131 WARN_ON(context->bridge); 118 WARN_ON(context->bridge);
132 acpi_detach_data(context->adev->handle, acpiphp_context_handler); 119 context->hp.self->hp = NULL;
133 kfree(context); 120 kfree(context);
134} 121}
135 122
@@ -211,22 +198,13 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
211 198
212static void dock_event(acpi_handle handle, u32 type, void *data) 199static void dock_event(acpi_handle handle, u32 type, void *data)
213{ 200{
214 struct acpiphp_context *context; 201 struct acpi_device *adev;
215 202
216 acpi_lock_hp_context(); 203 adev = acpi_bus_get_acpi_device(handle);
217 context = acpiphp_get_context(handle); 204 if (adev) {
218 if (!context || WARN_ON(context->adev->handle != handle) 205 acpiphp_hotplug_event(adev, type);
219 || context->func.parent->is_going_away) { 206 acpi_bus_put_acpi_device(adev);
220 acpi_unlock_hp_context();
221 return;
222 } 207 }
223 get_bridge(context->func.parent);
224 acpiphp_put_context(context);
225 acpi_unlock_hp_context();
226
227 hotplug_event(type, context);
228
229 put_bridge(context->func.parent);
230} 208}
231 209
232static const struct acpi_dock_ops acpiphp_dock_ops = { 210static const struct acpi_dock_ops acpiphp_dock_ops = {
@@ -397,25 +375,23 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
397 } 375 }
398 376
399 /* install notify handler */ 377 /* install notify handler */
400 if (!(newfunc->flags & FUNC_HAS_DCK)) { 378 if (!(newfunc->flags & FUNC_HAS_DCK))
401 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 379 acpi_install_hotplug_notify_handler(handle, NULL);
402 handle_hotplug_event,
403 context);
404 if (ACPI_FAILURE(status))
405 acpi_handle_err(handle,
406 "failed to install notify handler\n");
407 }
408 380
409 return AE_OK; 381 return AE_OK;
410} 382}
411 383
412static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) 384static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
413{ 385{
386 struct acpi_device *adev = acpi_bus_get_acpi_device(handle);
414 struct acpiphp_context *context; 387 struct acpiphp_context *context;
415 struct acpiphp_bridge *bridge = NULL; 388 struct acpiphp_bridge *bridge = NULL;
416 389
390 if (!adev)
391 return NULL;
392
417 acpi_lock_hp_context(); 393 acpi_lock_hp_context();
418 context = acpiphp_get_context(handle); 394 context = acpiphp_get_context(adev);
419 if (context) { 395 if (context) {
420 bridge = context->bridge; 396 bridge = context->bridge;
421 if (bridge) 397 if (bridge)
@@ -424,6 +400,7 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
424 acpiphp_put_context(context); 400 acpiphp_put_context(context);
425 } 401 }
426 acpi_unlock_hp_context(); 402 acpi_unlock_hp_context();
403 acpi_bus_put_acpi_device(adev);
427 return bridge; 404 return bridge;
428} 405}
429 406
@@ -431,7 +408,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
431{ 408{
432 struct acpiphp_slot *slot; 409 struct acpiphp_slot *slot;
433 struct acpiphp_func *func; 410 struct acpiphp_func *func;
434 acpi_status status;
435 411
436 list_for_each_entry(slot, &bridge->slots, node) { 412 list_for_each_entry(slot, &bridge->slots, node) {
437 list_for_each_entry(func, &slot->funcs, sibling) { 413 list_for_each_entry(func, &slot->funcs, sibling) {
@@ -440,13 +416,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
440 if (is_dock_device(handle)) 416 if (is_dock_device(handle))
441 unregister_hotplug_dock_device(handle); 417 unregister_hotplug_dock_device(handle);
442 418
443 if (!(func->flags & FUNC_HAS_DCK)) { 419 if (!(func->flags & FUNC_HAS_DCK))
444 status = acpi_remove_notify_handler(handle, 420 acpi_remove_hotplug_notify_handler(handle);
445 ACPI_SYSTEM_NOTIFY,
446 handle_hotplug_event);
447 if (ACPI_FAILURE(status))
448 pr_err("failed to remove notify handler\n");
449 }
450 } 421 }
451 slot->flags |= SLOT_IS_GOING_AWAY; 422 slot->flags |= SLOT_IS_GOING_AWAY;
452 if (slot->slot) 423 if (slot->slot)
@@ -814,7 +785,7 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
814 785
815static void hotplug_event(u32 type, struct acpiphp_context *context) 786static void hotplug_event(u32 type, struct acpiphp_context *context)
816{ 787{
817 acpi_handle handle = context->adev->handle; 788 acpi_handle handle = context->hp.self->handle;
818 struct acpiphp_func *func = &context->func; 789 struct acpiphp_func *func = &context->func;
819 struct acpiphp_slot *slot = func->slot; 790 struct acpiphp_slot *slot = func->slot;
820 struct acpiphp_bridge *bridge; 791 struct acpiphp_bridge *bridge;
@@ -866,87 +837,24 @@ static void hotplug_event(u32 type, struct acpiphp_context *context)
866 put_bridge(bridge); 837 put_bridge(bridge);
867} 838}
868 839
869static void hotplug_event_work(void *data, u32 type) 840static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
870{
871 struct acpiphp_context *context = data;
872
873 acpi_scan_lock_acquire();
874
875 hotplug_event(type, context);
876
877 acpi_scan_lock_release();
878 acpi_evaluate_hotplug_ost(context->adev->handle, type,
879 ACPI_OST_SC_SUCCESS, NULL);
880 put_bridge(context->func.parent);
881}
882
883/**
884 * handle_hotplug_event - handle ACPI hotplug event
885 * @handle: Notify()'ed acpi_handle
886 * @type: Notify code
887 * @data: pointer to acpiphp_context structure
888 *
889 * Handles ACPI event notification on slots.
890 */
891static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
892{ 841{
893 struct acpiphp_context *context; 842 struct acpiphp_context *context;
894 u32 ost_code = ACPI_OST_SC_SUCCESS;
895 acpi_status status;
896
897 switch (type) {
898 case ACPI_NOTIFY_BUS_CHECK:
899 case ACPI_NOTIFY_DEVICE_CHECK:
900 break;
901 case ACPI_NOTIFY_EJECT_REQUEST:
902 ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
903 acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
904 break;
905
906 case ACPI_NOTIFY_DEVICE_WAKE:
907 return;
908
909 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
910 acpi_handle_err(handle, "Device cannot be configured due "
911 "to a frequency mismatch\n");
912 goto out;
913
914 case ACPI_NOTIFY_BUS_MODE_MISMATCH:
915 acpi_handle_err(handle, "Device cannot be configured due "
916 "to a bus mode mismatch\n");
917 goto out;
918
919 case ACPI_NOTIFY_POWER_FAULT:
920 acpi_handle_err(handle, "Device has suffered a power fault\n");
921 goto out;
922
923 default:
924 acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
925 ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
926 goto out;
927 }
928 843
929 acpi_lock_hp_context(); 844 acpi_lock_hp_context();
930 context = acpiphp_get_context(handle); 845 context = acpiphp_get_context(adev);
931 if (!context || WARN_ON(context->adev->handle != handle) 846 if (!context || context->func.parent->is_going_away) {
932 || context->func.parent->is_going_away)
933 goto err_out;
934
935 get_bridge(context->func.parent);
936 acpiphp_put_context(context);
937 status = acpi_hotplug_execute(hotplug_event_work, context, type);
938 if (ACPI_SUCCESS(status)) {
939 acpi_unlock_hp_context(); 847 acpi_unlock_hp_context();
940 return; 848 return -ENODATA;
941 } 849 }
942 put_bridge(context->func.parent); 850 get_bridge(context->func.parent);
943 851 acpiphp_put_context(context);
944 err_out:
945 acpi_unlock_hp_context(); 852 acpi_unlock_hp_context();
946 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
947 853
948 out: 854 hotplug_event(type, context);
949 acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); 855
856 put_bridge(context->func.parent);
857 return 0;
950} 858}
951 859
952/** 860/**
@@ -999,7 +907,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
999 * bridge is not interesting to us either. 907 * bridge is not interesting to us either.
1000 */ 908 */
1001 acpi_lock_hp_context(); 909 acpi_lock_hp_context();
1002 context = acpiphp_get_context(handle); 910 context = acpiphp_get_context(adev);
1003 if (!context) { 911 if (!context) {
1004 acpi_unlock_hp_context(); 912 acpi_unlock_hp_context();
1005 put_device(&bus->dev); 913 put_device(&bus->dev);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0c82708ff08a..53ce357f6335 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -137,6 +137,16 @@ struct acpi_scan_handler {
137}; 137};
138 138
139/* 139/*
140 * ACPI Hotplug Context
141 * --------------------
142 */
143
144struct acpi_hotplug_context {
145 struct acpi_device *self;
146 int (*event)(struct acpi_device *, u32);
147};
148
149/*
140 * ACPI Driver 150 * ACPI Driver
141 * ----------- 151 * -----------
142 */ 152 */
@@ -190,7 +200,8 @@ struct acpi_device_flags {
190 u32 initialized:1; 200 u32 initialized:1;
191 u32 visited:1; 201 u32 visited:1;
192 u32 no_hotplug:1; 202 u32 no_hotplug:1;
193 u32 reserved:24; 203 u32 hotplug_notify:1;
204 u32 reserved:23;
194}; 205};
195 206
196/* File System */ 207/* File System */
@@ -329,6 +340,7 @@ struct acpi_device {
329 struct acpi_device_perf performance; 340 struct acpi_device_perf performance;
330 struct acpi_device_dir dir; 341 struct acpi_device_dir dir;
331 struct acpi_scan_handler *handler; 342 struct acpi_scan_handler *handler;
343 struct acpi_hotplug_context *hp;
332 struct acpi_driver *driver; 344 struct acpi_driver *driver;
333 void *driver_data; 345 void *driver_data;
334 struct device dev; 346 struct device dev;
@@ -351,6 +363,15 @@ static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)
351 *((u32 *)&adev->status) = sta; 363 *((u32 *)&adev->status) = sta;
352} 364}
353 365
366static inline void acpi_set_hp_context(struct acpi_device *adev,
367 struct acpi_hotplug_context *hp,
368 int (*event)(struct acpi_device *, u32))
369{
370 hp->self = adev;
371 hp->event = event;
372 adev->hp = hp;
373}
374
354/* acpi_device.dev.bus == &acpi_bus_type */ 375/* acpi_device.dev.bus == &acpi_bus_type */
355extern struct bus_type acpi_bus_type; 376extern struct bus_type acpi_bus_type;
356 377
@@ -425,6 +446,8 @@ static inline bool acpi_device_enumerated(struct acpi_device *adev)
425typedef void (*acpi_hp_callback)(void *data, u32 src); 446typedef void (*acpi_hp_callback)(void *data, u32 src);
426 447
427acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); 448acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
449void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
450void acpi_remove_hotplug_notify_handler(acpi_handle handle);
428 451
429/** 452/**
430 * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver 453 * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver