diff options
Diffstat (limited to 'drivers/acpi/device_pm.c')
-rw-r--r-- | drivers/acpi/device_pm.c | 148 |
1 files changed, 83 insertions, 65 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 49a51277f81d..67075f800e34 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable); | |||
367 | #ifdef CONFIG_PM | 367 | #ifdef CONFIG_PM |
368 | static DEFINE_MUTEX(acpi_pm_notifier_lock); | 368 | static DEFINE_MUTEX(acpi_pm_notifier_lock); |
369 | 369 | ||
370 | static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | ||
371 | { | ||
372 | struct acpi_device *adev; | ||
373 | |||
374 | if (val != ACPI_NOTIFY_DEVICE_WAKE) | ||
375 | return; | ||
376 | |||
377 | adev = acpi_bus_get_acpi_device(handle); | ||
378 | if (!adev) | ||
379 | return; | ||
380 | |||
381 | mutex_lock(&acpi_pm_notifier_lock); | ||
382 | |||
383 | if (adev->wakeup.flags.notifier_present) { | ||
384 | __pm_wakeup_event(adev->wakeup.ws, 0); | ||
385 | if (adev->wakeup.context.work.func) | ||
386 | queue_pm_work(&adev->wakeup.context.work); | ||
387 | } | ||
388 | |||
389 | mutex_unlock(&acpi_pm_notifier_lock); | ||
390 | |||
391 | acpi_bus_put_acpi_device(adev); | ||
392 | } | ||
393 | |||
370 | /** | 394 | /** |
371 | * acpi_add_pm_notifier - Register PM notifier for given ACPI device. | 395 | * acpi_add_pm_notifier - Register PM notify handler for given ACPI device. |
372 | * @adev: ACPI device to add the notifier for. | 396 | * @adev: ACPI device to add the notify handler for. |
373 | * @context: Context information to pass to the notifier routine. | 397 | * @dev: Device to generate a wakeup event for while handling the notification. |
398 | * @work_func: Work function to execute when handling the notification. | ||
374 | * | 399 | * |
375 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of | 400 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of |
376 | * PM wakeup events. For example, wakeup events may be generated for bridges | 401 | * PM wakeup events. For example, wakeup events may be generated for bridges |
377 | * if one of the devices below the bridge is signaling wakeup, even if the | 402 | * if one of the devices below the bridge is signaling wakeup, even if the |
378 | * bridge itself doesn't have a wakeup GPE associated with it. | 403 | * bridge itself doesn't have a wakeup GPE associated with it. |
379 | */ | 404 | */ |
380 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | 405 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, |
381 | acpi_notify_handler handler, void *context) | 406 | void (*work_func)(struct work_struct *work)) |
382 | { | 407 | { |
383 | acpi_status status = AE_ALREADY_EXISTS; | 408 | acpi_status status = AE_ALREADY_EXISTS; |
384 | 409 | ||
410 | if (!dev && !work_func) | ||
411 | return AE_BAD_PARAMETER; | ||
412 | |||
385 | mutex_lock(&acpi_pm_notifier_lock); | 413 | mutex_lock(&acpi_pm_notifier_lock); |
386 | 414 | ||
387 | if (adev->wakeup.flags.notifier_present) | 415 | if (adev->wakeup.flags.notifier_present) |
388 | goto out; | 416 | goto out; |
389 | 417 | ||
390 | status = acpi_install_notify_handler(adev->handle, | 418 | adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); |
391 | ACPI_SYSTEM_NOTIFY, | 419 | adev->wakeup.context.dev = dev; |
392 | handler, context); | 420 | if (work_func) |
421 | INIT_WORK(&adev->wakeup.context.work, work_func); | ||
422 | |||
423 | status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, | ||
424 | acpi_pm_notify_handler, NULL); | ||
393 | if (ACPI_FAILURE(status)) | 425 | if (ACPI_FAILURE(status)) |
394 | goto out; | 426 | goto out; |
395 | 427 | ||
@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | |||
404 | * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. | 436 | * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. |
405 | * @adev: ACPI device to remove the notifier from. | 437 | * @adev: ACPI device to remove the notifier from. |
406 | */ | 438 | */ |
407 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | 439 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) |
408 | acpi_notify_handler handler) | ||
409 | { | 440 | { |
410 | acpi_status status = AE_BAD_PARAMETER; | 441 | acpi_status status = AE_BAD_PARAMETER; |
411 | 442 | ||
@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | |||
416 | 447 | ||
417 | status = acpi_remove_notify_handler(adev->handle, | 448 | status = acpi_remove_notify_handler(adev->handle, |
418 | ACPI_SYSTEM_NOTIFY, | 449 | ACPI_SYSTEM_NOTIFY, |
419 | handler); | 450 | acpi_pm_notify_handler); |
420 | if (ACPI_FAILURE(status)) | 451 | if (ACPI_FAILURE(status)) |
421 | goto out; | 452 | goto out; |
422 | 453 | ||
454 | if (adev->wakeup.context.work.func) { | ||
455 | cancel_work_sync(&adev->wakeup.context.work); | ||
456 | adev->wakeup.context.work.func = NULL; | ||
457 | } | ||
458 | adev->wakeup.context.dev = NULL; | ||
459 | wakeup_source_unregister(adev->wakeup.ws); | ||
460 | |||
423 | adev->wakeup.flags.notifier_present = false; | 461 | adev->wakeup.flags.notifier_present = false; |
424 | 462 | ||
425 | out: | 463 | out: |
@@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | |||
558 | */ | 596 | */ |
559 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | 597 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) |
560 | { | 598 | { |
561 | acpi_handle handle = ACPI_HANDLE(dev); | ||
562 | struct acpi_device *adev; | 599 | struct acpi_device *adev; |
563 | int ret, d_min, d_max; | 600 | int ret, d_min, d_max; |
564 | 601 | ||
@@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | |||
573 | d_max_in = ACPI_STATE_D3_HOT; | 610 | d_max_in = ACPI_STATE_D3_HOT; |
574 | } | 611 | } |
575 | 612 | ||
576 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 613 | adev = ACPI_COMPANION(dev); |
577 | dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); | 614 | if (!adev) { |
615 | dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); | ||
578 | return -ENODEV; | 616 | return -ENODEV; |
579 | } | 617 | } |
580 | 618 | ||
@@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | |||
600 | } | 638 | } |
601 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); | 639 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); |
602 | 640 | ||
603 | #ifdef CONFIG_PM_RUNTIME | ||
604 | /** | 641 | /** |
605 | * acpi_wakeup_device - Wakeup notification handler for ACPI devices. | 642 | * acpi_pm_notify_work_func - ACPI devices wakeup notification work function. |
606 | * @handle: ACPI handle of the device the notification is for. | 643 | * @work: Work item to handle. |
607 | * @event: Type of the signaled event. | ||
608 | * @context: Device corresponding to @handle. | ||
609 | */ | 644 | */ |
610 | static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) | 645 | static void acpi_pm_notify_work_func(struct work_struct *work) |
611 | { | 646 | { |
612 | struct device *dev = context; | 647 | struct device *dev; |
613 | 648 | ||
614 | if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) { | 649 | dev = container_of(work, struct acpi_device_wakeup_context, work)->dev; |
650 | if (dev) { | ||
615 | pm_wakeup_event(dev, 0); | 651 | pm_wakeup_event(dev, 0); |
616 | pm_runtime_resume(dev); | 652 | pm_runtime_resume(dev); |
617 | } | 653 | } |
618 | } | 654 | } |
619 | 655 | ||
620 | /** | 656 | /** |
621 | * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device. | 657 | * acpi_device_wakeup - Enable/disable wakeup functionality for device. |
622 | * @adev: ACPI device to enable/disable the remote wakeup for. | 658 | * @adev: ACPI device to enable/disable wakeup functionality for. |
659 | * @target_state: State the system is transitioning into. | ||
623 | * @enable: Whether to enable or disable the wakeup functionality. | 660 | * @enable: Whether to enable or disable the wakeup functionality. |
624 | * | 661 | * |
625 | * Enable/disable the GPE associated with @adev so that it can generate | 662 | * Enable/disable the GPE associated with @adev so that it can generate |
@@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) | |||
629 | * Callers must ensure that @adev is a valid ACPI device node before executing | 666 | * Callers must ensure that @adev is a valid ACPI device node before executing |
630 | * this function. | 667 | * this function. |
631 | */ | 668 | */ |
632 | int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | 669 | static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state, |
670 | bool enable) | ||
633 | { | 671 | { |
634 | struct acpi_device_wakeup *wakeup = &adev->wakeup; | 672 | struct acpi_device_wakeup *wakeup = &adev->wakeup; |
635 | 673 | ||
@@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | |||
637 | acpi_status res; | 675 | acpi_status res; |
638 | int error; | 676 | int error; |
639 | 677 | ||
640 | error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0); | 678 | error = acpi_enable_wakeup_device_power(adev, target_state); |
641 | if (error) | 679 | if (error) |
642 | return error; | 680 | return error; |
643 | 681 | ||
@@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | |||
653 | return 0; | 691 | return 0; |
654 | } | 692 | } |
655 | 693 | ||
694 | #ifdef CONFIG_PM_RUNTIME | ||
656 | /** | 695 | /** |
657 | * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. | 696 | * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. |
658 | * @dev: Device to enable/disable the platform to wake up. | 697 | * @dev: Device to enable/disable the platform to wake up. |
@@ -661,63 +700,42 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | |||
661 | int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) | 700 | int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) |
662 | { | 701 | { |
663 | struct acpi_device *adev; | 702 | struct acpi_device *adev; |
664 | acpi_handle handle; | ||
665 | 703 | ||
666 | if (!device_run_wake(phys_dev)) | 704 | if (!device_run_wake(phys_dev)) |
667 | return -EINVAL; | 705 | return -EINVAL; |
668 | 706 | ||
669 | handle = ACPI_HANDLE(phys_dev); | 707 | adev = ACPI_COMPANION(phys_dev); |
670 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 708 | if (!adev) { |
671 | dev_dbg(phys_dev, "ACPI handle without context in %s!\n", | 709 | dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__); |
672 | __func__); | ||
673 | return -ENODEV; | 710 | return -ENODEV; |
674 | } | 711 | } |
675 | 712 | ||
676 | return __acpi_device_run_wake(adev, enable); | 713 | return acpi_device_wakeup(adev, enable, ACPI_STATE_S0); |
677 | } | 714 | } |
678 | EXPORT_SYMBOL(acpi_pm_device_run_wake); | 715 | EXPORT_SYMBOL(acpi_pm_device_run_wake); |
679 | #else | ||
680 | static inline void acpi_wakeup_device(acpi_handle handle, u32 event, | ||
681 | void *context) {} | ||
682 | #endif /* CONFIG_PM_RUNTIME */ | 716 | #endif /* CONFIG_PM_RUNTIME */ |
683 | 717 | ||
684 | #ifdef CONFIG_PM_SLEEP | 718 | #ifdef CONFIG_PM_SLEEP |
685 | /** | 719 | /** |
686 | * __acpi_device_sleep_wake - Enable or disable device to wake up the system. | ||
687 | * @dev: Device to enable/desible to wake up the system. | ||
688 | * @target_state: System state the device is supposed to wake up from. | ||
689 | * @enable: Whether to enable or disable @dev to wake up the system. | ||
690 | */ | ||
691 | int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state, | ||
692 | bool enable) | ||
693 | { | ||
694 | return enable ? | ||
695 | acpi_enable_wakeup_device_power(adev, target_state) : | ||
696 | acpi_disable_wakeup_device_power(adev); | ||
697 | } | ||
698 | |||
699 | /** | ||
700 | * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. | 720 | * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. |
701 | * @dev: Device to enable/desible to wake up the system from sleep states. | 721 | * @dev: Device to enable/desible to wake up the system from sleep states. |
702 | * @enable: Whether to enable or disable @dev to wake up the system. | 722 | * @enable: Whether to enable or disable @dev to wake up the system. |
703 | */ | 723 | */ |
704 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | 724 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) |
705 | { | 725 | { |
706 | acpi_handle handle; | ||
707 | struct acpi_device *adev; | 726 | struct acpi_device *adev; |
708 | int error; | 727 | int error; |
709 | 728 | ||
710 | if (!device_can_wakeup(dev)) | 729 | if (!device_can_wakeup(dev)) |
711 | return -EINVAL; | 730 | return -EINVAL; |
712 | 731 | ||
713 | handle = ACPI_HANDLE(dev); | 732 | adev = ACPI_COMPANION(dev); |
714 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 733 | if (!adev) { |
715 | dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); | 734 | dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); |
716 | return -ENODEV; | 735 | return -ENODEV; |
717 | } | 736 | } |
718 | 737 | ||
719 | error = __acpi_device_sleep_wake(adev, acpi_target_system_state(), | 738 | error = acpi_device_wakeup(adev, acpi_target_system_state(), enable); |
720 | enable); | ||
721 | if (!error) | 739 | if (!error) |
722 | dev_info(dev, "System wakeup %s by ACPI\n", | 740 | dev_info(dev, "System wakeup %s by ACPI\n", |
723 | enable ? "enabled" : "disabled"); | 741 | enable ? "enabled" : "disabled"); |
@@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct device *dev) | |||
775 | 793 | ||
776 | remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > | 794 | remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > |
777 | PM_QOS_FLAGS_NONE; | 795 | PM_QOS_FLAGS_NONE; |
778 | error = __acpi_device_run_wake(adev, remote_wakeup); | 796 | error = acpi_device_wakeup(adev, ACPI_STATE_S0, remote_wakeup); |
779 | if (remote_wakeup && error) | 797 | if (remote_wakeup && error) |
780 | return -EAGAIN; | 798 | return -EAGAIN; |
781 | 799 | ||
782 | error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); | 800 | error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); |
783 | if (error) | 801 | if (error) |
784 | __acpi_device_run_wake(adev, false); | 802 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
785 | 803 | ||
786 | return error; | 804 | return error; |
787 | } | 805 | } |
@@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct device *dev) | |||
804 | return 0; | 822 | return 0; |
805 | 823 | ||
806 | error = acpi_dev_pm_full_power(adev); | 824 | error = acpi_dev_pm_full_power(adev); |
807 | __acpi_device_run_wake(adev, false); | 825 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
808 | return error; | 826 | return error; |
809 | } | 827 | } |
810 | EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); | 828 | EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); |
@@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device *dev) | |||
860 | 878 | ||
861 | target_state = acpi_target_system_state(); | 879 | target_state = acpi_target_system_state(); |
862 | wakeup = device_may_wakeup(dev); | 880 | wakeup = device_may_wakeup(dev); |
863 | error = __acpi_device_sleep_wake(adev, target_state, wakeup); | 881 | error = acpi_device_wakeup(adev, target_state, wakeup); |
864 | if (wakeup && error) | 882 | if (wakeup && error) |
865 | return error; | 883 | return error; |
866 | 884 | ||
867 | error = acpi_dev_pm_low_power(dev, adev, target_state); | 885 | error = acpi_dev_pm_low_power(dev, adev, target_state); |
868 | if (error) | 886 | if (error) |
869 | __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); | 887 | acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); |
870 | 888 | ||
871 | return error; | 889 | return error; |
872 | } | 890 | } |
@@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device *dev) | |||
889 | return 0; | 907 | return 0; |
890 | 908 | ||
891 | error = acpi_dev_pm_full_power(adev); | 909 | error = acpi_dev_pm_full_power(adev); |
892 | __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); | 910 | acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); |
893 | return error; | 911 | return error; |
894 | } | 912 | } |
895 | EXPORT_SYMBOL_GPL(acpi_dev_resume_early); | 913 | EXPORT_SYMBOL_GPL(acpi_dev_resume_early); |
@@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) | |||
1048 | if (dev->pm_domain) | 1066 | if (dev->pm_domain) |
1049 | return -EEXIST; | 1067 | return -EEXIST; |
1050 | 1068 | ||
1051 | acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); | 1069 | acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); |
1052 | dev->pm_domain = &acpi_general_pm_domain; | 1070 | dev->pm_domain = &acpi_general_pm_domain; |
1053 | if (power_on) { | 1071 | if (power_on) { |
1054 | acpi_dev_pm_full_power(adev); | 1072 | acpi_dev_pm_full_power(adev); |
1055 | __acpi_device_run_wake(adev, false); | 1073 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
1056 | } | 1074 | } |
1057 | return 0; | 1075 | return 0; |
1058 | } | 1076 | } |
@@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) | |||
1076 | 1094 | ||
1077 | if (adev && dev->pm_domain == &acpi_general_pm_domain) { | 1095 | if (adev && dev->pm_domain == &acpi_general_pm_domain) { |
1078 | dev->pm_domain = NULL; | 1096 | dev->pm_domain = NULL; |
1079 | acpi_remove_pm_notifier(adev, acpi_wakeup_device); | 1097 | acpi_remove_pm_notifier(adev); |
1080 | if (power_off) { | 1098 | if (power_off) { |
1081 | /* | 1099 | /* |
1082 | * If the device's PM QoS resume latency limit or flags | 1100 | * If the device's PM QoS resume latency limit or flags |
@@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) | |||
1086 | */ | 1104 | */ |
1087 | dev_pm_qos_hide_latency_limit(dev); | 1105 | dev_pm_qos_hide_latency_limit(dev); |
1088 | dev_pm_qos_hide_flags(dev); | 1106 | dev_pm_qos_hide_flags(dev); |
1089 | __acpi_device_run_wake(adev, false); | 1107 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
1090 | acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); | 1108 | acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); |
1091 | } | 1109 | } |
1092 | } | 1110 | } |