diff options
Diffstat (limited to 'kernel/power/hibernate.c')
-rw-r--r-- | kernel/power/hibernate.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 6d6d28870335..0a186cfde788 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -245,8 +245,8 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop, | |||
245 | * create_image - Create a hibernation image. | 245 | * create_image - Create a hibernation image. |
246 | * @platform_mode: Whether or not to use the platform driver. | 246 | * @platform_mode: Whether or not to use the platform driver. |
247 | * | 247 | * |
248 | * Execute device drivers' .freeze_noirq() callbacks, create a hibernation image | 248 | * Execute device drivers' "late" and "noirq" freeze callbacks, create a |
249 | * and execute the drivers' .thaw_noirq() callbacks. | 249 | * hibernation image and run the drivers' "noirq" and "early" thaw callbacks. |
250 | * | 250 | * |
251 | * Control reappears in this routine after the subsequent restore. | 251 | * Control reappears in this routine after the subsequent restore. |
252 | */ | 252 | */ |
@@ -254,7 +254,7 @@ static int create_image(int platform_mode) | |||
254 | { | 254 | { |
255 | int error; | 255 | int error; |
256 | 256 | ||
257 | error = dpm_suspend_noirq(PMSG_FREEZE); | 257 | error = dpm_suspend_end(PMSG_FREEZE); |
258 | if (error) { | 258 | if (error) { |
259 | printk(KERN_ERR "PM: Some devices failed to power down, " | 259 | printk(KERN_ERR "PM: Some devices failed to power down, " |
260 | "aborting hibernation\n"); | 260 | "aborting hibernation\n"); |
@@ -306,7 +306,7 @@ static int create_image(int platform_mode) | |||
306 | Platform_finish: | 306 | Platform_finish: |
307 | platform_finish(platform_mode); | 307 | platform_finish(platform_mode); |
308 | 308 | ||
309 | dpm_resume_noirq(in_suspend ? | 309 | dpm_resume_start(in_suspend ? |
310 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 310 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
311 | 311 | ||
312 | return error; | 312 | return error; |
@@ -343,13 +343,13 @@ int hibernation_snapshot(int platform_mode) | |||
343 | * successful freezer test. | 343 | * successful freezer test. |
344 | */ | 344 | */ |
345 | freezer_test_done = true; | 345 | freezer_test_done = true; |
346 | goto Cleanup; | 346 | goto Thaw; |
347 | } | 347 | } |
348 | 348 | ||
349 | error = dpm_prepare(PMSG_FREEZE); | 349 | error = dpm_prepare(PMSG_FREEZE); |
350 | if (error) { | 350 | if (error) { |
351 | dpm_complete(PMSG_RECOVER); | 351 | dpm_complete(PMSG_RECOVER); |
352 | goto Cleanup; | 352 | goto Thaw; |
353 | } | 353 | } |
354 | 354 | ||
355 | suspend_console(); | 355 | suspend_console(); |
@@ -385,6 +385,8 @@ int hibernation_snapshot(int platform_mode) | |||
385 | platform_end(platform_mode); | 385 | platform_end(platform_mode); |
386 | return error; | 386 | return error; |
387 | 387 | ||
388 | Thaw: | ||
389 | thaw_kernel_threads(); | ||
388 | Cleanup: | 390 | Cleanup: |
389 | swsusp_free(); | 391 | swsusp_free(); |
390 | goto Close; | 392 | goto Close; |
@@ -394,16 +396,16 @@ int hibernation_snapshot(int platform_mode) | |||
394 | * resume_target_kernel - Restore system state from a hibernation image. | 396 | * resume_target_kernel - Restore system state from a hibernation image. |
395 | * @platform_mode: Whether or not to use the platform driver. | 397 | * @platform_mode: Whether or not to use the platform driver. |
396 | * | 398 | * |
397 | * Execute device drivers' .freeze_noirq() callbacks, restore the contents of | 399 | * Execute device drivers' "noirq" and "late" freeze callbacks, restore the |
398 | * highmem that have not been restored yet from the image and run the low-level | 400 | * contents of highmem that have not been restored yet from the image and run |
399 | * code that will restore the remaining contents of memory and switch to the | 401 | * the low-level code that will restore the remaining contents of memory and |
400 | * just restored target kernel. | 402 | * switch to the just restored target kernel. |
401 | */ | 403 | */ |
402 | static int resume_target_kernel(bool platform_mode) | 404 | static int resume_target_kernel(bool platform_mode) |
403 | { | 405 | { |
404 | int error; | 406 | int error; |
405 | 407 | ||
406 | error = dpm_suspend_noirq(PMSG_QUIESCE); | 408 | error = dpm_suspend_end(PMSG_QUIESCE); |
407 | if (error) { | 409 | if (error) { |
408 | printk(KERN_ERR "PM: Some devices failed to power down, " | 410 | printk(KERN_ERR "PM: Some devices failed to power down, " |
409 | "aborting resume\n"); | 411 | "aborting resume\n"); |
@@ -460,7 +462,7 @@ static int resume_target_kernel(bool platform_mode) | |||
460 | Cleanup: | 462 | Cleanup: |
461 | platform_restore_cleanup(platform_mode); | 463 | platform_restore_cleanup(platform_mode); |
462 | 464 | ||
463 | dpm_resume_noirq(PMSG_RECOVER); | 465 | dpm_resume_start(PMSG_RECOVER); |
464 | 466 | ||
465 | return error; | 467 | return error; |
466 | } | 468 | } |
@@ -518,7 +520,7 @@ int hibernation_platform_enter(void) | |||
518 | goto Resume_devices; | 520 | goto Resume_devices; |
519 | } | 521 | } |
520 | 522 | ||
521 | error = dpm_suspend_noirq(PMSG_HIBERNATE); | 523 | error = dpm_suspend_end(PMSG_HIBERNATE); |
522 | if (error) | 524 | if (error) |
523 | goto Resume_devices; | 525 | goto Resume_devices; |
524 | 526 | ||
@@ -549,7 +551,7 @@ int hibernation_platform_enter(void) | |||
549 | Platform_finish: | 551 | Platform_finish: |
550 | hibernation_ops->finish(); | 552 | hibernation_ops->finish(); |
551 | 553 | ||
552 | dpm_resume_noirq(PMSG_RESTORE); | 554 | dpm_resume_start(PMSG_RESTORE); |
553 | 555 | ||
554 | Resume_devices: | 556 | Resume_devices: |
555 | entering_platform_hibernation = false; | 557 | entering_platform_hibernation = false; |
@@ -616,7 +618,7 @@ int hibernate(void) | |||
616 | /* Allocate memory management structures */ | 618 | /* Allocate memory management structures */ |
617 | error = create_basic_memory_bitmaps(); | 619 | error = create_basic_memory_bitmaps(); |
618 | if (error) | 620 | if (error) |
619 | goto Exit; | 621 | goto Enable_umh; |
620 | 622 | ||
621 | printk(KERN_INFO "PM: Syncing filesystems ... "); | 623 | printk(KERN_INFO "PM: Syncing filesystems ... "); |
622 | sys_sync(); | 624 | sys_sync(); |
@@ -624,15 +626,11 @@ int hibernate(void) | |||
624 | 626 | ||
625 | error = freeze_processes(); | 627 | error = freeze_processes(); |
626 | if (error) | 628 | if (error) |
627 | goto Finish; | 629 | goto Free_bitmaps; |
628 | 630 | ||
629 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); | 631 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); |
630 | if (error) | 632 | if (error || freezer_test_done) |
631 | goto Thaw; | ||
632 | if (freezer_test_done) { | ||
633 | freezer_test_done = false; | ||
634 | goto Thaw; | 633 | goto Thaw; |
635 | } | ||
636 | 634 | ||
637 | if (in_suspend) { | 635 | if (in_suspend) { |
638 | unsigned int flags = 0; | 636 | unsigned int flags = 0; |
@@ -657,8 +655,13 @@ int hibernate(void) | |||
657 | 655 | ||
658 | Thaw: | 656 | Thaw: |
659 | thaw_processes(); | 657 | thaw_processes(); |
660 | Finish: | 658 | |
659 | /* Don't bother checking whether freezer_test_done is true */ | ||
660 | freezer_test_done = false; | ||
661 | |||
662 | Free_bitmaps: | ||
661 | free_basic_memory_bitmaps(); | 663 | free_basic_memory_bitmaps(); |
664 | Enable_umh: | ||
662 | usermodehelper_enable(); | 665 | usermodehelper_enable(); |
663 | Exit: | 666 | Exit: |
664 | pm_notifier_call_chain(PM_POST_HIBERNATION); | 667 | pm_notifier_call_chain(PM_POST_HIBERNATION); |