diff options
Diffstat (limited to 'drivers/acpi/acpica/hwsleep.c')
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 401 |
1 files changed, 73 insertions, 328 deletions
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 3c4a922a9fc2..0ed85cac3231 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c | |||
@@ -1,7 +1,7 @@ | |||
1 | |||
2 | /****************************************************************************** | 1 | /****************************************************************************** |
3 | * | 2 | * |
4 | * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface | 3 | * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the |
4 | * original/legacy sleep/PM registers. | ||
5 | * | 5 | * |
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
@@ -43,213 +43,37 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <acpi/acpi.h> | 45 | #include <acpi/acpi.h> |
46 | #include <linux/acpi.h> | ||
46 | #include "accommon.h" | 47 | #include "accommon.h" |
47 | #include "actables.h" | ||
48 | #include <linux/tboot.h> | ||
49 | #include <linux/module.h> | 48 | #include <linux/module.h> |
50 | 49 | ||
51 | #define _COMPONENT ACPI_HARDWARE | 50 | #define _COMPONENT ACPI_HARDWARE |
52 | ACPI_MODULE_NAME("hwsleep") | 51 | ACPI_MODULE_NAME("hwsleep") |
53 | 52 | ||
53 | #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ | ||
54 | /******************************************************************************* | 54 | /******************************************************************************* |
55 | * | 55 | * |
56 | * FUNCTION: acpi_set_firmware_waking_vector | 56 | * FUNCTION: acpi_hw_legacy_sleep |
57 | * | ||
58 | * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode | ||
59 | * entry point. | ||
60 | * | ||
61 | * RETURN: Status | ||
62 | * | ||
63 | * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS | ||
64 | * | ||
65 | ******************************************************************************/ | ||
66 | acpi_status | ||
67 | acpi_set_firmware_waking_vector(u32 physical_address) | ||
68 | { | ||
69 | ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); | ||
70 | |||
71 | |||
72 | /* | ||
73 | * According to the ACPI specification 2.0c and later, the 64-bit | ||
74 | * waking vector should be cleared and the 32-bit waking vector should | ||
75 | * be used, unless we want the wake-up code to be called by the BIOS in | ||
76 | * Protected Mode. Some systems (for example HP dv5-1004nr) are known | ||
77 | * to fail to resume if the 64-bit vector is used. | ||
78 | */ | ||
79 | |||
80 | /* Set the 32-bit vector */ | ||
81 | |||
82 | acpi_gbl_FACS->firmware_waking_vector = physical_address; | ||
83 | |||
84 | /* Clear the 64-bit vector if it exists */ | ||
85 | |||
86 | if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { | ||
87 | acpi_gbl_FACS->xfirmware_waking_vector = 0; | ||
88 | } | ||
89 | |||
90 | return_ACPI_STATUS(AE_OK); | ||
91 | } | ||
92 | |||
93 | ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) | ||
94 | |||
95 | #if ACPI_MACHINE_WIDTH == 64 | ||
96 | /******************************************************************************* | ||
97 | * | ||
98 | * FUNCTION: acpi_set_firmware_waking_vector64 | ||
99 | * | ||
100 | * PARAMETERS: physical_address - 64-bit physical address of ACPI protected | ||
101 | * mode entry point. | ||
102 | * | ||
103 | * RETURN: Status | ||
104 | * | ||
105 | * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if | ||
106 | * it exists in the table. This function is intended for use with | ||
107 | * 64-bit host operating systems. | ||
108 | * | ||
109 | ******************************************************************************/ | ||
110 | acpi_status | ||
111 | acpi_set_firmware_waking_vector64(u64 physical_address) | ||
112 | { | ||
113 | ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); | ||
114 | |||
115 | |||
116 | /* Determine if the 64-bit vector actually exists */ | ||
117 | |||
118 | if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { | ||
119 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
120 | } | ||
121 | |||
122 | /* Clear 32-bit vector, set the 64-bit X_ vector */ | ||
123 | |||
124 | acpi_gbl_FACS->firmware_waking_vector = 0; | ||
125 | acpi_gbl_FACS->xfirmware_waking_vector = physical_address; | ||
126 | |||
127 | return_ACPI_STATUS(AE_OK); | ||
128 | } | ||
129 | |||
130 | ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) | ||
131 | #endif | ||
132 | |||
133 | /******************************************************************************* | ||
134 | * | ||
135 | * FUNCTION: acpi_enter_sleep_state_prep | ||
136 | * | ||
137 | * PARAMETERS: sleep_state - Which sleep state to enter | ||
138 | * | ||
139 | * RETURN: Status | ||
140 | * | ||
141 | * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) | ||
142 | * This function must execute with interrupts enabled. | ||
143 | * We break sleeping into 2 stages so that OSPM can handle | ||
144 | * various OS-specific tasks between the two steps. | ||
145 | * | ||
146 | ******************************************************************************/ | ||
147 | acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | ||
148 | { | ||
149 | acpi_status status; | ||
150 | struct acpi_object_list arg_list; | ||
151 | union acpi_object arg; | ||
152 | |||
153 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); | ||
154 | |||
155 | /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ | ||
156 | |||
157 | status = acpi_get_sleep_type_data(sleep_state, | ||
158 | &acpi_gbl_sleep_type_a, | ||
159 | &acpi_gbl_sleep_type_b); | ||
160 | if (ACPI_FAILURE(status)) { | ||
161 | return_ACPI_STATUS(status); | ||
162 | } | ||
163 | |||
164 | /* Setup parameter object */ | ||
165 | |||
166 | arg_list.count = 1; | ||
167 | arg_list.pointer = &arg; | ||
168 | |||
169 | arg.type = ACPI_TYPE_INTEGER; | ||
170 | arg.integer.value = sleep_state; | ||
171 | |||
172 | /* Run the _PTS method */ | ||
173 | |||
174 | status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); | ||
175 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
176 | return_ACPI_STATUS(status); | ||
177 | } | ||
178 | |||
179 | /* Setup the argument to _SST */ | ||
180 | |||
181 | switch (sleep_state) { | ||
182 | case ACPI_STATE_S0: | ||
183 | arg.integer.value = ACPI_SST_WORKING; | ||
184 | break; | ||
185 | |||
186 | case ACPI_STATE_S1: | ||
187 | case ACPI_STATE_S2: | ||
188 | case ACPI_STATE_S3: | ||
189 | arg.integer.value = ACPI_SST_SLEEPING; | ||
190 | break; | ||
191 | |||
192 | case ACPI_STATE_S4: | ||
193 | arg.integer.value = ACPI_SST_SLEEP_CONTEXT; | ||
194 | break; | ||
195 | |||
196 | default: | ||
197 | arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */ | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Set the system indicators to show the desired sleep state. | ||
203 | * _SST is an optional method (return no error if not found) | ||
204 | */ | ||
205 | status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | ||
206 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
207 | ACPI_EXCEPTION((AE_INFO, status, | ||
208 | "While executing method _SST")); | ||
209 | } | ||
210 | |||
211 | return_ACPI_STATUS(AE_OK); | ||
212 | } | ||
213 | |||
214 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) | ||
215 | |||
216 | static unsigned int gts, bfs; | ||
217 | module_param(gts, uint, 0644); | ||
218 | module_param(bfs, uint, 0644); | ||
219 | MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); | ||
220 | MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); | ||
221 | |||
222 | /******************************************************************************* | ||
223 | * | ||
224 | * FUNCTION: acpi_enter_sleep_state | ||
225 | * | 57 | * |
226 | * PARAMETERS: sleep_state - Which sleep state to enter | 58 | * PARAMETERS: sleep_state - Which sleep state to enter |
59 | * Flags - ACPI_EXECUTE_GTS to run optional method | ||
227 | * | 60 | * |
228 | * RETURN: Status | 61 | * RETURN: Status |
229 | * | 62 | * |
230 | * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) | 63 | * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers |
231 | * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED | 64 | * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED |
232 | * | 65 | * |
233 | ******************************************************************************/ | 66 | ******************************************************************************/ |
234 | acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | 67 | acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) |
235 | { | 68 | { |
236 | u32 pm1a_control; | ||
237 | u32 pm1b_control; | ||
238 | struct acpi_bit_register_info *sleep_type_reg_info; | 69 | struct acpi_bit_register_info *sleep_type_reg_info; |
239 | struct acpi_bit_register_info *sleep_enable_reg_info; | 70 | struct acpi_bit_register_info *sleep_enable_reg_info; |
71 | u32 pm1a_control; | ||
72 | u32 pm1b_control; | ||
240 | u32 in_value; | 73 | u32 in_value; |
241 | struct acpi_object_list arg_list; | ||
242 | union acpi_object arg; | ||
243 | acpi_status status; | 74 | acpi_status status; |
244 | 75 | ||
245 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); | 76 | ACPI_FUNCTION_TRACE(hw_legacy_sleep); |
246 | |||
247 | if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || | ||
248 | (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { | ||
249 | ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", | ||
250 | acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); | ||
251 | return_ACPI_STATUS(AE_AML_OPERAND_VALUE); | ||
252 | } | ||
253 | 77 | ||
254 | sleep_type_reg_info = | 78 | sleep_type_reg_info = |
255 | acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); | 79 | acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); |
@@ -271,6 +95,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
271 | return_ACPI_STATUS(status); | 95 | return_ACPI_STATUS(status); |
272 | } | 96 | } |
273 | 97 | ||
98 | if (sleep_state != ACPI_STATE_S5) { | ||
99 | /* | ||
100 | * Disable BM arbitration. This feature is contained within an | ||
101 | * optional register (PM2 Control), so ignore a BAD_ADDRESS | ||
102 | * exception. | ||
103 | */ | ||
104 | status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); | ||
105 | if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) { | ||
106 | return_ACPI_STATUS(status); | ||
107 | } | ||
108 | } | ||
109 | |||
274 | /* | 110 | /* |
275 | * 1) Disable/Clear all GPEs | 111 | * 1) Disable/Clear all GPEs |
276 | * 2) Enable all wakeup GPEs | 112 | * 2) Enable all wakeup GPEs |
@@ -286,18 +122,10 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
286 | return_ACPI_STATUS(status); | 122 | return_ACPI_STATUS(status); |
287 | } | 123 | } |
288 | 124 | ||
289 | if (gts) { | 125 | /* Optionally execute _GTS (Going To Sleep) */ |
290 | /* Execute the _GTS method */ | ||
291 | |||
292 | arg_list.count = 1; | ||
293 | arg_list.pointer = &arg; | ||
294 | arg.type = ACPI_TYPE_INTEGER; | ||
295 | arg.integer.value = sleep_state; | ||
296 | 126 | ||
297 | status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); | 127 | if (flags & ACPI_EXECUTE_GTS) { |
298 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 128 | acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); |
299 | return_ACPI_STATUS(status); | ||
300 | } | ||
301 | } | 129 | } |
302 | 130 | ||
303 | /* Get current value of PM1A control */ | 131 | /* Get current value of PM1A control */ |
@@ -344,8 +172,12 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
344 | 172 | ||
345 | ACPI_FLUSH_CPU_CACHE(); | 173 | ACPI_FLUSH_CPU_CACHE(); |
346 | 174 | ||
347 | tboot_sleep(sleep_state, pm1a_control, pm1b_control); | 175 | status = acpi_os_prepare_sleep(sleep_state, pm1a_control, |
348 | 176 | pm1b_control); | |
177 | if (ACPI_SKIP(status)) | ||
178 | return_ACPI_STATUS(AE_OK); | ||
179 | if (ACPI_FAILURE(status)) | ||
180 | return_ACPI_STATUS(status); | ||
349 | /* Write #2: Write both SLP_TYP + SLP_EN */ | 181 | /* Write #2: Write both SLP_TYP + SLP_EN */ |
350 | 182 | ||
351 | status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); | 183 | status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); |
@@ -375,114 +207,44 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | |||
375 | } | 207 | } |
376 | } | 208 | } |
377 | 209 | ||
378 | /* Wait until we enter sleep state */ | 210 | /* Wait for transition back to Working State */ |
379 | |||
380 | do { | ||
381 | status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, | ||
382 | &in_value); | ||
383 | if (ACPI_FAILURE(status)) { | ||
384 | return_ACPI_STATUS(status); | ||
385 | } | ||
386 | |||
387 | /* Spin until we wake */ | ||
388 | |||
389 | } while (!in_value); | ||
390 | |||
391 | return_ACPI_STATUS(AE_OK); | ||
392 | } | ||
393 | |||
394 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) | ||
395 | |||
396 | /******************************************************************************* | ||
397 | * | ||
398 | * FUNCTION: acpi_enter_sleep_state_s4bios | ||
399 | * | ||
400 | * PARAMETERS: None | ||
401 | * | ||
402 | * RETURN: Status | ||
403 | * | ||
404 | * DESCRIPTION: Perform a S4 bios request. | ||
405 | * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED | ||
406 | * | ||
407 | ******************************************************************************/ | ||
408 | acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) | ||
409 | { | ||
410 | u32 in_value; | ||
411 | acpi_status status; | ||
412 | |||
413 | ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); | ||
414 | |||
415 | /* Clear the wake status bit (PM1) */ | ||
416 | |||
417 | status = | ||
418 | acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); | ||
419 | if (ACPI_FAILURE(status)) { | ||
420 | return_ACPI_STATUS(status); | ||
421 | } | ||
422 | |||
423 | status = acpi_hw_clear_acpi_status(); | ||
424 | if (ACPI_FAILURE(status)) { | ||
425 | return_ACPI_STATUS(status); | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * 1) Disable/Clear all GPEs | ||
430 | * 2) Enable all wakeup GPEs | ||
431 | */ | ||
432 | status = acpi_hw_disable_all_gpes(); | ||
433 | if (ACPI_FAILURE(status)) { | ||
434 | return_ACPI_STATUS(status); | ||
435 | } | ||
436 | acpi_gbl_system_awake_and_running = FALSE; | ||
437 | |||
438 | status = acpi_hw_enable_all_wakeup_gpes(); | ||
439 | if (ACPI_FAILURE(status)) { | ||
440 | return_ACPI_STATUS(status); | ||
441 | } | ||
442 | |||
443 | ACPI_FLUSH_CPU_CACHE(); | ||
444 | |||
445 | status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, | ||
446 | (u32) acpi_gbl_FADT.S4bios_request, 8); | ||
447 | 211 | ||
448 | do { | 212 | do { |
449 | acpi_os_stall(1000); | ||
450 | status = | 213 | status = |
451 | acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); | 214 | acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); |
452 | if (ACPI_FAILURE(status)) { | 215 | if (ACPI_FAILURE(status)) { |
453 | return_ACPI_STATUS(status); | 216 | return_ACPI_STATUS(status); |
454 | } | 217 | } |
218 | |||
455 | } while (!in_value); | 219 | } while (!in_value); |
456 | 220 | ||
457 | return_ACPI_STATUS(AE_OK); | 221 | return_ACPI_STATUS(AE_OK); |
458 | } | 222 | } |
459 | 223 | ||
460 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) | ||
461 | |||
462 | /******************************************************************************* | 224 | /******************************************************************************* |
463 | * | 225 | * |
464 | * FUNCTION: acpi_leave_sleep_state_prep | 226 | * FUNCTION: acpi_hw_legacy_wake_prep |
465 | * | 227 | * |
466 | * PARAMETERS: sleep_state - Which sleep state we are exiting | 228 | * PARAMETERS: sleep_state - Which sleep state we just exited |
229 | * Flags - ACPI_EXECUTE_BFS to run optional method | ||
467 | * | 230 | * |
468 | * RETURN: Status | 231 | * RETURN: Status |
469 | * | 232 | * |
470 | * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a | 233 | * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a |
471 | * sleep. | 234 | * sleep. |
472 | * Called with interrupts DISABLED. | 235 | * Called with interrupts ENABLED. |
473 | * | 236 | * |
474 | ******************************************************************************/ | 237 | ******************************************************************************/ |
475 | acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) | 238 | |
239 | acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) | ||
476 | { | 240 | { |
477 | struct acpi_object_list arg_list; | ||
478 | union acpi_object arg; | ||
479 | acpi_status status; | 241 | acpi_status status; |
480 | struct acpi_bit_register_info *sleep_type_reg_info; | 242 | struct acpi_bit_register_info *sleep_type_reg_info; |
481 | struct acpi_bit_register_info *sleep_enable_reg_info; | 243 | struct acpi_bit_register_info *sleep_enable_reg_info; |
482 | u32 pm1a_control; | 244 | u32 pm1a_control; |
483 | u32 pm1b_control; | 245 | u32 pm1b_control; |
484 | 246 | ||
485 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); | 247 | ACPI_FUNCTION_TRACE(hw_legacy_wake_prep); |
486 | 248 | ||
487 | /* | 249 | /* |
488 | * Set SLP_TYPE and SLP_EN to state S0. | 250 | * Set SLP_TYPE and SLP_EN to state S0. |
@@ -525,27 +287,20 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) | |||
525 | } | 287 | } |
526 | } | 288 | } |
527 | 289 | ||
528 | if (bfs) { | 290 | /* Optionally execute _BFS (Back From Sleep) */ |
529 | /* Execute the _BFS method */ | ||
530 | 291 | ||
531 | arg_list.count = 1; | 292 | if (flags & ACPI_EXECUTE_BFS) { |
532 | arg_list.pointer = &arg; | 293 | acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); |
533 | arg.type = ACPI_TYPE_INTEGER; | ||
534 | arg.integer.value = sleep_state; | ||
535 | |||
536 | status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); | ||
537 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
538 | ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); | ||
539 | } | ||
540 | } | 294 | } |
541 | return_ACPI_STATUS(status); | 295 | return_ACPI_STATUS(status); |
542 | } | 296 | } |
543 | 297 | ||
544 | /******************************************************************************* | 298 | /******************************************************************************* |
545 | * | 299 | * |
546 | * FUNCTION: acpi_leave_sleep_state | 300 | * FUNCTION: acpi_hw_legacy_wake |
547 | * | 301 | * |
548 | * PARAMETERS: sleep_state - Which sleep state we just exited | 302 | * PARAMETERS: sleep_state - Which sleep state we just exited |
303 | * Flags - Reserved, set to zero | ||
549 | * | 304 | * |
550 | * RETURN: Status | 305 | * RETURN: Status |
551 | * | 306 | * |
@@ -553,31 +308,17 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) | |||
553 | * Called with interrupts ENABLED. | 308 | * Called with interrupts ENABLED. |
554 | * | 309 | * |
555 | ******************************************************************************/ | 310 | ******************************************************************************/ |
556 | acpi_status acpi_leave_sleep_state(u8 sleep_state) | 311 | |
312 | acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags) | ||
557 | { | 313 | { |
558 | struct acpi_object_list arg_list; | ||
559 | union acpi_object arg; | ||
560 | acpi_status status; | 314 | acpi_status status; |
561 | 315 | ||
562 | ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); | 316 | ACPI_FUNCTION_TRACE(hw_legacy_wake); |
563 | 317 | ||
564 | /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ | 318 | /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ |
565 | 319 | ||
566 | acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; | 320 | acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; |
567 | 321 | acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING); | |
568 | /* Setup parameter object */ | ||
569 | |||
570 | arg_list.count = 1; | ||
571 | arg_list.pointer = &arg; | ||
572 | arg.type = ACPI_TYPE_INTEGER; | ||
573 | |||
574 | /* Ignore any errors from these methods */ | ||
575 | |||
576 | arg.integer.value = ACPI_SST_WAKING; | ||
577 | status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | ||
578 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
579 | ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); | ||
580 | } | ||
581 | 322 | ||
582 | /* | 323 | /* |
583 | * GPEs must be enabled before _WAK is called as GPEs | 324 | * GPEs must be enabled before _WAK is called as GPEs |
@@ -591,46 +332,50 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) | |||
591 | if (ACPI_FAILURE(status)) { | 332 | if (ACPI_FAILURE(status)) { |
592 | return_ACPI_STATUS(status); | 333 | return_ACPI_STATUS(status); |
593 | } | 334 | } |
335 | |||
594 | status = acpi_hw_enable_all_runtime_gpes(); | 336 | status = acpi_hw_enable_all_runtime_gpes(); |
595 | if (ACPI_FAILURE(status)) { | 337 | if (ACPI_FAILURE(status)) { |
596 | return_ACPI_STATUS(status); | 338 | return_ACPI_STATUS(status); |
597 | } | 339 | } |
598 | 340 | ||
599 | arg.integer.value = sleep_state; | 341 | /* |
600 | status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); | 342 | * Now we can execute _WAK, etc. Some machines require that the GPEs |
601 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 343 | * are enabled before the wake methods are executed. |
602 | ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); | 344 | */ |
603 | } | 345 | acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state); |
604 | /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ | ||
605 | 346 | ||
606 | /* | 347 | /* |
607 | * Some BIOSes assume that WAK_STS will be cleared on resume and use | 348 | * Some BIOS code assumes that WAK_STS will be cleared on resume |
608 | * it to determine whether the system is rebooting or resuming. Clear | 349 | * and use it to determine whether the system is rebooting or |
609 | * it for compatibility. | 350 | * resuming. Clear WAK_STS for compatibility. |
610 | */ | 351 | */ |
611 | acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); | 352 | acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); |
612 | |||
613 | acpi_gbl_system_awake_and_running = TRUE; | 353 | acpi_gbl_system_awake_and_running = TRUE; |
614 | 354 | ||
615 | /* Enable power button */ | 355 | /* Enable power button */ |
616 | 356 | ||
617 | (void) | 357 | (void) |
618 | acpi_write_bit_register(acpi_gbl_fixed_event_info | 358 | acpi_write_bit_register(acpi_gbl_fixed_event_info |
619 | [ACPI_EVENT_POWER_BUTTON]. | 359 | [ACPI_EVENT_POWER_BUTTON]. |
620 | enable_register_id, ACPI_ENABLE_EVENT); | 360 | enable_register_id, ACPI_ENABLE_EVENT); |
621 | 361 | ||
622 | (void) | 362 | (void) |
623 | acpi_write_bit_register(acpi_gbl_fixed_event_info | 363 | acpi_write_bit_register(acpi_gbl_fixed_event_info |
624 | [ACPI_EVENT_POWER_BUTTON]. | 364 | [ACPI_EVENT_POWER_BUTTON]. |
625 | status_register_id, ACPI_CLEAR_STATUS); | 365 | status_register_id, ACPI_CLEAR_STATUS); |
626 | 366 | ||
627 | arg.integer.value = ACPI_SST_WORKING; | 367 | /* |
628 | status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | 368 | * Enable BM arbitration. This feature is contained within an |
629 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 369 | * optional register (PM2 Control), so ignore a BAD_ADDRESS |
630 | ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); | 370 | * exception. |
371 | */ | ||
372 | status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); | ||
373 | if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) { | ||
374 | return_ACPI_STATUS(status); | ||
631 | } | 375 | } |
632 | 376 | ||
377 | acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); | ||
633 | return_ACPI_STATUS(status); | 378 | return_ACPI_STATUS(status); |
634 | } | 379 | } |
635 | 380 | ||
636 | ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) | 381 | #endif /* !ACPI_REDUCED_HARDWARE */ |