diff options
-rw-r--r-- | drivers/acpi/bus.c | 61 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 81 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 24 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 2 |
6 files changed, 57 insertions, 113 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c3237774632f..e61e7b8a2eaf 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -340,62 +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; | 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 | device = acpi_bus_get_acpi_device(handle); | 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 && | ||
394 | (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) | ||
395 | driver->ops.notify(device, type); | ||
396 | 393 | ||
397 | acpi_bus_put_acpi_device(device); | 394 | driver = adev->driver; |
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; | ||
398 | } | 408 | } |
409 | acpi_bus_put_acpi_device(adev); | ||
410 | return; | ||
411 | |||
412 | err: | ||
413 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
399 | } | 414 | } |
400 | 415 | ||
401 | /* -------------------------------------------------------------------------- | 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/scan.c b/drivers/acpi/scan.c index 59f9e272562e..8bb48bfab1df 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -470,7 +470,7 @@ static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type) | |||
470 | return -EINVAL; | 470 | return -EINVAL; |
471 | } | 471 | } |
472 | 472 | ||
473 | static void acpi_device_hotplug(void *data, u32 src) | 473 | void acpi_device_hotplug(void *data, u32 src) |
474 | { | 474 | { |
475 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 475 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
476 | struct acpi_device *adev = data; | 476 | struct acpi_device *adev = data; |
@@ -520,75 +520,6 @@ static void acpi_device_hotplug(void *data, u32 src) | |||
520 | unlock_device_hotplug(); | 520 | unlock_device_hotplug(); |
521 | } | 521 | } |
522 | 522 | ||
523 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | ||
524 | { | ||
525 | u32 ost_code = ACPI_OST_SC_SUCCESS; | ||
526 | struct acpi_device *adev; | ||
527 | acpi_status status; | ||
528 | |||
529 | switch (type) { | ||
530 | case ACPI_NOTIFY_BUS_CHECK: | ||
531 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); | ||
532 | break; | ||
533 | |||
534 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
535 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); | ||
536 | break; | ||
537 | |||
538 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
539 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | ||
540 | break; | ||
541 | |||
542 | case ACPI_NOTIFY_DEVICE_WAKE: | ||
543 | return; | ||
544 | |||
545 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | ||
546 | acpi_handle_err(handle, "Device cannot be configured due " | ||
547 | "to a frequency mismatch\n"); | ||
548 | goto out; | ||
549 | |||
550 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | ||
551 | acpi_handle_err(handle, "Device cannot be configured due " | ||
552 | "to a bus mode mismatch\n"); | ||
553 | goto out; | ||
554 | |||
555 | case ACPI_NOTIFY_POWER_FAULT: | ||
556 | acpi_handle_err(handle, "Device has suffered a power fault\n"); | ||
557 | goto out; | ||
558 | |||
559 | default: | ||
560 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); | ||
561 | ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; | ||
562 | goto out; | ||
563 | } | ||
564 | |||
565 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
566 | adev = acpi_bus_get_acpi_device(handle); | ||
567 | if (!adev) | ||
568 | goto out; | ||
569 | |||
570 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
571 | if (ACPI_SUCCESS(status)) | ||
572 | return; | ||
573 | |||
574 | acpi_bus_put_acpi_device(adev); | ||
575 | |||
576 | out: | ||
577 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
578 | } | ||
579 | |||
580 | void acpi_install_hotplug_notify_handler(acpi_handle handle) | ||
581 | { | ||
582 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
583 | acpi_hotplug_notify_cb, NULL); | ||
584 | } | ||
585 | |||
586 | void acpi_remove_hotplug_notify_handler(acpi_handle handle) | ||
587 | { | ||
588 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
589 | acpi_hotplug_notify_cb); | ||
590 | } | ||
591 | |||
592 | static ssize_t real_power_state_show(struct device *dev, | 523 | static ssize_t real_power_state_show(struct device *dev, |
593 | struct device_attribute *attr, char *buf) | 524 | struct device_attribute *attr, char *buf) |
594 | { | 525 | { |
@@ -2037,12 +1968,10 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev) | |||
2037 | struct acpi_scan_handler *handler; | 1968 | struct acpi_scan_handler *handler; |
2038 | 1969 | ||
2039 | handler = acpi_scan_match_handler(hwid->id, NULL); | 1970 | handler = acpi_scan_match_handler(hwid->id, NULL); |
2040 | if (!handler) | 1971 | if (handler) { |
2041 | continue; | 1972 | adev->flags.hotplug_notify = true; |
2042 | 1973 | break; | |
2043 | acpi_install_hotplug_notify_handler(adev->handle); | 1974 | } |
2044 | adev->flags.hotplug_notify = true; | ||
2045 | break; | ||
2046 | } | 1975 | } |
2047 | } | 1976 | } |
2048 | 1977 | ||
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index d7c1fc9712ad..2b859249303b 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -167,7 +167,6 @@ struct acpiphp_attention_info | |||
167 | 167 | ||
168 | #define FUNC_HAS_STA (0x00000001) | 168 | #define FUNC_HAS_STA (0x00000001) |
169 | #define FUNC_HAS_EJ0 (0x00000002) | 169 | #define FUNC_HAS_EJ0 (0x00000002) |
170 | #define FUNC_HAS_DCK (0x00000004) | ||
171 | 170 | ||
172 | /* function prototypes */ | 171 | /* function prototypes */ |
173 | 172 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index f3c49c442d93..b7342d2e819b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -297,7 +297,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
297 | newfunc = &context->func; | 297 | newfunc = &context->func; |
298 | newfunc->function = function; | 298 | newfunc->function = function; |
299 | newfunc->parent = bridge; | 299 | newfunc->parent = bridge; |
300 | acpi_unlock_hp_context(); | ||
301 | 300 | ||
302 | if (acpi_has_method(handle, "_EJ0")) | 301 | if (acpi_has_method(handle, "_EJ0")) |
303 | newfunc->flags = FUNC_HAS_EJ0; | 302 | newfunc->flags = FUNC_HAS_EJ0; |
@@ -305,8 +304,14 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
305 | if (acpi_has_method(handle, "_STA")) | 304 | if (acpi_has_method(handle, "_STA")) |
306 | newfunc->flags |= FUNC_HAS_STA; | 305 | newfunc->flags |= FUNC_HAS_STA; |
307 | 306 | ||
307 | /* | ||
308 | * Dock stations' notify handler should be used for dock devices instead | ||
309 | * of the common one, so clear hp.event in their contexts. | ||
310 | */ | ||
308 | if (acpi_has_method(handle, "_DCK")) | 311 | if (acpi_has_method(handle, "_DCK")) |
309 | newfunc->flags |= FUNC_HAS_DCK; | 312 | context->hp.event = NULL; |
313 | |||
314 | acpi_unlock_hp_context(); | ||
310 | 315 | ||
311 | /* search for objects that share the same slot */ | 316 | /* search for objects that share the same slot */ |
312 | list_for_each_entry(slot, &bridge->slots, node) | 317 | list_for_each_entry(slot, &bridge->slots, node) |
@@ -374,10 +379,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
374 | pr_debug("failed to register dock device\n"); | 379 | pr_debug("failed to register dock device\n"); |
375 | } | 380 | } |
376 | 381 | ||
377 | /* install notify handler */ | ||
378 | if (!(newfunc->flags & FUNC_HAS_DCK)) | ||
379 | acpi_install_hotplug_notify_handler(handle); | ||
380 | |||
381 | return AE_OK; | 382 | return AE_OK; |
382 | } | 383 | } |
383 | 384 | ||
@@ -411,13 +412,14 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
411 | 412 | ||
412 | list_for_each_entry(slot, &bridge->slots, node) { | 413 | list_for_each_entry(slot, &bridge->slots, node) { |
413 | list_for_each_entry(func, &slot->funcs, sibling) { | 414 | list_for_each_entry(func, &slot->funcs, sibling) { |
414 | acpi_handle handle = func_to_handle(func); | 415 | struct acpi_device *adev = func_to_acpi_device(func); |
415 | 416 | ||
416 | if (is_dock_device(handle)) | 417 | if (is_dock_device(adev->handle)) |
417 | unregister_hotplug_dock_device(handle); | 418 | unregister_hotplug_dock_device(adev->handle); |
418 | 419 | ||
419 | if (!(func->flags & FUNC_HAS_DCK)) | 420 | acpi_lock_hp_context(); |
420 | acpi_remove_hotplug_notify_handler(handle); | 421 | adev->hp->event = NULL; |
422 | acpi_unlock_hp_context(); | ||
421 | } | 423 | } |
422 | slot->flags |= SLOT_IS_GOING_AWAY; | 424 | slot->flags |= SLOT_IS_GOING_AWAY; |
423 | if (slot->slot) | 425 | if (slot->slot) |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 907d5078f78a..32f90c7bcb03 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -446,8 +446,6 @@ static inline bool acpi_device_enumerated(struct acpi_device *adev) | |||
446 | typedef void (*acpi_hp_callback)(void *data, u32 src); | 446 | typedef void (*acpi_hp_callback)(void *data, u32 src); |
447 | 447 | ||
448 | acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); | 448 | acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); |
449 | void acpi_install_hotplug_notify_handler(acpi_handle handle); | ||
450 | void acpi_remove_hotplug_notify_handler(acpi_handle handle); | ||
451 | 449 | ||
452 | /** | 450 | /** |
453 | * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver | 451 | * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver |