aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2008-08-11 22:20:22 -0400
committerLen Brown <len.brown@intel.com>2008-10-16 20:45:18 -0400
commite49f711cc8f3bf8d719a9f5c86e79ecc0a72bf70 (patch)
treeb3b3dcdfd5000ba62e79a47a7680dcb833d35007 /drivers/acpi/sleep
parenta68823ee5285e65b51ceb96f8b13a5b4f99a6888 (diff)
ACPI: Add the support for _TTS object
The _TTS object is defined in the section 7.3 of acpi 3.0b spec. The _TTS control method is executed by the OSPM at the beginning of the sleep transition process for S1,S2, S3, S4, and orderly S5 shutdown. OS will invoke _TTS before it has notified any native mode device drivers of the sleep state transition. The target sleeping state value is passed to the _TTS control method. The _TTS control method is also executed by the OSPM at the end of any sleep transition process when the system transitions to S0 from S1, S2, S3, or S4. The _TTS object should be evaluated after it has notified any native mode device drivers of the end of the sleep state transition. The working state value (0) is passed to the _TTS control method. So it is necessary to add the support for _TTS object. The _TTS object will be evaluated if it exists. At the same time a block notifier is added to the reboot notifier list so that the _TTS object will also be evaluated when the system shutdown. lenb: note that as of Sep 2008, I've not yet seen _TTS in any shipping BIOS. So this patch is to future-proof Linux, rather than fix the installed base. http://bugzilla.kernel.org/show_bug.cgi?id=11132 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/sleep')
-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}