diff options
Diffstat (limited to 'drivers/acpi/sleep/main.c')
-rw-r--r-- | drivers/acpi/sleep/main.c | 49 |
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 | ||
25 | u8 sleep_states[ACPI_S_STATE_COUNT]; | 26 | u8 sleep_states[ACPI_S_STATE_COUNT]; |
26 | 27 | ||
28 | static 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 | |||
45 | static 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 | |||
52 | static struct notifier_block tts_notifier = { | ||
53 | .notifier_call = tts_notify_reboot, | ||
54 | .next = NULL, | ||
55 | .priority = 0, | ||
56 | }; | ||
57 | |||
27 | static int acpi_sleep_prepare(u32 acpi_state) | 58 | static 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) | |||
313 | static int acpi_hibernation_begin(void) | 346 | static 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 | */ |
377 | static int acpi_hibernation_begin_old(void) | 411 | static 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 | } |