aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/sleep/main.c')
-rw-r--r--drivers/acpi/sleep/main.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index d13194a031bf..c7f0c9cd8701 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -15,6 +15,7 @@
15#include <linux/dmi.h> 15#include <linux/dmi.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/suspend.h> 17#include <linux/suspend.h>
18#include <linux/reboot.h>
18 19
19#include <asm/io.h> 20#include <asm/io.h>
20 21
@@ -24,6 +25,36 @@
24 25
25u8 sleep_states[ACPI_S_STATE_COUNT]; 26u8 sleep_states[ACPI_S_STATE_COUNT];
26 27
28static void acpi_sleep_tts_switch(u32 acpi_state)
29{
30 union acpi_object in_arg = { ACPI_TYPE_INTEGER };
31 struct acpi_object_list arg_list = { 1, &in_arg };
32 acpi_status status = AE_OK;
33
34 in_arg.integer.value = acpi_state;
35 status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
36 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
37 /*
38 * OS can't evaluate the _TTS object correctly. Some warning
39 * message will be printed. But it won't break anything.
40 */
41 printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
42 }
43}
44
45static int tts_notify_reboot(struct notifier_block *this,
46 unsigned long code, void *x)
47{
48 acpi_sleep_tts_switch(ACPI_STATE_S5);
49 return NOTIFY_DONE;
50}
51
52static struct notifier_block tts_notifier = {
53 .notifier_call = tts_notify_reboot,
54 .next = NULL,
55 .priority = 0,
56};
57
27static int acpi_sleep_prepare(u32 acpi_state) 58static int acpi_sleep_prepare(u32 acpi_state)
28{ 59{
29#ifdef CONFIG_ACPI_SLEEP 60#ifdef CONFIG_ACPI_SLEEP
@@ -131,6 +162,7 @@ static void acpi_pm_end(void)
131 * failing transition to a sleep state. 162 * failing transition to a sleep state.
132 */ 163 */
133 acpi_target_sleep_state = ACPI_STATE_S0; 164 acpi_target_sleep_state = ACPI_STATE_S0;
165 acpi_sleep_tts_switch(acpi_target_sleep_state);
134} 166}
135#endif /* CONFIG_PM_SLEEP */ 167#endif /* CONFIG_PM_SLEEP */
136 168
@@ -155,6 +187,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
155 187
156 if (sleep_states[acpi_state]) { 188 if (sleep_states[acpi_state]) {
157 acpi_target_sleep_state = acpi_state; 189 acpi_target_sleep_state = acpi_state;
190 acpi_sleep_tts_switch(acpi_target_sleep_state);
158 } else { 191 } else {
159 printk(KERN_ERR "ACPI does not support this state: %d\n", 192 printk(KERN_ERR "ACPI does not support this state: %d\n",
160 pm_state); 193 pm_state);
@@ -313,6 +346,7 @@ void __init acpi_no_s4_hw_signature(void)
313static int acpi_hibernation_begin(void) 346static int acpi_hibernation_begin(void)
314{ 347{
315 acpi_target_sleep_state = ACPI_STATE_S4; 348 acpi_target_sleep_state = ACPI_STATE_S4;
349 acpi_sleep_tts_switch(acpi_target_sleep_state);
316 return 0; 350 return 0;
317} 351}
318 352
@@ -376,7 +410,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
376 */ 410 */
377static int acpi_hibernation_begin_old(void) 411static int acpi_hibernation_begin_old(void)
378{ 412{
379 int error = acpi_sleep_prepare(ACPI_STATE_S4); 413 int error;
414 /*
415 * The _TTS object should always be evaluated before the _PTS object.
416 * When the old_suspended_ordering is true, the _PTS object is
417 * evaluated in the acpi_sleep_prepare.
418 */
419 acpi_sleep_tts_switch(ACPI_STATE_S4);
420
421 error = acpi_sleep_prepare(ACPI_STATE_S4);
380 422
381 if (!error) 423 if (!error)
382 acpi_target_sleep_state = ACPI_STATE_S4; 424 acpi_target_sleep_state = ACPI_STATE_S4;
@@ -596,5 +638,10 @@ int __init acpi_sleep_init(void)
596 pm_power_off = acpi_power_off; 638 pm_power_off = acpi_power_off;
597 } 639 }
598 printk(")\n"); 640 printk(")\n");
641 /*
642 * Register the tts_notifier to reboot notifier list so that the _TTS
643 * object can also be evaluated when the system enters S5.
644 */
645 register_reboot_notifier(&tts_notifier);
599 return 0; 646 return 0;
600} 647}