diff options
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r-- | drivers/acpi/sleep.c | 85 |
1 files changed, 46 insertions, 39 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4ab2275b4461..5b7c52e4a00f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -94,11 +94,13 @@ void __init acpi_old_suspend_ordering(void) | |||
94 | } | 94 | } |
95 | 95 | ||
96 | /** | 96 | /** |
97 | * acpi_pm_disable_gpes - Disable the GPEs. | 97 | * acpi_pm_freeze - Disable the GPEs and suspend EC transactions. |
98 | */ | 98 | */ |
99 | static int acpi_pm_disable_gpes(void) | 99 | static int acpi_pm_freeze(void) |
100 | { | 100 | { |
101 | acpi_disable_all_gpes(); | 101 | acpi_disable_all_gpes(); |
102 | acpi_os_wait_events_complete(NULL); | ||
103 | acpi_ec_block_transactions(); | ||
102 | return 0; | 104 | return 0; |
103 | } | 105 | } |
104 | 106 | ||
@@ -112,6 +114,8 @@ static int __acpi_pm_prepare(void) | |||
112 | { | 114 | { |
113 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 115 | int error = acpi_sleep_prepare(acpi_target_sleep_state); |
114 | 116 | ||
117 | suspend_nvs_save(); | ||
118 | |||
115 | if (error) | 119 | if (error) |
116 | acpi_target_sleep_state = ACPI_STATE_S0; | 120 | acpi_target_sleep_state = ACPI_STATE_S0; |
117 | return error; | 121 | return error; |
@@ -126,7 +130,8 @@ static int acpi_pm_prepare(void) | |||
126 | int error = __acpi_pm_prepare(); | 130 | int error = __acpi_pm_prepare(); |
127 | 131 | ||
128 | if (!error) | 132 | if (!error) |
129 | acpi_disable_all_gpes(); | 133 | acpi_pm_freeze(); |
134 | |||
130 | return error; | 135 | return error; |
131 | } | 136 | } |
132 | 137 | ||
@@ -140,6 +145,9 @@ static void acpi_pm_finish(void) | |||
140 | { | 145 | { |
141 | u32 acpi_state = acpi_target_sleep_state; | 146 | u32 acpi_state = acpi_target_sleep_state; |
142 | 147 | ||
148 | suspend_nvs_free(); | ||
149 | acpi_ec_unblock_transactions(); | ||
150 | |||
143 | if (acpi_state == ACPI_STATE_S0) | 151 | if (acpi_state == ACPI_STATE_S0) |
144 | return; | 152 | return; |
145 | 153 | ||
@@ -189,6 +197,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
189 | u32 acpi_state = acpi_suspend_states[pm_state]; | 197 | u32 acpi_state = acpi_suspend_states[pm_state]; |
190 | int error = 0; | 198 | int error = 0; |
191 | 199 | ||
200 | error = suspend_nvs_alloc(); | ||
201 | |||
202 | if (error) | ||
203 | return error; | ||
204 | |||
192 | if (sleep_states[acpi_state]) { | 205 | if (sleep_states[acpi_state]) { |
193 | acpi_target_sleep_state = acpi_state; | 206 | acpi_target_sleep_state = acpi_state; |
194 | acpi_sleep_tts_switch(acpi_target_sleep_state); | 207 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
@@ -256,6 +269,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
256 | * acpi_leave_sleep_state will reenable specific GPEs later | 269 | * acpi_leave_sleep_state will reenable specific GPEs later |
257 | */ | 270 | */ |
258 | acpi_disable_all_gpes(); | 271 | acpi_disable_all_gpes(); |
272 | /* Allow EC transactions to happen. */ | ||
273 | acpi_ec_unblock_transactions_early(); | ||
259 | 274 | ||
260 | local_irq_restore(flags); | 275 | local_irq_restore(flags); |
261 | printk(KERN_DEBUG "Back to C!\n"); | 276 | printk(KERN_DEBUG "Back to C!\n"); |
@@ -264,9 +279,16 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
264 | if (acpi_state == ACPI_STATE_S3) | 279 | if (acpi_state == ACPI_STATE_S3) |
265 | acpi_restore_state_mem(); | 280 | acpi_restore_state_mem(); |
266 | 281 | ||
282 | suspend_nvs_restore(); | ||
283 | |||
267 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 284 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
268 | } | 285 | } |
269 | 286 | ||
287 | static void acpi_suspend_finish(void) | ||
288 | { | ||
289 | acpi_pm_finish(); | ||
290 | } | ||
291 | |||
270 | static int acpi_suspend_state_valid(suspend_state_t pm_state) | 292 | static int acpi_suspend_state_valid(suspend_state_t pm_state) |
271 | { | 293 | { |
272 | u32 acpi_state; | 294 | u32 acpi_state; |
@@ -288,7 +310,7 @@ static struct platform_suspend_ops acpi_suspend_ops = { | |||
288 | .begin = acpi_suspend_begin, | 310 | .begin = acpi_suspend_begin, |
289 | .prepare_late = acpi_pm_prepare, | 311 | .prepare_late = acpi_pm_prepare, |
290 | .enter = acpi_suspend_enter, | 312 | .enter = acpi_suspend_enter, |
291 | .wake = acpi_pm_finish, | 313 | .wake = acpi_suspend_finish, |
292 | .end = acpi_pm_end, | 314 | .end = acpi_pm_end, |
293 | }; | 315 | }; |
294 | 316 | ||
@@ -314,9 +336,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) | |||
314 | static struct platform_suspend_ops acpi_suspend_ops_old = { | 336 | static struct platform_suspend_ops acpi_suspend_ops_old = { |
315 | .valid = acpi_suspend_state_valid, | 337 | .valid = acpi_suspend_state_valid, |
316 | .begin = acpi_suspend_begin_old, | 338 | .begin = acpi_suspend_begin_old, |
317 | .prepare_late = acpi_pm_disable_gpes, | 339 | .prepare_late = acpi_pm_freeze, |
318 | .enter = acpi_suspend_enter, | 340 | .enter = acpi_suspend_enter, |
319 | .wake = acpi_pm_finish, | 341 | .wake = acpi_suspend_finish, |
320 | .end = acpi_pm_end, | 342 | .end = acpi_pm_end, |
321 | .recover = acpi_pm_finish, | 343 | .recover = acpi_pm_finish, |
322 | }; | 344 | }; |
@@ -393,7 +415,7 @@ static int acpi_hibernation_begin(void) | |||
393 | { | 415 | { |
394 | int error; | 416 | int error; |
395 | 417 | ||
396 | error = s4_no_nvs ? 0 : hibernate_nvs_alloc(); | 418 | error = s4_no_nvs ? 0 : suspend_nvs_alloc(); |
397 | if (!error) { | 419 | if (!error) { |
398 | acpi_target_sleep_state = ACPI_STATE_S4; | 420 | acpi_target_sleep_state = ACPI_STATE_S4; |
399 | acpi_sleep_tts_switch(acpi_target_sleep_state); | 421 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
@@ -407,7 +429,7 @@ static int acpi_hibernation_pre_snapshot(void) | |||
407 | int error = acpi_pm_prepare(); | 429 | int error = acpi_pm_prepare(); |
408 | 430 | ||
409 | if (!error) | 431 | if (!error) |
410 | hibernate_nvs_save(); | 432 | suspend_nvs_save(); |
411 | 433 | ||
412 | return error; | 434 | return error; |
413 | } | 435 | } |
@@ -430,12 +452,6 @@ static int acpi_hibernation_enter(void) | |||
430 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 452 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
431 | } | 453 | } |
432 | 454 | ||
433 | static void acpi_hibernation_finish(void) | ||
434 | { | ||
435 | hibernate_nvs_free(); | ||
436 | acpi_pm_finish(); | ||
437 | } | ||
438 | |||
439 | static void acpi_hibernation_leave(void) | 455 | static void acpi_hibernation_leave(void) |
440 | { | 456 | { |
441 | /* | 457 | /* |
@@ -452,20 +468,14 @@ static void acpi_hibernation_leave(void) | |||
452 | panic("ACPI S4 hardware signature mismatch"); | 468 | panic("ACPI S4 hardware signature mismatch"); |
453 | } | 469 | } |
454 | /* Restore the NVS memory area */ | 470 | /* Restore the NVS memory area */ |
455 | hibernate_nvs_restore(); | 471 | suspend_nvs_restore(); |
472 | /* Allow EC transactions to happen. */ | ||
473 | acpi_ec_unblock_transactions_early(); | ||
456 | } | 474 | } |
457 | 475 | ||
458 | static int acpi_pm_pre_restore(void) | 476 | static void acpi_pm_thaw(void) |
459 | { | 477 | { |
460 | acpi_disable_all_gpes(); | 478 | acpi_ec_unblock_transactions(); |
461 | acpi_os_wait_events_complete(NULL); | ||
462 | acpi_ec_suspend_transactions(); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static void acpi_pm_restore_cleanup(void) | ||
467 | { | ||
468 | acpi_ec_resume_transactions(); | ||
469 | acpi_enable_all_runtime_gpes(); | 479 | acpi_enable_all_runtime_gpes(); |
470 | } | 480 | } |
471 | 481 | ||
@@ -473,12 +483,12 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { | |||
473 | .begin = acpi_hibernation_begin, | 483 | .begin = acpi_hibernation_begin, |
474 | .end = acpi_pm_end, | 484 | .end = acpi_pm_end, |
475 | .pre_snapshot = acpi_hibernation_pre_snapshot, | 485 | .pre_snapshot = acpi_hibernation_pre_snapshot, |
476 | .finish = acpi_hibernation_finish, | 486 | .finish = acpi_pm_finish, |
477 | .prepare = acpi_pm_prepare, | 487 | .prepare = acpi_pm_prepare, |
478 | .enter = acpi_hibernation_enter, | 488 | .enter = acpi_hibernation_enter, |
479 | .leave = acpi_hibernation_leave, | 489 | .leave = acpi_hibernation_leave, |
480 | .pre_restore = acpi_pm_pre_restore, | 490 | .pre_restore = acpi_pm_freeze, |
481 | .restore_cleanup = acpi_pm_restore_cleanup, | 491 | .restore_cleanup = acpi_pm_thaw, |
482 | }; | 492 | }; |
483 | 493 | ||
484 | /** | 494 | /** |
@@ -501,7 +511,7 @@ static int acpi_hibernation_begin_old(void) | |||
501 | 511 | ||
502 | if (!error) { | 512 | if (!error) { |
503 | if (!s4_no_nvs) | 513 | if (!s4_no_nvs) |
504 | error = hibernate_nvs_alloc(); | 514 | error = suspend_nvs_alloc(); |
505 | if (!error) | 515 | if (!error) |
506 | acpi_target_sleep_state = ACPI_STATE_S4; | 516 | acpi_target_sleep_state = ACPI_STATE_S4; |
507 | } | 517 | } |
@@ -510,12 +520,9 @@ static int acpi_hibernation_begin_old(void) | |||
510 | 520 | ||
511 | static int acpi_hibernation_pre_snapshot_old(void) | 521 | static int acpi_hibernation_pre_snapshot_old(void) |
512 | { | 522 | { |
513 | int error = acpi_pm_disable_gpes(); | 523 | acpi_pm_freeze(); |
514 | 524 | suspend_nvs_save(); | |
515 | if (!error) | 525 | return 0; |
516 | hibernate_nvs_save(); | ||
517 | |||
518 | return error; | ||
519 | } | 526 | } |
520 | 527 | ||
521 | /* | 528 | /* |
@@ -526,12 +533,12 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { | |||
526 | .begin = acpi_hibernation_begin_old, | 533 | .begin = acpi_hibernation_begin_old, |
527 | .end = acpi_pm_end, | 534 | .end = acpi_pm_end, |
528 | .pre_snapshot = acpi_hibernation_pre_snapshot_old, | 535 | .pre_snapshot = acpi_hibernation_pre_snapshot_old, |
529 | .finish = acpi_hibernation_finish, | 536 | .prepare = acpi_pm_freeze, |
530 | .prepare = acpi_pm_disable_gpes, | 537 | .finish = acpi_pm_finish, |
531 | .enter = acpi_hibernation_enter, | 538 | .enter = acpi_hibernation_enter, |
532 | .leave = acpi_hibernation_leave, | 539 | .leave = acpi_hibernation_leave, |
533 | .pre_restore = acpi_pm_pre_restore, | 540 | .pre_restore = acpi_pm_freeze, |
534 | .restore_cleanup = acpi_pm_restore_cleanup, | 541 | .restore_cleanup = acpi_pm_thaw, |
535 | .recover = acpi_pm_finish, | 542 | .recover = acpi_pm_finish, |
536 | }; | 543 | }; |
537 | #endif /* CONFIG_HIBERNATION */ | 544 | #endif /* CONFIG_HIBERNATION */ |