diff options
author | Len Brown <len.brown@intel.com> | 2008-10-22 23:28:46 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-10-22 23:28:46 -0400 |
commit | acd41d36e5a813501da92156f325ce15ddcd58ff (patch) | |
tree | daaca230153261b13e6d1989a977352e2c29a3d4 /drivers/acpi | |
parent | 4dff4e7f6cbcd2722b02dbb394ba87c4e05f8841 (diff) | |
parent | 4fb507b6b764195bb7821cf2baa988f6eb677d30 (diff) |
Merge branch 'suspend' into test
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/hardware/hwsleep.c | 44 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 59 |
2 files changed, 76 insertions, 27 deletions
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index dba3cfbe8cba..25dccdf179b9 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c | |||
@@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) | |||
78 | return_ACPI_STATUS(status); | 78 | return_ACPI_STATUS(status); |
79 | } | 79 | } |
80 | 80 | ||
81 | /* Set the vector */ | 81 | /* |
82 | * According to the ACPI specification 2.0c and later, the 64-bit | ||
83 | * waking vector should be cleared and the 32-bit waking vector should | ||
84 | * be used, unless we want the wake-up code to be called by the BIOS in | ||
85 | * Protected Mode. Some systems (for example HP dv5-1004nr) are known | ||
86 | * to fail to resume if the 64-bit vector is used. | ||
87 | */ | ||
88 | if (facs->version >= 1) | ||
89 | facs->xfirmware_waking_vector = 0; | ||
82 | 90 | ||
83 | if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { | 91 | facs->firmware_waking_vector = (u32)physical_address; |
84 | /* | ||
85 | * ACPI 1.0 FACS or short table or optional X_ field is zero | ||
86 | */ | ||
87 | facs->firmware_waking_vector = (u32) physical_address; | ||
88 | } else { | ||
89 | /* | ||
90 | * ACPI 2.0 FACS with valid X_ field | ||
91 | */ | ||
92 | facs->xfirmware_waking_vector = physical_address; | ||
93 | } | ||
94 | 92 | ||
95 | return_ACPI_STATUS(AE_OK); | 93 | return_ACPI_STATUS(AE_OK); |
96 | } | 94 | } |
@@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) | |||
134 | } | 132 | } |
135 | 133 | ||
136 | /* Get the vector */ | 134 | /* Get the vector */ |
137 | 135 | *physical_address = (acpi_physical_address)facs->firmware_waking_vector; | |
138 | if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { | ||
139 | /* | ||
140 | * ACPI 1.0 FACS or short table or optional X_ field is zero | ||
141 | */ | ||
142 | *physical_address = | ||
143 | (acpi_physical_address) facs->firmware_waking_vector; | ||
144 | } else { | ||
145 | /* | ||
146 | * ACPI 2.0 FACS with valid X_ field | ||
147 | */ | ||
148 | *physical_address = | ||
149 | (acpi_physical_address) facs->xfirmware_waking_vector; | ||
150 | } | ||
151 | 136 | ||
152 | return_ACPI_STATUS(AE_OK); | 137 | return_ACPI_STATUS(AE_OK); |
153 | } | 138 | } |
@@ -627,6 +612,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
627 | } | 612 | } |
628 | /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ | 613 | /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ |
629 | 614 | ||
615 | /* | ||
616 | * Some BIOSes assume that WAK_STS will be cleared on resume and use | ||
617 | * it to determine whether the system is rebooting or resuming. Clear | ||
618 | * it for compatibility. | ||
619 | */ | ||
620 | acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); | ||
621 | |||
630 | acpi_gbl_system_awake_and_running = TRUE; | 622 | acpi_gbl_system_awake_and_running = TRUE; |
631 | 623 | ||
632 | /* Enable power button */ | 624 | /* Enable power button */ |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 4c21480b5820..cc344d4252c9 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 | ||
@@ -25,6 +26,36 @@ | |||
25 | u8 sleep_states[ACPI_S_STATE_COUNT]; | 26 | u8 sleep_states[ACPI_S_STATE_COUNT]; |
26 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 27 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
27 | 28 | ||
29 | static void acpi_sleep_tts_switch(u32 acpi_state) | ||
30 | { | ||
31 | union acpi_object in_arg = { ACPI_TYPE_INTEGER }; | ||
32 | struct acpi_object_list arg_list = { 1, &in_arg }; | ||
33 | acpi_status status = AE_OK; | ||
34 | |||
35 | in_arg.integer.value = acpi_state; | ||
36 | status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); | ||
37 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
38 | /* | ||
39 | * OS can't evaluate the _TTS object correctly. Some warning | ||
40 | * message will be printed. But it won't break anything. | ||
41 | */ | ||
42 | printk(KERN_NOTICE "Failure in evaluating _TTS object\n"); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static int tts_notify_reboot(struct notifier_block *this, | ||
47 | unsigned long code, void *x) | ||
48 | { | ||
49 | acpi_sleep_tts_switch(ACPI_STATE_S5); | ||
50 | return NOTIFY_DONE; | ||
51 | } | ||
52 | |||
53 | static struct notifier_block tts_notifier = { | ||
54 | .notifier_call = tts_notify_reboot, | ||
55 | .next = NULL, | ||
56 | .priority = 0, | ||
57 | }; | ||
58 | |||
28 | static int acpi_sleep_prepare(u32 acpi_state) | 59 | static int acpi_sleep_prepare(u32 acpi_state) |
29 | { | 60 | { |
30 | #ifdef CONFIG_ACPI_SLEEP | 61 | #ifdef CONFIG_ACPI_SLEEP |
@@ -130,6 +161,7 @@ static void acpi_pm_end(void) | |||
130 | * failing transition to a sleep state. | 161 | * failing transition to a sleep state. |
131 | */ | 162 | */ |
132 | acpi_target_sleep_state = ACPI_STATE_S0; | 163 | acpi_target_sleep_state = ACPI_STATE_S0; |
164 | acpi_sleep_tts_switch(acpi_target_sleep_state); | ||
133 | } | 165 | } |
134 | #endif /* CONFIG_ACPI_SLEEP */ | 166 | #endif /* CONFIG_ACPI_SLEEP */ |
135 | 167 | ||
@@ -154,6 +186,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
154 | 186 | ||
155 | if (sleep_states[acpi_state]) { | 187 | if (sleep_states[acpi_state]) { |
156 | acpi_target_sleep_state = acpi_state; | 188 | acpi_target_sleep_state = acpi_state; |
189 | acpi_sleep_tts_switch(acpi_target_sleep_state); | ||
157 | } else { | 190 | } else { |
158 | printk(KERN_ERR "ACPI does not support this state: %d\n", | 191 | printk(KERN_ERR "ACPI does not support this state: %d\n", |
159 | pm_state); | 192 | pm_state); |
@@ -199,6 +232,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
199 | break; | 232 | break; |
200 | } | 233 | } |
201 | 234 | ||
235 | /* If ACPI is not enabled by the BIOS, we need to enable it here. */ | ||
236 | acpi_enable(); | ||
202 | /* Reprogram control registers and execute _BFS */ | 237 | /* Reprogram control registers and execute _BFS */ |
203 | acpi_leave_sleep_state_prep(acpi_state); | 238 | acpi_leave_sleep_state_prep(acpi_state); |
204 | 239 | ||
@@ -295,6 +330,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
295 | DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), | 330 | DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), |
296 | }, | 331 | }, |
297 | }, | 332 | }, |
333 | { | ||
334 | .callback = init_old_suspend_ordering, | ||
335 | .ident = "HP xw4600 Workstation", | ||
336 | .matches = { | ||
337 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
338 | DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), | ||
339 | }, | ||
340 | }, | ||
298 | {}, | 341 | {}, |
299 | }; | 342 | }; |
300 | #endif /* CONFIG_SUSPEND */ | 343 | #endif /* CONFIG_SUSPEND */ |
@@ -312,6 +355,7 @@ void __init acpi_no_s4_hw_signature(void) | |||
312 | static int acpi_hibernation_begin(void) | 355 | static int acpi_hibernation_begin(void) |
313 | { | 356 | { |
314 | acpi_target_sleep_state = ACPI_STATE_S4; | 357 | acpi_target_sleep_state = ACPI_STATE_S4; |
358 | acpi_sleep_tts_switch(acpi_target_sleep_state); | ||
315 | return 0; | 359 | return 0; |
316 | } | 360 | } |
317 | 361 | ||
@@ -375,7 +419,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { | |||
375 | */ | 419 | */ |
376 | static int acpi_hibernation_begin_old(void) | 420 | static int acpi_hibernation_begin_old(void) |
377 | { | 421 | { |
378 | int error = acpi_sleep_prepare(ACPI_STATE_S4); | 422 | int error; |
423 | /* | ||
424 | * The _TTS object should always be evaluated before the _PTS object. | ||
425 | * When the old_suspended_ordering is true, the _PTS object is | ||
426 | * evaluated in the acpi_sleep_prepare. | ||
427 | */ | ||
428 | acpi_sleep_tts_switch(ACPI_STATE_S4); | ||
429 | |||
430 | error = acpi_sleep_prepare(ACPI_STATE_S4); | ||
379 | 431 | ||
380 | if (!error) | 432 | if (!error) |
381 | acpi_target_sleep_state = ACPI_STATE_S4; | 433 | acpi_target_sleep_state = ACPI_STATE_S4; |
@@ -595,5 +647,10 @@ int __init acpi_sleep_init(void) | |||
595 | pm_power_off = acpi_power_off; | 647 | pm_power_off = acpi_power_off; |
596 | } | 648 | } |
597 | printk(")\n"); | 649 | printk(")\n"); |
650 | /* | ||
651 | * Register the tts_notifier to reboot notifier list so that the _TTS | ||
652 | * object can also be evaluated when the system enters S5. | ||
653 | */ | ||
654 | register_reboot_notifier(&tts_notifier); | ||
598 | return 0; | 655 | return 0; |
599 | } | 656 | } |