aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/hibernate.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/hibernate.c')
-rw-r--r--kernel/power/hibernate.c59
1 files changed, 24 insertions, 35 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 6d6d28870335..e09dfbfeecee 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -16,7 +16,6 @@
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/async.h> 18#include <linux/async.h>
19#include <linux/kmod.h>
20#include <linux/delay.h> 19#include <linux/delay.h>
21#include <linux/fs.h> 20#include <linux/fs.h>
22#include <linux/mount.h> 21#include <linux/mount.h>
@@ -245,8 +244,8 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
245 * create_image - Create a hibernation image. 244 * create_image - Create a hibernation image.
246 * @platform_mode: Whether or not to use the platform driver. 245 * @platform_mode: Whether or not to use the platform driver.
247 * 246 *
248 * Execute device drivers' .freeze_noirq() callbacks, create a hibernation image 247 * Execute device drivers' "late" and "noirq" freeze callbacks, create a
249 * and execute the drivers' .thaw_noirq() callbacks. 248 * hibernation image and run the drivers' "noirq" and "early" thaw callbacks.
250 * 249 *
251 * Control reappears in this routine after the subsequent restore. 250 * Control reappears in this routine after the subsequent restore.
252 */ 251 */
@@ -254,7 +253,7 @@ static int create_image(int platform_mode)
254{ 253{
255 int error; 254 int error;
256 255
257 error = dpm_suspend_noirq(PMSG_FREEZE); 256 error = dpm_suspend_end(PMSG_FREEZE);
258 if (error) { 257 if (error) {
259 printk(KERN_ERR "PM: Some devices failed to power down, " 258 printk(KERN_ERR "PM: Some devices failed to power down, "
260 "aborting hibernation\n"); 259 "aborting hibernation\n");
@@ -306,7 +305,7 @@ static int create_image(int platform_mode)
306 Platform_finish: 305 Platform_finish:
307 platform_finish(platform_mode); 306 platform_finish(platform_mode);
308 307
309 dpm_resume_noirq(in_suspend ? 308 dpm_resume_start(in_suspend ?
310 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 309 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
311 310
312 return error; 311 return error;
@@ -343,13 +342,13 @@ int hibernation_snapshot(int platform_mode)
343 * successful freezer test. 342 * successful freezer test.
344 */ 343 */
345 freezer_test_done = true; 344 freezer_test_done = true;
346 goto Cleanup; 345 goto Thaw;
347 } 346 }
348 347
349 error = dpm_prepare(PMSG_FREEZE); 348 error = dpm_prepare(PMSG_FREEZE);
350 if (error) { 349 if (error) {
351 dpm_complete(PMSG_RECOVER); 350 dpm_complete(PMSG_RECOVER);
352 goto Cleanup; 351 goto Thaw;
353 } 352 }
354 353
355 suspend_console(); 354 suspend_console();
@@ -385,6 +384,8 @@ int hibernation_snapshot(int platform_mode)
385 platform_end(platform_mode); 384 platform_end(platform_mode);
386 return error; 385 return error;
387 386
387 Thaw:
388 thaw_kernel_threads();
388 Cleanup: 389 Cleanup:
389 swsusp_free(); 390 swsusp_free();
390 goto Close; 391 goto Close;
@@ -394,16 +395,16 @@ int hibernation_snapshot(int platform_mode)
394 * resume_target_kernel - Restore system state from a hibernation image. 395 * resume_target_kernel - Restore system state from a hibernation image.
395 * @platform_mode: Whether or not to use the platform driver. 396 * @platform_mode: Whether or not to use the platform driver.
396 * 397 *
397 * Execute device drivers' .freeze_noirq() callbacks, restore the contents of 398 * 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 399 * 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 400 * the low-level code that will restore the remaining contents of memory and
400 * just restored target kernel. 401 * switch to the just restored target kernel.
401 */ 402 */
402static int resume_target_kernel(bool platform_mode) 403static int resume_target_kernel(bool platform_mode)
403{ 404{
404 int error; 405 int error;
405 406
406 error = dpm_suspend_noirq(PMSG_QUIESCE); 407 error = dpm_suspend_end(PMSG_QUIESCE);
407 if (error) { 408 if (error) {
408 printk(KERN_ERR "PM: Some devices failed to power down, " 409 printk(KERN_ERR "PM: Some devices failed to power down, "
409 "aborting resume\n"); 410 "aborting resume\n");
@@ -460,7 +461,7 @@ static int resume_target_kernel(bool platform_mode)
460 Cleanup: 461 Cleanup:
461 platform_restore_cleanup(platform_mode); 462 platform_restore_cleanup(platform_mode);
462 463
463 dpm_resume_noirq(PMSG_RECOVER); 464 dpm_resume_start(PMSG_RECOVER);
464 465
465 return error; 466 return error;
466} 467}
@@ -518,7 +519,7 @@ int hibernation_platform_enter(void)
518 goto Resume_devices; 519 goto Resume_devices;
519 } 520 }
520 521
521 error = dpm_suspend_noirq(PMSG_HIBERNATE); 522 error = dpm_suspend_end(PMSG_HIBERNATE);
522 if (error) 523 if (error)
523 goto Resume_devices; 524 goto Resume_devices;
524 525
@@ -549,7 +550,7 @@ int hibernation_platform_enter(void)
549 Platform_finish: 550 Platform_finish:
550 hibernation_ops->finish(); 551 hibernation_ops->finish();
551 552
552 dpm_resume_noirq(PMSG_RESTORE); 553 dpm_resume_start(PMSG_RESTORE);
553 554
554 Resume_devices: 555 Resume_devices:
555 entering_platform_hibernation = false; 556 entering_platform_hibernation = false;
@@ -609,10 +610,6 @@ int hibernate(void)
609 if (error) 610 if (error)
610 goto Exit; 611 goto Exit;
611 612
612 error = usermodehelper_disable();
613 if (error)
614 goto Exit;
615
616 /* Allocate memory management structures */ 613 /* Allocate memory management structures */
617 error = create_basic_memory_bitmaps(); 614 error = create_basic_memory_bitmaps();
618 if (error) 615 if (error)
@@ -624,15 +621,11 @@ int hibernate(void)
624 621
625 error = freeze_processes(); 622 error = freeze_processes();
626 if (error) 623 if (error)
627 goto Finish; 624 goto Free_bitmaps;
628 625
629 error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); 626 error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
630 if (error) 627 if (error || freezer_test_done)
631 goto Thaw;
632 if (freezer_test_done) {
633 freezer_test_done = false;
634 goto Thaw; 628 goto Thaw;
635 }
636 629
637 if (in_suspend) { 630 if (in_suspend) {
638 unsigned int flags = 0; 631 unsigned int flags = 0;
@@ -657,9 +650,12 @@ int hibernate(void)
657 650
658 Thaw: 651 Thaw:
659 thaw_processes(); 652 thaw_processes();
660 Finish: 653
654 /* Don't bother checking whether freezer_test_done is true */
655 freezer_test_done = false;
656
657 Free_bitmaps:
661 free_basic_memory_bitmaps(); 658 free_basic_memory_bitmaps();
662 usermodehelper_enable();
663 Exit: 659 Exit:
664 pm_notifier_call_chain(PM_POST_HIBERNATION); 660 pm_notifier_call_chain(PM_POST_HIBERNATION);
665 pm_restore_console(); 661 pm_restore_console();
@@ -774,15 +770,9 @@ static int software_resume(void)
774 if (error) 770 if (error)
775 goto close_finish; 771 goto close_finish;
776 772
777 error = usermodehelper_disable();
778 if (error)
779 goto close_finish;
780
781 error = create_basic_memory_bitmaps(); 773 error = create_basic_memory_bitmaps();
782 if (error) { 774 if (error)
783 usermodehelper_enable();
784 goto close_finish; 775 goto close_finish;
785 }
786 776
787 pr_debug("PM: Preparing processes for restore.\n"); 777 pr_debug("PM: Preparing processes for restore.\n");
788 error = freeze_processes(); 778 error = freeze_processes();
@@ -803,7 +793,6 @@ static int software_resume(void)
803 thaw_processes(); 793 thaw_processes();
804 Done: 794 Done:
805 free_basic_memory_bitmaps(); 795 free_basic_memory_bitmaps();
806 usermodehelper_enable();
807 Finish: 796 Finish:
808 pm_notifier_call_chain(PM_POST_RESTORE); 797 pm_notifier_call_chain(PM_POST_RESTORE);
809 pm_restore_console(); 798 pm_restore_console();