summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/power/hibernate.c65
-rw-r--r--kernel/power/swap.c6
2 files changed, 50 insertions, 21 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 5f3523e18e46..0ee1df0a0bd6 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -52,6 +52,7 @@ enum {
52#ifdef CONFIG_SUSPEND 52#ifdef CONFIG_SUSPEND
53 HIBERNATION_SUSPEND, 53 HIBERNATION_SUSPEND,
54#endif 54#endif
55 HIBERNATION_TEST_RESUME,
55 /* keep last */ 56 /* keep last */
56 __HIBERNATION_AFTER_LAST 57 __HIBERNATION_AFTER_LAST
57}; 58};
@@ -647,12 +648,39 @@ static void power_down(void)
647 cpu_relax(); 648 cpu_relax();
648} 649}
649 650
651static int load_image_and_restore(void)
652{
653 int error;
654 unsigned int flags;
655
656 pr_debug("PM: Loading hibernation image.\n");
657
658 lock_device_hotplug();
659 error = create_basic_memory_bitmaps();
660 if (error)
661 goto Unlock;
662
663 error = swsusp_read(&flags);
664 swsusp_close(FMODE_READ);
665 if (!error)
666 hibernation_restore(flags & SF_PLATFORM_MODE);
667
668 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
669 swsusp_free();
670 free_basic_memory_bitmaps();
671 Unlock:
672 unlock_device_hotplug();
673
674 return error;
675}
676
650/** 677/**
651 * hibernate - Carry out system hibernation, including saving the image. 678 * hibernate - Carry out system hibernation, including saving the image.
652 */ 679 */
653int hibernate(void) 680int hibernate(void)
654{ 681{
655 int error, nr_calls = 0; 682 int error, nr_calls = 0;
683 bool snapshot_test = false;
656 684
657 if (!hibernation_available()) { 685 if (!hibernation_available()) {
658 pr_debug("PM: Hibernation not available.\n"); 686 pr_debug("PM: Hibernation not available.\n");
@@ -704,8 +732,12 @@ int hibernate(void)
704 pr_debug("PM: writing image.\n"); 732 pr_debug("PM: writing image.\n");
705 error = swsusp_write(flags); 733 error = swsusp_write(flags);
706 swsusp_free(); 734 swsusp_free();
707 if (!error) 735 if (!error) {
708 power_down(); 736 if (hibernation_mode == HIBERNATION_TEST_RESUME)
737 snapshot_test = true;
738 else
739 power_down();
740 }
709 in_suspend = 0; 741 in_suspend = 0;
710 pm_restore_gfp_mask(); 742 pm_restore_gfp_mask();
711 } else { 743 } else {
@@ -716,6 +748,12 @@ int hibernate(void)
716 free_basic_memory_bitmaps(); 748 free_basic_memory_bitmaps();
717 Thaw: 749 Thaw:
718 unlock_device_hotplug(); 750 unlock_device_hotplug();
751 if (snapshot_test) {
752 pr_debug("PM: Checking hibernation image\n");
753 error = swsusp_check();
754 if (!error)
755 error = load_image_and_restore();
756 }
719 thaw_processes(); 757 thaw_processes();
720 758
721 /* Don't bother checking whether freezer_test_done is true */ 759 /* Don't bother checking whether freezer_test_done is true */
@@ -748,7 +786,6 @@ int hibernate(void)
748static int software_resume(void) 786static int software_resume(void)
749{ 787{
750 int error, nr_calls = 0; 788 int error, nr_calls = 0;
751 unsigned int flags;
752 789
753 /* 790 /*
754 * If the user said "noresume".. bail out early. 791 * If the user said "noresume".. bail out early.
@@ -844,24 +881,7 @@ static int software_resume(void)
844 error = freeze_processes(); 881 error = freeze_processes();
845 if (error) 882 if (error)
846 goto Close_Finish; 883 goto Close_Finish;
847 884 error = load_image_and_restore();
848 pr_debug("PM: Loading hibernation image.\n");
849
850 lock_device_hotplug();
851 error = create_basic_memory_bitmaps();
852 if (error)
853 goto Thaw;
854
855 error = swsusp_read(&flags);
856 swsusp_close(FMODE_READ);
857 if (!error)
858 hibernation_restore(flags & SF_PLATFORM_MODE);
859
860 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
861 swsusp_free();
862 free_basic_memory_bitmaps();
863 Thaw:
864 unlock_device_hotplug();
865 thaw_processes(); 885 thaw_processes();
866 Finish: 886 Finish:
867 __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL); 887 __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
@@ -887,6 +907,7 @@ static const char * const hibernation_modes[] = {
887#ifdef CONFIG_SUSPEND 907#ifdef CONFIG_SUSPEND
888 [HIBERNATION_SUSPEND] = "suspend", 908 [HIBERNATION_SUSPEND] = "suspend",
889#endif 909#endif
910 [HIBERNATION_TEST_RESUME] = "test_resume",
890}; 911};
891 912
892/* 913/*
@@ -933,6 +954,7 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
933#ifdef CONFIG_SUSPEND 954#ifdef CONFIG_SUSPEND
934 case HIBERNATION_SUSPEND: 955 case HIBERNATION_SUSPEND:
935#endif 956#endif
957 case HIBERNATION_TEST_RESUME:
936 break; 958 break;
937 case HIBERNATION_PLATFORM: 959 case HIBERNATION_PLATFORM:
938 if (hibernation_ops) 960 if (hibernation_ops)
@@ -979,6 +1001,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
979#ifdef CONFIG_SUSPEND 1001#ifdef CONFIG_SUSPEND
980 case HIBERNATION_SUSPEND: 1002 case HIBERNATION_SUSPEND:
981#endif 1003#endif
1004 case HIBERNATION_TEST_RESUME:
982 hibernation_mode = mode; 1005 hibernation_mode = mode;
983 break; 1006 break;
984 case HIBERNATION_PLATFORM: 1007 case HIBERNATION_PLATFORM:
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 160e1006640d..51cef8432154 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -348,6 +348,12 @@ static int swsusp_swap_check(void)
348 if (res < 0) 348 if (res < 0)
349 blkdev_put(hib_resume_bdev, FMODE_WRITE); 349 blkdev_put(hib_resume_bdev, FMODE_WRITE);
350 350
351 /*
352 * Update the resume device to the one actually used,
353 * so the test_resume mode can use it in case it is
354 * invoked from hibernate() to test the snapshot.
355 */
356 swsusp_resume_device = hib_resume_bdev->bd_dev;
351 return res; 357 return res;
352} 358}
353 359