diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-20 19:06:58 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-20 19:06:58 -0500 |
commit | 2bd74d91b1217d84d08db57b860d056d130248d3 (patch) | |
tree | 6333daab84310e75200be4c3dc511b7e4baa1f42 /drivers/acpi | |
parent | ae3caa80a5d532d334c7a4785d74104e3de5a9ae (diff) | |
parent | cc6254e00eb676dda6501655f8185aef7b761b4f (diff) |
Merge branch 'acpi-pci-hotplug' into acpi-ost
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpica/nsxfeval.c | 33 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 61 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 2 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 181 |
5 files changed, 164 insertions, 114 deletions
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 1f0c28ba50df..d6b33bc7bab0 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c | |||
@@ -923,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data) | |||
923 | 923 | ||
924 | /******************************************************************************* | 924 | /******************************************************************************* |
925 | * | 925 | * |
926 | * FUNCTION: acpi_get_data | 926 | * FUNCTION: acpi_get_data_full |
927 | * | 927 | * |
928 | * PARAMETERS: obj_handle - Namespace node | 928 | * PARAMETERS: obj_handle - Namespace node |
929 | * handler - Handler used in call to attach_data | 929 | * handler - Handler used in call to attach_data |
930 | * data - Where the data is returned | 930 | * data - Where the data is returned |
931 | * callback - function to execute before returning | ||
931 | * | 932 | * |
932 | * RETURN: Status | 933 | * RETURN: Status |
933 | * | 934 | * |
934 | * DESCRIPTION: Retrieve data that was previously attached to a namespace node. | 935 | * DESCRIPTION: Retrieve data that was previously attached to a namespace node |
936 | * and execute a callback before returning. | ||
935 | * | 937 | * |
936 | ******************************************************************************/ | 938 | ******************************************************************************/ |
937 | acpi_status | 939 | acpi_status |
938 | acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) | 940 | acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler, |
941 | void **data, void (*callback)(void *)) | ||
939 | { | 942 | { |
940 | struct acpi_namespace_node *node; | 943 | struct acpi_namespace_node *node; |
941 | acpi_status status; | 944 | acpi_status status; |
@@ -960,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) | |||
960 | } | 963 | } |
961 | 964 | ||
962 | status = acpi_ns_get_attached_data(node, handler, data); | 965 | status = acpi_ns_get_attached_data(node, handler, data); |
966 | if (ACPI_SUCCESS(status) && callback) { | ||
967 | callback(*data); | ||
968 | } | ||
963 | 969 | ||
964 | unlock_and_exit: | 970 | unlock_and_exit: |
965 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 971 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
966 | return (status); | 972 | return (status); |
967 | } | 973 | } |
968 | 974 | ||
975 | ACPI_EXPORT_SYMBOL(acpi_get_data_full) | ||
976 | |||
977 | /******************************************************************************* | ||
978 | * | ||
979 | * FUNCTION: acpi_get_data | ||
980 | * | ||
981 | * PARAMETERS: obj_handle - Namespace node | ||
982 | * handler - Handler used in call to attach_data | ||
983 | * data - Where the data is returned | ||
984 | * | ||
985 | * RETURN: Status | ||
986 | * | ||
987 | * DESCRIPTION: Retrieve data that was previously attached to a namespace node. | ||
988 | * | ||
989 | ******************************************************************************/ | ||
990 | acpi_status | ||
991 | acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) | ||
992 | { | ||
993 | return acpi_get_data_full(obj_handle, handler, data, NULL); | ||
994 | } | ||
995 | |||
969 | ACPI_EXPORT_SYMBOL(acpi_get_data) | 996 | ACPI_EXPORT_SYMBOL(acpi_get_data) |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fcb59c21c68d..e61e7b8a2eaf 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -340,60 +340,77 @@ static void acpi_bus_osc_support(void) | |||
340 | */ | 340 | */ |
341 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | 341 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) |
342 | { | 342 | { |
343 | struct acpi_device *device = NULL; | 343 | struct acpi_device *adev; |
344 | struct acpi_driver *driver; | 344 | struct acpi_driver *driver; |
345 | 345 | acpi_status status; | |
346 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", | 346 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
347 | type, handle)); | ||
348 | 347 | ||
349 | switch (type) { | 348 | switch (type) { |
350 | |||
351 | case ACPI_NOTIFY_BUS_CHECK: | 349 | case ACPI_NOTIFY_BUS_CHECK: |
352 | /* TBD */ | 350 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); |
353 | break; | 351 | break; |
354 | 352 | ||
355 | case ACPI_NOTIFY_DEVICE_CHECK: | 353 | case ACPI_NOTIFY_DEVICE_CHECK: |
356 | /* TBD */ | 354 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); |
357 | break; | 355 | break; |
358 | 356 | ||
359 | case ACPI_NOTIFY_DEVICE_WAKE: | 357 | case ACPI_NOTIFY_DEVICE_WAKE: |
360 | /* TBD */ | 358 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n"); |
361 | break; | 359 | break; |
362 | 360 | ||
363 | case ACPI_NOTIFY_EJECT_REQUEST: | 361 | case ACPI_NOTIFY_EJECT_REQUEST: |
364 | /* TBD */ | 362 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
365 | break; | 363 | break; |
366 | 364 | ||
367 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: | 365 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: |
366 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n"); | ||
368 | /* TBD: Exactly what does 'light' mean? */ | 367 | /* TBD: Exactly what does 'light' mean? */ |
369 | break; | 368 | break; |
370 | 369 | ||
371 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 370 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
372 | /* TBD */ | 371 | acpi_handle_err(handle, "Device cannot be configured due " |
372 | "to a frequency mismatch\n"); | ||
373 | break; | 373 | break; |
374 | 374 | ||
375 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 375 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
376 | /* TBD */ | 376 | acpi_handle_err(handle, "Device cannot be configured due " |
377 | "to a bus mode mismatch\n"); | ||
377 | break; | 378 | break; |
378 | 379 | ||
379 | case ACPI_NOTIFY_POWER_FAULT: | 380 | case ACPI_NOTIFY_POWER_FAULT: |
380 | /* TBD */ | 381 | acpi_handle_err(handle, "Device has suffered a power fault\n"); |
381 | break; | 382 | break; |
382 | 383 | ||
383 | default: | 384 | default: |
384 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 385 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); |
385 | "Received unknown/unsupported notification [%08x]\n", | 386 | ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; |
386 | type)); | 387 | goto err; |
387 | break; | ||
388 | } | 388 | } |
389 | 389 | ||
390 | acpi_bus_get_device(handle, &device); | 390 | adev = acpi_bus_get_acpi_device(handle); |
391 | if (device) { | 391 | if (!adev) |
392 | driver = device->driver; | 392 | goto err; |
393 | if (driver && driver->ops.notify && | 393 | |
394 | (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) | 394 | driver = adev->driver; |
395 | driver->ops.notify(device, type); | 395 | if (driver && driver->ops.notify && |
396 | (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) | ||
397 | driver->ops.notify(adev, type); | ||
398 | |||
399 | switch (type) { | ||
400 | case ACPI_NOTIFY_BUS_CHECK: | ||
401 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
402 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
403 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
404 | if (ACPI_SUCCESS(status)) | ||
405 | return; | ||
406 | default: | ||
407 | break; | ||
396 | } | 408 | } |
409 | acpi_bus_put_acpi_device(adev); | ||
410 | return; | ||
411 | |||
412 | err: | ||
413 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
397 | } | 414 | } |
398 | 415 | ||
399 | /* -------------------------------------------------------------------------- | 416 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index dedbb2d802f1..143d5df5ec32 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -73,6 +73,7 @@ static inline void acpi_lpss_init(void) {} | |||
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | bool acpi_queue_hotplug_work(struct work_struct *work); | 75 | bool acpi_queue_hotplug_work(struct work_struct *work); |
76 | void acpi_device_hotplug(void *data, u32 src); | ||
76 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); | 77 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); |
77 | 78 | ||
78 | /* -------------------------------------------------------------------------- | 79 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index c1c4102e6478..c288ff3c6998 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -51,7 +51,7 @@ static void acpi_pci_root_remove(struct acpi_device *device); | |||
51 | 51 | ||
52 | static int acpi_pci_root_scan_dependent(struct acpi_device *adev) | 52 | static int acpi_pci_root_scan_dependent(struct acpi_device *adev) |
53 | { | 53 | { |
54 | acpiphp_check_host_bridge(adev->handle); | 54 | acpiphp_check_host_bridge(adev); |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 62ec4ba7ecef..3fc530a8d362 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock); | |||
41 | static LIST_HEAD(acpi_scan_handlers_list); | 41 | static LIST_HEAD(acpi_scan_handlers_list); |
42 | DEFINE_MUTEX(acpi_device_lock); | 42 | DEFINE_MUTEX(acpi_device_lock); |
43 | LIST_HEAD(acpi_wakeup_device_list); | 43 | LIST_HEAD(acpi_wakeup_device_list); |
44 | static DEFINE_MUTEX(acpi_hp_context_lock); | ||
44 | 45 | ||
45 | struct acpi_device_bus_id{ | 46 | struct acpi_device_bus_id{ |
46 | char bus_id[15]; | 47 | char bus_id[15]; |
@@ -60,6 +61,16 @@ void acpi_scan_lock_release(void) | |||
60 | } | 61 | } |
61 | EXPORT_SYMBOL_GPL(acpi_scan_lock_release); | 62 | EXPORT_SYMBOL_GPL(acpi_scan_lock_release); |
62 | 63 | ||
64 | void acpi_lock_hp_context(void) | ||
65 | { | ||
66 | mutex_lock(&acpi_hp_context_lock); | ||
67 | } | ||
68 | |||
69 | void acpi_unlock_hp_context(void) | ||
70 | { | ||
71 | mutex_unlock(&acpi_hp_context_lock); | ||
72 | } | ||
73 | |||
63 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) | 74 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) |
64 | { | 75 | { |
65 | if (!handler || !handler->attach) | 76 | if (!handler || !handler->attach) |
@@ -439,90 +450,74 @@ static int acpi_scan_bus_check(struct acpi_device *adev) | |||
439 | return 0; | 450 | return 0; |
440 | } | 451 | } |
441 | 452 | ||
442 | static void acpi_device_hotplug(void *data, u32 src) | 453 | static 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 | if (adev->handler && !adev->handler->hotplug.enabled) { | ||
463 | dev_info(&adev->dev, "Eject disabled\n"); | ||
464 | return -EPERM; | ||
465 | } | ||
466 | acpi_evaluate_hotplug_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST, | ||
467 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
468 | return acpi_scan_hot_remove(adev); | ||
469 | } | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | |||
473 | void acpi_device_hotplug(void *data, u32 src) | ||
443 | { | 474 | { |
444 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 475 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
445 | struct acpi_device *adev = data; | 476 | struct acpi_device *adev = data; |
446 | int error; | 477 | int error = -ENODEV; |
447 | 478 | ||
448 | lock_device_hotplug(); | 479 | lock_device_hotplug(); |
449 | mutex_lock(&acpi_scan_lock); | 480 | mutex_lock(&acpi_scan_lock); |
450 | 481 | ||
451 | /* | 482 | /* |
452 | * The device object's ACPI handle cannot become invalid as long as we | 483 | * The device object's ACPI handle cannot become invalid as long as we |
453 | * are holding acpi_scan_lock, but it may have become invalid before | 484 | * are holding acpi_scan_lock, but it might have become invalid before |
454 | * that lock was acquired. | 485 | * that lock was acquired. |
455 | */ | 486 | */ |
456 | if (adev->handle == INVALID_ACPI_HANDLE) | 487 | if (adev->handle == INVALID_ACPI_HANDLE) |
457 | goto out; | ||
458 | |||
459 | switch (src) { | ||
460 | case ACPI_NOTIFY_BUS_CHECK: | ||
461 | error = acpi_scan_bus_check(adev); | ||
462 | break; | ||
463 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
464 | error = acpi_scan_device_check(adev); | ||
465 | break; | ||
466 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
467 | case ACPI_OST_EC_OSPM_EJECT: | ||
468 | error = acpi_scan_hot_remove(adev); | ||
469 | break; | ||
470 | default: | ||
471 | error = -EINVAL; | ||
472 | break; | ||
473 | } | ||
474 | if (!error) | ||
475 | ost_code = ACPI_OST_SC_SUCCESS; | ||
476 | |||
477 | out: | ||
478 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); | ||
479 | put_device(&adev->dev); | ||
480 | mutex_unlock(&acpi_scan_lock); | ||
481 | unlock_device_hotplug(); | ||
482 | } | ||
483 | |||
484 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | ||
485 | { | ||
486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
487 | struct acpi_device *adev; | ||
488 | acpi_status status; | ||
489 | |||
490 | if (acpi_bus_get_device(handle, &adev)) | ||
491 | goto err_out; | 488 | goto err_out; |
492 | 489 | ||
493 | switch (type) { | 490 | if (adev->flags.hotplug_notify) { |
494 | case ACPI_NOTIFY_BUS_CHECK: | 491 | error = acpi_generic_hotplug_event(adev, src); |
495 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); | 492 | if (error == -EPERM) { |
496 | break; | ||
497 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
498 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); | ||
499 | break; | ||
500 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
501 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | ||
502 | if (!adev->handler) | ||
503 | goto err_out; | ||
504 | |||
505 | if (!adev->handler->hotplug.enabled) { | ||
506 | acpi_handle_err(handle, "Eject disabled\n"); | ||
507 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 493 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; |
508 | goto err_out; | 494 | goto err_out; |
509 | } | 495 | } |
510 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 496 | } else { |
511 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 497 | int (*event)(struct acpi_device *, u32); |
512 | break; | ||
513 | default: | ||
514 | /* non-hotplug event; possibly handled by other handler */ | ||
515 | return; | ||
516 | } | ||
517 | get_device(&adev->dev); | ||
518 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
519 | if (ACPI_SUCCESS(status)) | ||
520 | return; | ||
521 | 498 | ||
522 | put_device(&adev->dev); | 499 | acpi_lock_hp_context(); |
500 | event = adev->hp ? adev->hp->event : NULL; | ||
501 | acpi_unlock_hp_context(); | ||
502 | /* | ||
503 | * There may be additional notify handlers for device objects | ||
504 | * without the .event() callback, so ignore them here. | ||
505 | */ | ||
506 | if (event) | ||
507 | error = event(adev, src); | ||
508 | else | ||
509 | goto out; | ||
510 | } | ||
511 | if (!error) | ||
512 | ost_code = ACPI_OST_SC_SUCCESS; | ||
523 | 513 | ||
524 | err_out: | 514 | err_out: |
525 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | 515 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); |
516 | |||
517 | out: | ||
518 | acpi_bus_put_acpi_device(adev); | ||
519 | mutex_unlock(&acpi_scan_lock); | ||
520 | unlock_device_hotplug(); | ||
526 | } | 521 | } |
527 | 522 | ||
528 | static ssize_t real_power_state_show(struct device *dev, | 523 | static ssize_t real_power_state_show(struct device *dev, |
@@ -570,8 +565,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
570 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) | 565 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) |
571 | return -ENODEV; | 566 | return -ENODEV; |
572 | 567 | ||
573 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | ||
574 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
575 | get_device(&acpi_device->dev); | 568 | get_device(&acpi_device->dev); |
576 | status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, | 569 | status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, |
577 | ACPI_OST_EC_OSPM_EJECT); | 570 | ACPI_OST_EC_OSPM_EJECT); |
@@ -1114,14 +1107,16 @@ static void acpi_scan_drop_device(acpi_handle handle, void *context) | |||
1114 | mutex_unlock(&acpi_device_del_lock); | 1107 | mutex_unlock(&acpi_device_del_lock); |
1115 | } | 1108 | } |
1116 | 1109 | ||
1117 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | 1110 | static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device, |
1111 | void (*callback)(void *)) | ||
1118 | { | 1112 | { |
1119 | acpi_status status; | 1113 | acpi_status status; |
1120 | 1114 | ||
1121 | if (!device) | 1115 | if (!device) |
1122 | return -EINVAL; | 1116 | return -EINVAL; |
1123 | 1117 | ||
1124 | status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); | 1118 | status = acpi_get_data_full(handle, acpi_scan_drop_device, |
1119 | (void **)device, callback); | ||
1125 | if (ACPI_FAILURE(status) || !*device) { | 1120 | if (ACPI_FAILURE(status) || !*device) { |
1126 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", | 1121 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
1127 | handle)); | 1122 | handle)); |
@@ -1129,8 +1124,32 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | |||
1129 | } | 1124 | } |
1130 | return 0; | 1125 | return 0; |
1131 | } | 1126 | } |
1127 | |||
1128 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | ||
1129 | { | ||
1130 | return acpi_get_device_data(handle, device, NULL); | ||
1131 | } | ||
1132 | EXPORT_SYMBOL(acpi_bus_get_device); | 1132 | EXPORT_SYMBOL(acpi_bus_get_device); |
1133 | 1133 | ||
1134 | static void get_acpi_device(void *dev) | ||
1135 | { | ||
1136 | if (dev) | ||
1137 | get_device(&((struct acpi_device *)dev)->dev); | ||
1138 | } | ||
1139 | |||
1140 | struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) | ||
1141 | { | ||
1142 | struct acpi_device *adev = NULL; | ||
1143 | |||
1144 | acpi_get_device_data(handle, &adev, get_acpi_device); | ||
1145 | return adev; | ||
1146 | } | ||
1147 | |||
1148 | void acpi_bus_put_acpi_device(struct acpi_device *adev) | ||
1149 | { | ||
1150 | put_device(&adev->dev); | ||
1151 | } | ||
1152 | |||
1134 | int acpi_device_add(struct acpi_device *device, | 1153 | int acpi_device_add(struct acpi_device *device, |
1135 | void (*release)(struct device *)) | 1154 | void (*release)(struct device *)) |
1136 | { | 1155 | { |
@@ -1957,33 +1976,19 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val) | |||
1957 | mutex_unlock(&acpi_scan_lock); | 1976 | mutex_unlock(&acpi_scan_lock); |
1958 | } | 1977 | } |
1959 | 1978 | ||
1960 | static void acpi_scan_init_hotplug(acpi_handle handle, int type) | 1979 | static void acpi_scan_init_hotplug(struct acpi_device *adev) |
1961 | { | 1980 | { |
1962 | struct acpi_device_pnp pnp = {}; | ||
1963 | struct acpi_hardware_id *hwid; | 1981 | struct acpi_hardware_id *hwid; |
1964 | struct acpi_scan_handler *handler; | ||
1965 | |||
1966 | INIT_LIST_HEAD(&pnp.ids); | ||
1967 | acpi_set_pnp_ids(handle, &pnp, type); | ||
1968 | 1982 | ||
1969 | if (!pnp.type.hardware_id) | 1983 | list_for_each_entry(hwid, &adev->pnp.ids, list) { |
1970 | goto out; | 1984 | struct acpi_scan_handler *handler; |
1971 | 1985 | ||
1972 | /* | ||
1973 | * This relies on the fact that acpi_install_notify_handler() will not | ||
1974 | * install the same notify handler routine twice for the same handle. | ||
1975 | */ | ||
1976 | list_for_each_entry(hwid, &pnp.ids, list) { | ||
1977 | handler = acpi_scan_match_handler(hwid->id, NULL); | 1986 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1978 | if (handler) { | 1987 | if (handler) { |
1979 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1988 | adev->flags.hotplug_notify = true; |
1980 | acpi_hotplug_notify_cb, handler); | ||
1981 | break; | 1989 | break; |
1982 | } | 1990 | } |
1983 | } | 1991 | } |
1984 | |||
1985 | out: | ||
1986 | acpi_free_pnp_ids(&pnp); | ||
1987 | } | 1992 | } |
1988 | 1993 | ||
1989 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | 1994 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, |
@@ -2007,12 +2012,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
2007 | return AE_OK; | 2012 | return AE_OK; |
2008 | } | 2013 | } |
2009 | 2014 | ||
2010 | acpi_scan_init_hotplug(handle, type); | ||
2011 | |||
2012 | acpi_add_single_object(&device, handle, type, sta); | 2015 | acpi_add_single_object(&device, handle, type, sta); |
2013 | if (!device) | 2016 | if (!device) |
2014 | return AE_CTRL_DEPTH; | 2017 | return AE_CTRL_DEPTH; |
2015 | 2018 | ||
2019 | acpi_scan_init_hotplug(device); | ||
2020 | |||
2016 | out: | 2021 | out: |
2017 | if (!*return_value) | 2022 | if (!*return_value) |
2018 | *return_value = device; | 2023 | *return_value = device; |