diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 22:29:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 22:29:57 -0500 |
commit | 687fcdf741e4a268c2c7bac8b3734de761bb9719 (patch) | |
tree | 82603cd0f892b13d4252cc525ecaec99bb86c0cd /drivers | |
parent | 215e871aaa3d94540121a3809d80d0c5e5686e4f (diff) | |
parent | a6eb84bc1e069e1d285167e09035ed6c27978feb (diff) |
Merge branch 'suspend' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'suspend' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (38 commits)
suspend: cleanup reference to swsusp_pg_dir[]
PM: Remove obsolete /sys/devices/.../power/state docs
Hibernation: Invoke suspend notifications after console switch
Suspend: Invoke suspend notifications after console switch
Suspend: Clean up suspend_64.c
Suspend: Add config option to disable the freezer if architecture wants that
ACPI: Print message before calling _PTS
ACPI hibernation: Call _PTS before suspending devices
Hibernation: Introduce begin() and end() callbacks
ACPI suspend: Call _PTS before suspending devices
ACPI: Separate disabling of GPEs from _PTS
ACPI: Separate invocations of _GTS and _BFS from _PTS and _WAK
Suspend: Introduce begin() and end() callbacks
suspend: fix ia64 allmodconfig build
ACPI: clear GPE earily in resume to avoid warning
Suspend: Clean up Kconfig (V2)
Hibernation: Clean up Kconfig (V2)
Hibernation: Update messages
Suspend: Use common prefix in messages
Hibernation: Remove unnecessary variable declaration
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/hardware/hwsleep.c | 79 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 129 | ||||
-rw-r--r-- | drivers/acpi/sleep/sleep.h | 2 | ||||
-rw-r--r-- | drivers/base/power/Makefile | 2 |
4 files changed, 166 insertions, 46 deletions
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 81b248429703..fd1c4ba63367 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c | |||
@@ -192,18 +192,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | |||
192 | arg.type = ACPI_TYPE_INTEGER; | 192 | arg.type = ACPI_TYPE_INTEGER; |
193 | arg.integer.value = sleep_state; | 193 | arg.integer.value = sleep_state; |
194 | 194 | ||
195 | /* Run the _PTS and _GTS methods */ | 195 | /* Run the _PTS method */ |
196 | 196 | ||
197 | status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); | 197 | status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); |
198 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 198 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
199 | return_ACPI_STATUS(status); | 199 | return_ACPI_STATUS(status); |
200 | } | 200 | } |
201 | 201 | ||
202 | status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); | ||
203 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
204 | return_ACPI_STATUS(status); | ||
205 | } | ||
206 | |||
207 | /* Setup the argument to _SST */ | 202 | /* Setup the argument to _SST */ |
208 | 203 | ||
209 | switch (sleep_state) { | 204 | switch (sleep_state) { |
@@ -234,10 +229,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | |||
234 | "While executing method _SST")); | 229 | "While executing method _SST")); |
235 | } | 230 | } |
236 | 231 | ||
237 | /* Disable/Clear all GPEs */ | ||
238 | |||
239 | status = acpi_hw_disable_all_gpes(); | ||
240 | |||
241 | return_ACPI_STATUS(status); | 232 | return_ACPI_STATUS(status); |
242 | } | 233 | } |
243 | 234 | ||
@@ -262,6 +253,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
262 | struct acpi_bit_register_info *sleep_type_reg_info; | 253 | struct acpi_bit_register_info *sleep_type_reg_info; |
263 | struct acpi_bit_register_info *sleep_enable_reg_info; | 254 | struct acpi_bit_register_info *sleep_enable_reg_info; |
264 | u32 in_value; | 255 | u32 in_value; |
256 | struct acpi_object_list arg_list; | ||
257 | union acpi_object arg; | ||
265 | acpi_status status; | 258 | acpi_status status; |
266 | 259 | ||
267 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); | 260 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); |
@@ -307,6 +300,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
307 | return_ACPI_STATUS(status); | 300 | return_ACPI_STATUS(status); |
308 | } | 301 | } |
309 | 302 | ||
303 | /* Execute the _GTS method */ | ||
304 | |||
305 | arg_list.count = 1; | ||
306 | arg_list.pointer = &arg; | ||
307 | arg.type = ACPI_TYPE_INTEGER; | ||
308 | arg.integer.value = sleep_state; | ||
309 | |||
310 | status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); | ||
311 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
312 | return_ACPI_STATUS(status); | ||
313 | } | ||
314 | |||
310 | /* Get current value of PM1A control */ | 315 | /* Get current value of PM1A control */ |
311 | 316 | ||
312 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); | 317 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); |
@@ -473,17 +478,18 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) | |||
473 | 478 | ||
474 | /******************************************************************************* | 479 | /******************************************************************************* |
475 | * | 480 | * |
476 | * FUNCTION: acpi_leave_sleep_state | 481 | * FUNCTION: acpi_leave_sleep_state_prep |
477 | * | 482 | * |
478 | * PARAMETERS: sleep_state - Which sleep state we just exited | 483 | * PARAMETERS: sleep_state - Which sleep state we are exiting |
479 | * | 484 | * |
480 | * RETURN: Status | 485 | * RETURN: Status |
481 | * | 486 | * |
482 | * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep | 487 | * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a |
483 | * Called with interrupts ENABLED. | 488 | * sleep. |
489 | * Called with interrupts DISABLED. | ||
484 | * | 490 | * |
485 | ******************************************************************************/ | 491 | ******************************************************************************/ |
486 | acpi_status acpi_leave_sleep_state(u8 sleep_state) | 492 | acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) |
487 | { | 493 | { |
488 | struct acpi_object_list arg_list; | 494 | struct acpi_object_list arg_list; |
489 | union acpi_object arg; | 495 | union acpi_object arg; |
@@ -493,7 +499,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
493 | u32 PM1Acontrol; | 499 | u32 PM1Acontrol; |
494 | u32 PM1Bcontrol; | 500 | u32 PM1Bcontrol; |
495 | 501 | ||
496 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); | 502 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); |
497 | 503 | ||
498 | /* | 504 | /* |
499 | * Set SLP_TYPE and SLP_EN to state S0. | 505 | * Set SLP_TYPE and SLP_EN to state S0. |
@@ -540,6 +546,41 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
540 | } | 546 | } |
541 | } | 547 | } |
542 | 548 | ||
549 | /* Execute the _BFS method */ | ||
550 | |||
551 | arg_list.count = 1; | ||
552 | arg_list.pointer = &arg; | ||
553 | arg.type = ACPI_TYPE_INTEGER; | ||
554 | arg.integer.value = sleep_state; | ||
555 | |||
556 | status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); | ||
557 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
558 | ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); | ||
559 | } | ||
560 | |||
561 | return_ACPI_STATUS(status); | ||
562 | } | ||
563 | |||
564 | /******************************************************************************* | ||
565 | * | ||
566 | * FUNCTION: acpi_leave_sleep_state | ||
567 | * | ||
568 | * PARAMETERS: sleep_state - Which sleep state we just exited | ||
569 | * | ||
570 | * RETURN: Status | ||
571 | * | ||
572 | * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep | ||
573 | * Called with interrupts ENABLED. | ||
574 | * | ||
575 | ******************************************************************************/ | ||
576 | acpi_status acpi_leave_sleep_state(u8 sleep_state) | ||
577 | { | ||
578 | struct acpi_object_list arg_list; | ||
579 | union acpi_object arg; | ||
580 | acpi_status status; | ||
581 | |||
582 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); | ||
583 | |||
543 | /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ | 584 | /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ |
544 | 585 | ||
545 | acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; | 586 | acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; |
@@ -558,12 +599,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
558 | ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); | 599 | ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); |
559 | } | 600 | } |
560 | 601 | ||
561 | arg.integer.value = sleep_state; | ||
562 | status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); | ||
563 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
564 | ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); | ||
565 | } | ||
566 | |||
567 | /* | 602 | /* |
568 | * GPEs must be enabled before _WAK is called as GPEs | 603 | * GPEs must be enabled before _WAK is called as GPEs |
569 | * might get fired there | 604 | * might get fired there |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 2c0b6630f8ba..485de1347075 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -26,9 +26,24 @@ u8 sleep_states[ACPI_S_STATE_COUNT]; | |||
26 | 26 | ||
27 | #ifdef CONFIG_PM_SLEEP | 27 | #ifdef CONFIG_PM_SLEEP |
28 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 28 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
29 | static bool acpi_sleep_finish_wake_up; | ||
30 | |||
31 | /* | ||
32 | * ACPI 2.0 and later want us to execute _PTS after suspending devices, so we | ||
33 | * allow the user to request that behavior by using the 'acpi_new_pts_ordering' | ||
34 | * kernel command line option that causes the following variable to be set. | ||
35 | */ | ||
36 | static bool new_pts_ordering; | ||
37 | |||
38 | static int __init acpi_new_pts_ordering(char *str) | ||
39 | { | ||
40 | new_pts_ordering = true; | ||
41 | return 1; | ||
42 | } | ||
43 | __setup("acpi_new_pts_ordering", acpi_new_pts_ordering); | ||
29 | #endif | 44 | #endif |
30 | 45 | ||
31 | int acpi_sleep_prepare(u32 acpi_state) | 46 | static int acpi_sleep_prepare(u32 acpi_state) |
32 | { | 47 | { |
33 | #ifdef CONFIG_ACPI_SLEEP | 48 | #ifdef CONFIG_ACPI_SLEEP |
34 | /* do we have a wakeup address for S2 and S3? */ | 49 | /* do we have a wakeup address for S2 and S3? */ |
@@ -44,6 +59,8 @@ int acpi_sleep_prepare(u32 acpi_state) | |||
44 | ACPI_FLUSH_CPU_CACHE(); | 59 | ACPI_FLUSH_CPU_CACHE(); |
45 | acpi_enable_wakeup_device_prep(acpi_state); | 60 | acpi_enable_wakeup_device_prep(acpi_state); |
46 | #endif | 61 | #endif |
62 | printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n", | ||
63 | acpi_state); | ||
47 | acpi_enter_sleep_state_prep(acpi_state); | 64 | acpi_enter_sleep_state_prep(acpi_state); |
48 | return 0; | 65 | return 0; |
49 | } | 66 | } |
@@ -63,17 +80,25 @@ static u32 acpi_suspend_states[] = { | |||
63 | static int init_8259A_after_S1; | 80 | static int init_8259A_after_S1; |
64 | 81 | ||
65 | /** | 82 | /** |
66 | * acpi_pm_set_target - Set the target system sleep state to the state | 83 | * acpi_pm_begin - Set the target system sleep state to the state |
67 | * associated with given @pm_state, if supported. | 84 | * associated with given @pm_state, if supported. |
68 | */ | 85 | */ |
69 | 86 | ||
70 | static int acpi_pm_set_target(suspend_state_t pm_state) | 87 | static int acpi_pm_begin(suspend_state_t pm_state) |
71 | { | 88 | { |
72 | u32 acpi_state = acpi_suspend_states[pm_state]; | 89 | u32 acpi_state = acpi_suspend_states[pm_state]; |
73 | int error = 0; | 90 | int error = 0; |
74 | 91 | ||
75 | if (sleep_states[acpi_state]) { | 92 | if (sleep_states[acpi_state]) { |
76 | acpi_target_sleep_state = acpi_state; | 93 | acpi_target_sleep_state = acpi_state; |
94 | if (new_pts_ordering) | ||
95 | return 0; | ||
96 | |||
97 | error = acpi_sleep_prepare(acpi_state); | ||
98 | if (error) | ||
99 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
100 | else | ||
101 | acpi_sleep_finish_wake_up = true; | ||
77 | } else { | 102 | } else { |
78 | printk(KERN_ERR "ACPI does not support this state: %d\n", | 103 | printk(KERN_ERR "ACPI does not support this state: %d\n", |
79 | pm_state); | 104 | pm_state); |
@@ -91,12 +116,17 @@ static int acpi_pm_set_target(suspend_state_t pm_state) | |||
91 | 116 | ||
92 | static int acpi_pm_prepare(void) | 117 | static int acpi_pm_prepare(void) |
93 | { | 118 | { |
94 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 119 | if (new_pts_ordering) { |
120 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | ||
95 | 121 | ||
96 | if (error) | 122 | if (error) { |
97 | acpi_target_sleep_state = ACPI_STATE_S0; | 123 | acpi_target_sleep_state = ACPI_STATE_S0; |
124 | return error; | ||
125 | } | ||
126 | acpi_sleep_finish_wake_up = true; | ||
127 | } | ||
98 | 128 | ||
99 | return error; | 129 | return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; |
100 | } | 130 | } |
101 | 131 | ||
102 | /** | 132 | /** |
@@ -120,10 +150,8 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
120 | if (acpi_state == ACPI_STATE_S3) { | 150 | if (acpi_state == ACPI_STATE_S3) { |
121 | int error = acpi_save_state_mem(); | 151 | int error = acpi_save_state_mem(); |
122 | 152 | ||
123 | if (error) { | 153 | if (error) |
124 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
125 | return error; | 154 | return error; |
126 | } | ||
127 | } | 155 | } |
128 | 156 | ||
129 | local_irq_save(flags); | 157 | local_irq_save(flags); |
@@ -139,6 +167,9 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
139 | break; | 167 | break; |
140 | } | 168 | } |
141 | 169 | ||
170 | /* Reprogram control registers and execute _BFS */ | ||
171 | acpi_leave_sleep_state_prep(acpi_state); | ||
172 | |||
142 | /* ACPI 3.0 specs (P62) says that it's the responsabilty | 173 | /* ACPI 3.0 specs (P62) says that it's the responsabilty |
143 | * of the OSPM to clear the status bit [ implying that the | 174 | * of the OSPM to clear the status bit [ implying that the |
144 | * POWER_BUTTON event should not reach userspace ] | 175 | * POWER_BUTTON event should not reach userspace ] |
@@ -146,6 +177,13 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
146 | if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) | 177 | if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) |
147 | acpi_clear_event(ACPI_EVENT_POWER_BUTTON); | 178 | acpi_clear_event(ACPI_EVENT_POWER_BUTTON); |
148 | 179 | ||
180 | /* | ||
181 | * Disable and clear GPE status before interrupt is enabled. Some GPEs | ||
182 | * (like wakeup GPE) haven't handler, this can avoid such GPE misfire. | ||
183 | * acpi_leave_sleep_state will reenable specific GPEs later | ||
184 | */ | ||
185 | acpi_hw_disable_all_gpes(); | ||
186 | |||
149 | local_irq_restore(flags); | 187 | local_irq_restore(flags); |
150 | printk(KERN_DEBUG "Back to C!\n"); | 188 | printk(KERN_DEBUG "Back to C!\n"); |
151 | 189 | ||
@@ -157,7 +195,7 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
157 | } | 195 | } |
158 | 196 | ||
159 | /** | 197 | /** |
160 | * acpi_pm_finish - Finish up suspend sequence. | 198 | * acpi_pm_finish - Instruct the platform to leave a sleep state. |
161 | * | 199 | * |
162 | * This is called after we wake back up (or if entering the sleep state | 200 | * This is called after we wake back up (or if entering the sleep state |
163 | * failed). | 201 | * failed). |
@@ -174,6 +212,7 @@ static void acpi_pm_finish(void) | |||
174 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 212 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
175 | 213 | ||
176 | acpi_target_sleep_state = ACPI_STATE_S0; | 214 | acpi_target_sleep_state = ACPI_STATE_S0; |
215 | acpi_sleep_finish_wake_up = false; | ||
177 | 216 | ||
178 | #ifdef CONFIG_X86 | 217 | #ifdef CONFIG_X86 |
179 | if (init_8259A_after_S1) { | 218 | if (init_8259A_after_S1) { |
@@ -183,6 +222,20 @@ static void acpi_pm_finish(void) | |||
183 | #endif | 222 | #endif |
184 | } | 223 | } |
185 | 224 | ||
225 | /** | ||
226 | * acpi_pm_end - Finish up suspend sequence. | ||
227 | */ | ||
228 | |||
229 | static void acpi_pm_end(void) | ||
230 | { | ||
231 | /* | ||
232 | * This is necessary in case acpi_pm_finish() is not called directly | ||
233 | * during a failing transition to a sleep state. | ||
234 | */ | ||
235 | if (acpi_sleep_finish_wake_up) | ||
236 | acpi_pm_finish(); | ||
237 | } | ||
238 | |||
186 | static int acpi_pm_state_valid(suspend_state_t pm_state) | 239 | static int acpi_pm_state_valid(suspend_state_t pm_state) |
187 | { | 240 | { |
188 | u32 acpi_state; | 241 | u32 acpi_state; |
@@ -201,10 +254,11 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) | |||
201 | 254 | ||
202 | static struct platform_suspend_ops acpi_pm_ops = { | 255 | static struct platform_suspend_ops acpi_pm_ops = { |
203 | .valid = acpi_pm_state_valid, | 256 | .valid = acpi_pm_state_valid, |
204 | .set_target = acpi_pm_set_target, | 257 | .begin = acpi_pm_begin, |
205 | .prepare = acpi_pm_prepare, | 258 | .prepare = acpi_pm_prepare, |
206 | .enter = acpi_pm_enter, | 259 | .enter = acpi_pm_enter, |
207 | .finish = acpi_pm_finish, | 260 | .finish = acpi_pm_finish, |
261 | .end = acpi_pm_end, | ||
208 | }; | 262 | }; |
209 | 263 | ||
210 | /* | 264 | /* |
@@ -229,15 +283,36 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
229 | #endif /* CONFIG_SUSPEND */ | 283 | #endif /* CONFIG_SUSPEND */ |
230 | 284 | ||
231 | #ifdef CONFIG_HIBERNATION | 285 | #ifdef CONFIG_HIBERNATION |
232 | static int acpi_hibernation_start(void) | 286 | static int acpi_hibernation_begin(void) |
233 | { | 287 | { |
288 | int error; | ||
289 | |||
234 | acpi_target_sleep_state = ACPI_STATE_S4; | 290 | acpi_target_sleep_state = ACPI_STATE_S4; |
235 | return 0; | 291 | if (new_pts_ordering) |
292 | return 0; | ||
293 | |||
294 | error = acpi_sleep_prepare(ACPI_STATE_S4); | ||
295 | if (error) | ||
296 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
297 | else | ||
298 | acpi_sleep_finish_wake_up = true; | ||
299 | |||
300 | return error; | ||
236 | } | 301 | } |
237 | 302 | ||
238 | static int acpi_hibernation_prepare(void) | 303 | static int acpi_hibernation_prepare(void) |
239 | { | 304 | { |
240 | return acpi_sleep_prepare(ACPI_STATE_S4); | 305 | if (new_pts_ordering) { |
306 | int error = acpi_sleep_prepare(ACPI_STATE_S4); | ||
307 | |||
308 | if (error) { | ||
309 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
310 | return error; | ||
311 | } | ||
312 | acpi_sleep_finish_wake_up = true; | ||
313 | } | ||
314 | |||
315 | return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; | ||
241 | } | 316 | } |
242 | 317 | ||
243 | static int acpi_hibernation_enter(void) | 318 | static int acpi_hibernation_enter(void) |
@@ -251,6 +326,8 @@ static int acpi_hibernation_enter(void) | |||
251 | acpi_enable_wakeup_device(ACPI_STATE_S4); | 326 | acpi_enable_wakeup_device(ACPI_STATE_S4); |
252 | /* This shouldn't return. If it returns, we have a problem */ | 327 | /* This shouldn't return. If it returns, we have a problem */ |
253 | status = acpi_enter_sleep_state(ACPI_STATE_S4); | 328 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
329 | /* Reprogram control registers and execute _BFS */ | ||
330 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | ||
254 | local_irq_restore(flags); | 331 | local_irq_restore(flags); |
255 | 332 | ||
256 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 333 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
@@ -263,15 +340,12 @@ static void acpi_hibernation_leave(void) | |||
263 | * enable it here. | 340 | * enable it here. |
264 | */ | 341 | */ |
265 | acpi_enable(); | 342 | acpi_enable(); |
343 | /* Reprogram control registers and execute _BFS */ | ||
344 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | ||
266 | } | 345 | } |
267 | 346 | ||
268 | static void acpi_hibernation_finish(void) | 347 | static void acpi_hibernation_finish(void) |
269 | { | 348 | { |
270 | /* | ||
271 | * If ACPI is not enabled by the BIOS and the boot kernel, we need to | ||
272 | * enable it here. | ||
273 | */ | ||
274 | acpi_enable(); | ||
275 | acpi_disable_wakeup_device(ACPI_STATE_S4); | 349 | acpi_disable_wakeup_device(ACPI_STATE_S4); |
276 | acpi_leave_sleep_state(ACPI_STATE_S4); | 350 | acpi_leave_sleep_state(ACPI_STATE_S4); |
277 | 351 | ||
@@ -279,6 +353,17 @@ static void acpi_hibernation_finish(void) | |||
279 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 353 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
280 | 354 | ||
281 | acpi_target_sleep_state = ACPI_STATE_S0; | 355 | acpi_target_sleep_state = ACPI_STATE_S0; |
356 | acpi_sleep_finish_wake_up = false; | ||
357 | } | ||
358 | |||
359 | static void acpi_hibernation_end(void) | ||
360 | { | ||
361 | /* | ||
362 | * This is necessary in case acpi_hibernation_finish() is not called | ||
363 | * directly during a failing transition to the sleep state. | ||
364 | */ | ||
365 | if (acpi_sleep_finish_wake_up) | ||
366 | acpi_hibernation_finish(); | ||
282 | } | 367 | } |
283 | 368 | ||
284 | static int acpi_hibernation_pre_restore(void) | 369 | static int acpi_hibernation_pre_restore(void) |
@@ -296,7 +381,8 @@ static void acpi_hibernation_restore_cleanup(void) | |||
296 | } | 381 | } |
297 | 382 | ||
298 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 383 | static struct platform_hibernation_ops acpi_hibernation_ops = { |
299 | .start = acpi_hibernation_start, | 384 | .begin = acpi_hibernation_begin, |
385 | .end = acpi_hibernation_end, | ||
300 | .pre_snapshot = acpi_hibernation_prepare, | 386 | .pre_snapshot = acpi_hibernation_prepare, |
301 | .finish = acpi_hibernation_finish, | 387 | .finish = acpi_hibernation_finish, |
302 | .prepare = acpi_hibernation_prepare, | 388 | .prepare = acpi_hibernation_prepare, |
@@ -403,6 +489,7 @@ static void acpi_power_off_prepare(void) | |||
403 | { | 489 | { |
404 | /* Prepare to power off the system */ | 490 | /* Prepare to power off the system */ |
405 | acpi_sleep_prepare(ACPI_STATE_S5); | 491 | acpi_sleep_prepare(ACPI_STATE_S5); |
492 | acpi_hw_disable_all_gpes(); | ||
406 | } | 493 | } |
407 | 494 | ||
408 | static void acpi_power_off(void) | 495 | static void acpi_power_off(void) |
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index a2ea125ae2d0..cfaf8f5b0a14 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h | |||
@@ -5,5 +5,3 @@ extern int acpi_suspend (u32 state); | |||
5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); | 5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); |
6 | extern void acpi_enable_wakeup_device(u8 sleep_state); | 6 | extern void acpi_enable_wakeup_device(u8 sleep_state); |
7 | extern void acpi_disable_wakeup_device(u8 sleep_state); | 7 | extern void acpi_disable_wakeup_device(u8 sleep_state); |
8 | |||
9 | extern int acpi_sleep_prepare(u32 acpi_state); | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index de28dfd3b96c..911208b89259 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-$(CONFIG_PM) += sysfs.o | 1 | obj-$(CONFIG_PM) += sysfs.o |
2 | obj-$(CONFIG_PM_SLEEP) += main.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o |
3 | obj-$(CONFIG_PM_TRACE) += trace.o | 3 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o |
4 | 4 | ||
5 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG | 5 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
6 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG | 6 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG |