diff options
author | Jiri Kosina <jkosina@suse.cz> | 2010-08-04 09:14:38 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-08-04 09:14:38 -0400 |
commit | d790d4d583aeaed9fc6f8a9f4d9f8ce6b1c15c7f (patch) | |
tree | 854ab394486288d40fa8179cbfaf66e8bdc44b0f /drivers/acpi/sleep.c | |
parent | 73b2c7165b76b20eb1290e7efebc33cfd21db1ca (diff) | |
parent | 3a09b1be53d23df780a0cd0e4087a05e2ca4a00c (diff) |
Merge branch 'master' into for-next
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r-- | drivers/acpi/sleep.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3fb4bdea7e06..2862c781b372 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -82,6 +82,20 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * The ACPI specification wants us to save NVS memory regions during hibernation | ||
86 | * and to restore them during the subsequent resume. Windows does that also for | ||
87 | * suspend to RAM. However, it is known that this mechanism does not work on | ||
88 | * all machines, so we allow the user to disable it with the help of the | ||
89 | * 'acpi_sleep=nonvs' kernel command line option. | ||
90 | */ | ||
91 | static bool nvs_nosave; | ||
92 | |||
93 | void __init acpi_nvs_nosave(void) | ||
94 | { | ||
95 | nvs_nosave = true; | ||
96 | } | ||
97 | |||
98 | /* | ||
85 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 99 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
86 | * user to request that behavior by using the 'acpi_old_suspend_ordering' | 100 | * user to request that behavior by using the 'acpi_old_suspend_ordering' |
87 | * kernel command line option that causes the following variable to be set. | 101 | * kernel command line option that causes the following variable to be set. |
@@ -114,6 +128,8 @@ static int __acpi_pm_prepare(void) | |||
114 | { | 128 | { |
115 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 129 | int error = acpi_sleep_prepare(acpi_target_sleep_state); |
116 | 130 | ||
131 | suspend_nvs_save(); | ||
132 | |||
117 | if (error) | 133 | if (error) |
118 | acpi_target_sleep_state = ACPI_STATE_S0; | 134 | acpi_target_sleep_state = ACPI_STATE_S0; |
119 | return error; | 135 | return error; |
@@ -143,6 +159,9 @@ static void acpi_pm_finish(void) | |||
143 | { | 159 | { |
144 | u32 acpi_state = acpi_target_sleep_state; | 160 | u32 acpi_state = acpi_target_sleep_state; |
145 | 161 | ||
162 | suspend_nvs_free(); | ||
163 | acpi_ec_unblock_transactions(); | ||
164 | |||
146 | if (acpi_state == ACPI_STATE_S0) | 165 | if (acpi_state == ACPI_STATE_S0) |
147 | return; | 166 | return; |
148 | 167 | ||
@@ -192,6 +211,10 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
192 | u32 acpi_state = acpi_suspend_states[pm_state]; | 211 | u32 acpi_state = acpi_suspend_states[pm_state]; |
193 | int error = 0; | 212 | int error = 0; |
194 | 213 | ||
214 | error = nvs_nosave ? 0 : suspend_nvs_alloc(); | ||
215 | if (error) | ||
216 | return error; | ||
217 | |||
195 | if (sleep_states[acpi_state]) { | 218 | if (sleep_states[acpi_state]) { |
196 | acpi_target_sleep_state = acpi_state; | 219 | acpi_target_sleep_state = acpi_state; |
197 | acpi_sleep_tts_switch(acpi_target_sleep_state); | 220 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
@@ -269,12 +292,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
269 | if (acpi_state == ACPI_STATE_S3) | 292 | if (acpi_state == ACPI_STATE_S3) |
270 | acpi_restore_state_mem(); | 293 | acpi_restore_state_mem(); |
271 | 294 | ||
295 | suspend_nvs_restore(); | ||
296 | |||
272 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 297 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
273 | } | 298 | } |
274 | 299 | ||
275 | static void acpi_suspend_finish(void) | 300 | static void acpi_suspend_finish(void) |
276 | { | 301 | { |
277 | acpi_ec_unblock_transactions(); | ||
278 | acpi_pm_finish(); | 302 | acpi_pm_finish(); |
279 | } | 303 | } |
280 | 304 | ||
@@ -377,20 +401,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
377 | #endif /* CONFIG_SUSPEND */ | 401 | #endif /* CONFIG_SUSPEND */ |
378 | 402 | ||
379 | #ifdef CONFIG_HIBERNATION | 403 | #ifdef CONFIG_HIBERNATION |
380 | /* | ||
381 | * The ACPI specification wants us to save NVS memory regions during hibernation | ||
382 | * and to restore them during the subsequent resume. However, it is not certain | ||
383 | * if this mechanism is going to work on all machines, so we allow the user to | ||
384 | * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line | ||
385 | * option. | ||
386 | */ | ||
387 | static bool s4_no_nvs; | ||
388 | |||
389 | void __init acpi_s4_no_nvs(void) | ||
390 | { | ||
391 | s4_no_nvs = true; | ||
392 | } | ||
393 | |||
394 | static unsigned long s4_hardware_signature; | 404 | static unsigned long s4_hardware_signature; |
395 | static struct acpi_table_facs *facs; | 405 | static struct acpi_table_facs *facs; |
396 | static bool nosigcheck; | 406 | static bool nosigcheck; |
@@ -404,7 +414,7 @@ static int acpi_hibernation_begin(void) | |||
404 | { | 414 | { |
405 | int error; | 415 | int error; |
406 | 416 | ||
407 | error = s4_no_nvs ? 0 : hibernate_nvs_alloc(); | 417 | error = nvs_nosave ? 0 : suspend_nvs_alloc(); |
408 | if (!error) { | 418 | if (!error) { |
409 | acpi_target_sleep_state = ACPI_STATE_S4; | 419 | acpi_target_sleep_state = ACPI_STATE_S4; |
410 | acpi_sleep_tts_switch(acpi_target_sleep_state); | 420 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
@@ -418,7 +428,7 @@ static int acpi_hibernation_pre_snapshot(void) | |||
418 | int error = acpi_pm_prepare(); | 428 | int error = acpi_pm_prepare(); |
419 | 429 | ||
420 | if (!error) | 430 | if (!error) |
421 | hibernate_nvs_save(); | 431 | suspend_nvs_save(); |
422 | 432 | ||
423 | return error; | 433 | return error; |
424 | } | 434 | } |
@@ -441,13 +451,6 @@ static int acpi_hibernation_enter(void) | |||
441 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 451 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
442 | } | 452 | } |
443 | 453 | ||
444 | static void acpi_hibernation_finish(void) | ||
445 | { | ||
446 | hibernate_nvs_free(); | ||
447 | acpi_ec_unblock_transactions(); | ||
448 | acpi_pm_finish(); | ||
449 | } | ||
450 | |||
451 | static void acpi_hibernation_leave(void) | 454 | static void acpi_hibernation_leave(void) |
452 | { | 455 | { |
453 | /* | 456 | /* |
@@ -464,7 +467,7 @@ static void acpi_hibernation_leave(void) | |||
464 | panic("ACPI S4 hardware signature mismatch"); | 467 | panic("ACPI S4 hardware signature mismatch"); |
465 | } | 468 | } |
466 | /* Restore the NVS memory area */ | 469 | /* Restore the NVS memory area */ |
467 | hibernate_nvs_restore(); | 470 | suspend_nvs_restore(); |
468 | /* Allow EC transactions to happen. */ | 471 | /* Allow EC transactions to happen. */ |
469 | acpi_ec_unblock_transactions_early(); | 472 | acpi_ec_unblock_transactions_early(); |
470 | } | 473 | } |
@@ -479,7 +482,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { | |||
479 | .begin = acpi_hibernation_begin, | 482 | .begin = acpi_hibernation_begin, |
480 | .end = acpi_pm_end, | 483 | .end = acpi_pm_end, |
481 | .pre_snapshot = acpi_hibernation_pre_snapshot, | 484 | .pre_snapshot = acpi_hibernation_pre_snapshot, |
482 | .finish = acpi_hibernation_finish, | 485 | .finish = acpi_pm_finish, |
483 | .prepare = acpi_pm_prepare, | 486 | .prepare = acpi_pm_prepare, |
484 | .enter = acpi_hibernation_enter, | 487 | .enter = acpi_hibernation_enter, |
485 | .leave = acpi_hibernation_leave, | 488 | .leave = acpi_hibernation_leave, |
@@ -506,8 +509,8 @@ static int acpi_hibernation_begin_old(void) | |||
506 | error = acpi_sleep_prepare(ACPI_STATE_S4); | 509 | error = acpi_sleep_prepare(ACPI_STATE_S4); |
507 | 510 | ||
508 | if (!error) { | 511 | if (!error) { |
509 | if (!s4_no_nvs) | 512 | if (!nvs_nosave) |
510 | error = hibernate_nvs_alloc(); | 513 | error = suspend_nvs_alloc(); |
511 | if (!error) | 514 | if (!error) |
512 | acpi_target_sleep_state = ACPI_STATE_S4; | 515 | acpi_target_sleep_state = ACPI_STATE_S4; |
513 | } | 516 | } |
@@ -517,7 +520,7 @@ static int acpi_hibernation_begin_old(void) | |||
517 | static int acpi_hibernation_pre_snapshot_old(void) | 520 | static int acpi_hibernation_pre_snapshot_old(void) |
518 | { | 521 | { |
519 | acpi_pm_freeze(); | 522 | acpi_pm_freeze(); |
520 | hibernate_nvs_save(); | 523 | suspend_nvs_save(); |
521 | return 0; | 524 | return 0; |
522 | } | 525 | } |
523 | 526 | ||
@@ -529,8 +532,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { | |||
529 | .begin = acpi_hibernation_begin_old, | 532 | .begin = acpi_hibernation_begin_old, |
530 | .end = acpi_pm_end, | 533 | .end = acpi_pm_end, |
531 | .pre_snapshot = acpi_hibernation_pre_snapshot_old, | 534 | .pre_snapshot = acpi_hibernation_pre_snapshot_old, |
532 | .finish = acpi_hibernation_finish, | ||
533 | .prepare = acpi_pm_freeze, | 535 | .prepare = acpi_pm_freeze, |
536 | .finish = acpi_pm_finish, | ||
534 | .enter = acpi_hibernation_enter, | 537 | .enter = acpi_hibernation_enter, |
535 | .leave = acpi_hibernation_leave, | 538 | .leave = acpi_hibernation_leave, |
536 | .pre_restore = acpi_pm_freeze, | 539 | .pre_restore = acpi_pm_freeze, |