aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep/main.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-10-26 15:52:15 -0400
committerLen Brown <len.brown@intel.com>2008-12-19 04:40:34 -0500
commit3f4b0ef7f2899c91b1d6958779f084b44dd59d32 (patch)
treec026201981ecac9c575653c9a46e4c1dea1245a2 /drivers/acpi/sleep/main.c
parent3fe0313e6ec572e6bb3f9d247316a834336db4be (diff)
ACPI hibernate: Add a mechanism to save/restore ACPI NVS memory
According to the ACPI Specification 3.0b, Section 15.3.2, "OSPM will call the _PTS control method some time before entering a sleeping state, to allow the platform's AML code to update this memory image before entering the sleeping state. After the system awakes from an S4 state, OSPM will restore this memory area and call the _WAK control method to enable the BIOS to reclaim its memory image." For this reason, implement a mechanism allowing us to save the NVS memory during hibernation and to restore it during the subsequent resume. Based on a patch by Zhang Rui. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Nigel Cunningham <nigel@tuxonice.net> Cc: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/sleep/main.c')
-rw-r--r--drivers/acpi/sleep/main.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 28a691cc625e..45a8015e4217 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -394,9 +394,25 @@ void __init acpi_no_s4_hw_signature(void)
394 394
395static int acpi_hibernation_begin(void) 395static int acpi_hibernation_begin(void)
396{ 396{
397 acpi_target_sleep_state = ACPI_STATE_S4; 397 int error;
398 acpi_sleep_tts_switch(acpi_target_sleep_state); 398
399 return 0; 399 error = hibernate_nvs_alloc();
400 if (!error) {
401 acpi_target_sleep_state = ACPI_STATE_S4;
402 acpi_sleep_tts_switch(acpi_target_sleep_state);
403 }
404
405 return error;
406}
407
408static int acpi_hibernation_pre_snapshot(void)
409{
410 int error = acpi_pm_prepare();
411
412 if (!error)
413 hibernate_nvs_save();
414
415 return error;
400} 416}
401 417
402static int acpi_hibernation_enter(void) 418static int acpi_hibernation_enter(void)
@@ -417,6 +433,12 @@ static int acpi_hibernation_enter(void)
417 return ACPI_SUCCESS(status) ? 0 : -EFAULT; 433 return ACPI_SUCCESS(status) ? 0 : -EFAULT;
418} 434}
419 435
436static void acpi_hibernation_finish(void)
437{
438 hibernate_nvs_free();
439 acpi_pm_finish();
440}
441
420static void acpi_hibernation_leave(void) 442static void acpi_hibernation_leave(void)
421{ 443{
422 /* 444 /*
@@ -432,6 +454,8 @@ static void acpi_hibernation_leave(void)
432 "cannot resume!\n"); 454 "cannot resume!\n");
433 panic("ACPI S4 hardware signature mismatch"); 455 panic("ACPI S4 hardware signature mismatch");
434 } 456 }
457 /* Restore the NVS memory area */
458 hibernate_nvs_restore();
435} 459}
436 460
437static void acpi_pm_enable_gpes(void) 461static void acpi_pm_enable_gpes(void)
@@ -442,8 +466,8 @@ static void acpi_pm_enable_gpes(void)
442static struct platform_hibernation_ops acpi_hibernation_ops = { 466static struct platform_hibernation_ops acpi_hibernation_ops = {
443 .begin = acpi_hibernation_begin, 467 .begin = acpi_hibernation_begin,
444 .end = acpi_pm_end, 468 .end = acpi_pm_end,
445 .pre_snapshot = acpi_pm_prepare, 469 .pre_snapshot = acpi_hibernation_pre_snapshot,
446 .finish = acpi_pm_finish, 470 .finish = acpi_hibernation_finish,
447 .prepare = acpi_pm_prepare, 471 .prepare = acpi_pm_prepare,
448 .enter = acpi_hibernation_enter, 472 .enter = acpi_hibernation_enter,
449 .leave = acpi_hibernation_leave, 473 .leave = acpi_hibernation_leave,
@@ -469,8 +493,21 @@ static int acpi_hibernation_begin_old(void)
469 493
470 error = acpi_sleep_prepare(ACPI_STATE_S4); 494 error = acpi_sleep_prepare(ACPI_STATE_S4);
471 495
496 if (!error) {
497 error = hibernate_nvs_alloc();
498 if (!error)
499 acpi_target_sleep_state = ACPI_STATE_S4;
500 }
501 return error;
502}
503
504static int acpi_hibernation_pre_snapshot_old(void)
505{
506 int error = acpi_pm_disable_gpes();
507
472 if (!error) 508 if (!error)
473 acpi_target_sleep_state = ACPI_STATE_S4; 509 hibernate_nvs_save();
510
474 return error; 511 return error;
475} 512}
476 513
@@ -481,8 +518,8 @@ static int acpi_hibernation_begin_old(void)
481static struct platform_hibernation_ops acpi_hibernation_ops_old = { 518static struct platform_hibernation_ops acpi_hibernation_ops_old = {
482 .begin = acpi_hibernation_begin_old, 519 .begin = acpi_hibernation_begin_old,
483 .end = acpi_pm_end, 520 .end = acpi_pm_end,
484 .pre_snapshot = acpi_pm_disable_gpes, 521 .pre_snapshot = acpi_hibernation_pre_snapshot_old,
485 .finish = acpi_pm_finish, 522 .finish = acpi_hibernation_finish,
486 .prepare = acpi_pm_disable_gpes, 523 .prepare = acpi_pm_disable_gpes,
487 .enter = acpi_hibernation_enter, 524 .enter = acpi_hibernation_enter,
488 .leave = acpi_hibernation_leave, 525 .leave = acpi_hibernation_leave,