diff options
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r-- | drivers/acpi/sleep.c | 103 |
1 files changed, 32 insertions, 71 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 88561029cca8..fdcdbb652915 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -28,36 +28,7 @@ | |||
28 | #include "internal.h" | 28 | #include "internal.h" |
29 | #include "sleep.h" | 29 | #include "sleep.h" |
30 | 30 | ||
31 | u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS; | ||
32 | static unsigned int gts, bfs; | ||
33 | static int set_param_wake_flag(const char *val, struct kernel_param *kp) | ||
34 | { | ||
35 | int ret = param_set_int(val, kp); | ||
36 | |||
37 | if (ret) | ||
38 | return ret; | ||
39 | |||
40 | if (kp->arg == (const char *)>s) { | ||
41 | if (gts) | ||
42 | wake_sleep_flags |= ACPI_EXECUTE_GTS; | ||
43 | else | ||
44 | wake_sleep_flags &= ~ACPI_EXECUTE_GTS; | ||
45 | } | ||
46 | if (kp->arg == (const char *)&bfs) { | ||
47 | if (bfs) | ||
48 | wake_sleep_flags |= ACPI_EXECUTE_BFS; | ||
49 | else | ||
50 | wake_sleep_flags &= ~ACPI_EXECUTE_BFS; | ||
51 | } | ||
52 | return ret; | ||
53 | } | ||
54 | module_param_call(gts, set_param_wake_flag, param_get_int, >s, 0644); | ||
55 | module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644); | ||
56 | MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); | ||
57 | MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); | ||
58 | |||
59 | static u8 sleep_states[ACPI_S_STATE_COUNT]; | 31 | static u8 sleep_states[ACPI_S_STATE_COUNT]; |
60 | static bool pwr_btn_event_pending; | ||
61 | 32 | ||
62 | static void acpi_sleep_tts_switch(u32 acpi_state) | 33 | static void acpi_sleep_tts_switch(u32 acpi_state) |
63 | { | 34 | { |
@@ -110,6 +81,7 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
110 | 81 | ||
111 | #ifdef CONFIG_ACPI_SLEEP | 82 | #ifdef CONFIG_ACPI_SLEEP |
112 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 83 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
84 | static bool pwr_btn_event_pending; | ||
113 | 85 | ||
114 | /* | 86 | /* |
115 | * The ACPI specification wants us to save NVS memory regions during hibernation | 87 | * The ACPI specification wants us to save NVS memory regions during hibernation |
@@ -143,7 +115,7 @@ void __init acpi_old_suspend_ordering(void) | |||
143 | static int acpi_pm_freeze(void) | 115 | static int acpi_pm_freeze(void) |
144 | { | 116 | { |
145 | acpi_disable_all_gpes(); | 117 | acpi_disable_all_gpes(); |
146 | acpi_os_wait_events_complete(NULL); | 118 | acpi_os_wait_events_complete(); |
147 | acpi_ec_block_transactions(); | 119 | acpi_ec_block_transactions(); |
148 | return 0; | 120 | return 0; |
149 | } | 121 | } |
@@ -305,7 +277,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
305 | switch (acpi_state) { | 277 | switch (acpi_state) { |
306 | case ACPI_STATE_S1: | 278 | case ACPI_STATE_S1: |
307 | barrier(); | 279 | barrier(); |
308 | status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags); | 280 | status = acpi_enter_sleep_state(acpi_state); |
309 | break; | 281 | break; |
310 | 282 | ||
311 | case ACPI_STATE_S3: | 283 | case ACPI_STATE_S3: |
@@ -319,8 +291,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
319 | /* This violates the spec but is required for bug compatibility. */ | 291 | /* This violates the spec but is required for bug compatibility. */ |
320 | acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); | 292 | acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); |
321 | 293 | ||
322 | /* Reprogram control registers and execute _BFS */ | 294 | /* Reprogram control registers */ |
323 | acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags); | 295 | acpi_leave_sleep_state_prep(acpi_state); |
324 | 296 | ||
325 | /* ACPI 3.0 specs (P62) says that it's the responsibility | 297 | /* ACPI 3.0 specs (P62) says that it's the responsibility |
326 | * of the OSPM to clear the status bit [ implying that the | 298 | * of the OSPM to clear the status bit [ implying that the |
@@ -603,9 +575,9 @@ static int acpi_hibernation_enter(void) | |||
603 | ACPI_FLUSH_CPU_CACHE(); | 575 | ACPI_FLUSH_CPU_CACHE(); |
604 | 576 | ||
605 | /* This shouldn't return. If it returns, we have a problem */ | 577 | /* This shouldn't return. If it returns, we have a problem */ |
606 | status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags); | 578 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
607 | /* Reprogram control registers and execute _BFS */ | 579 | /* Reprogram control registers */ |
608 | acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); | 580 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); |
609 | 581 | ||
610 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 582 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
611 | } | 583 | } |
@@ -617,8 +589,8 @@ static void acpi_hibernation_leave(void) | |||
617 | * enable it here. | 589 | * enable it here. |
618 | */ | 590 | */ |
619 | acpi_enable(); | 591 | acpi_enable(); |
620 | /* Reprogram control registers and execute _BFS */ | 592 | /* Reprogram control registers */ |
621 | acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); | 593 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); |
622 | /* Check the hardware signature */ | 594 | /* Check the hardware signature */ |
623 | if (facs && s4_hardware_signature != facs->hardware_signature) { | 595 | if (facs && s4_hardware_signature != facs->hardware_signature) { |
624 | printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " | 596 | printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " |
@@ -716,8 +688,9 @@ int acpi_suspend(u32 acpi_state) | |||
716 | * @dev: device to examine; its driver model wakeup flags control | 688 | * @dev: device to examine; its driver model wakeup flags control |
717 | * whether it should be able to wake up the system | 689 | * whether it should be able to wake up the system |
718 | * @d_min_p: used to store the upper limit of allowed states range | 690 | * @d_min_p: used to store the upper limit of allowed states range |
719 | * Return value: preferred power state of the device on success, -ENODEV on | 691 | * @d_max_in: specify the lowest allowed states |
720 | * failure (ie. if there's no 'struct acpi_device' for @dev) | 692 | * Return value: preferred power state of the device on success, -ENODEV |
693 | * (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure | ||
721 | * | 694 | * |
722 | * Find the lowest power (highest number) ACPI device power state that | 695 | * Find the lowest power (highest number) ACPI device power state that |
723 | * device @dev can be in while the system is in the sleep state represented | 696 | * device @dev can be in while the system is in the sleep state represented |
@@ -732,13 +705,15 @@ int acpi_suspend(u32 acpi_state) | |||
732 | * via @wake. | 705 | * via @wake. |
733 | */ | 706 | */ |
734 | 707 | ||
735 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | 708 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) |
736 | { | 709 | { |
737 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); | 710 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); |
738 | struct acpi_device *adev; | 711 | struct acpi_device *adev; |
739 | char acpi_method[] = "_SxD"; | 712 | char acpi_method[] = "_SxD"; |
740 | unsigned long long d_min, d_max; | 713 | unsigned long long d_min, d_max; |
741 | 714 | ||
715 | if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3) | ||
716 | return -EINVAL; | ||
742 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { | 717 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { |
743 | printk(KERN_DEBUG "ACPI handle has no context!\n"); | 718 | printk(KERN_DEBUG "ACPI handle has no context!\n"); |
744 | return -ENODEV; | 719 | return -ENODEV; |
@@ -746,8 +721,10 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
746 | 721 | ||
747 | acpi_method[2] = '0' + acpi_target_sleep_state; | 722 | acpi_method[2] = '0' + acpi_target_sleep_state; |
748 | /* | 723 | /* |
749 | * If the sleep state is S0, we will return D3, but if the device has | 724 | * If the sleep state is S0, the lowest limit from ACPI is D3, |
750 | * _S0W, we will use the value from _S0W | 725 | * but if the device has _S0W, we will use the value from _S0W |
726 | * as the lowest limit from ACPI. Finally, we will constrain | ||
727 | * the lowest limit with the specified one. | ||
751 | */ | 728 | */ |
752 | d_min = ACPI_STATE_D0; | 729 | d_min = ACPI_STATE_D0; |
753 | d_max = ACPI_STATE_D3; | 730 | d_max = ACPI_STATE_D3; |
@@ -791,10 +768,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
791 | } | 768 | } |
792 | } | 769 | } |
793 | 770 | ||
771 | if (d_max_in < d_min) | ||
772 | return -EINVAL; | ||
794 | if (d_min_p) | 773 | if (d_min_p) |
795 | *d_min_p = d_min; | 774 | *d_min_p = d_min; |
775 | /* constrain d_max with specified lowest limit (max number) */ | ||
776 | if (d_max > d_max_in) { | ||
777 | for (d_max = d_max_in; d_max > d_min; d_max--) { | ||
778 | if (adev->power.states[d_max].flags.valid) | ||
779 | break; | ||
780 | } | ||
781 | } | ||
796 | return d_max; | 782 | return d_max; |
797 | } | 783 | } |
784 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); | ||
798 | #endif /* CONFIG_PM */ | 785 | #endif /* CONFIG_PM */ |
799 | 786 | ||
800 | #ifdef CONFIG_PM_SLEEP | 787 | #ifdef CONFIG_PM_SLEEP |
@@ -831,6 +818,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) | |||
831 | 818 | ||
832 | return 0; | 819 | return 0; |
833 | } | 820 | } |
821 | EXPORT_SYMBOL(acpi_pm_device_run_wake); | ||
834 | 822 | ||
835 | /** | 823 | /** |
836 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | 824 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up |
@@ -876,33 +864,7 @@ static void acpi_power_off(void) | |||
876 | /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ | 864 | /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ |
877 | printk(KERN_DEBUG "%s called\n", __func__); | 865 | printk(KERN_DEBUG "%s called\n", __func__); |
878 | local_irq_disable(); | 866 | local_irq_disable(); |
879 | acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags); | 867 | acpi_enter_sleep_state(ACPI_STATE_S5); |
880 | } | ||
881 | |||
882 | /* | ||
883 | * ACPI 2.0 created the optional _GTS and _BFS, | ||
884 | * but industry adoption has been neither rapid nor broad. | ||
885 | * | ||
886 | * Linux gets into trouble when it executes poorly validated | ||
887 | * paths through the BIOS, so disable _GTS and _BFS by default, | ||
888 | * but do speak up and offer the option to enable them. | ||
889 | */ | ||
890 | static void __init acpi_gts_bfs_check(void) | ||
891 | { | ||
892 | acpi_handle dummy; | ||
893 | |||
894 | if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__GTS, &dummy))) | ||
895 | { | ||
896 | printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n"); | ||
897 | printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, " | ||
898 | "please notify linux-acpi@vger.kernel.org\n"); | ||
899 | } | ||
900 | if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__BFS, &dummy))) | ||
901 | { | ||
902 | printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n"); | ||
903 | printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, " | ||
904 | "please notify linux-acpi@vger.kernel.org\n"); | ||
905 | } | ||
906 | } | 868 | } |
907 | 869 | ||
908 | int __init acpi_sleep_init(void) | 870 | int __init acpi_sleep_init(void) |
@@ -963,6 +925,5 @@ int __init acpi_sleep_init(void) | |||
963 | * object can also be evaluated when the system enters S5. | 925 | * object can also be evaluated when the system enters S5. |
964 | */ | 926 | */ |
965 | register_reboot_notifier(&tts_notifier); | 927 | register_reboot_notifier(&tts_notifier); |
966 | acpi_gts_bfs_check(); | ||
967 | return 0; | 928 | return 0; |
968 | } | 929 | } |