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.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 8f7b1db1ece1..1c53f7fad5f7 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -14,6 +14,7 @@
14#include <linux/reboot.h> 14#include <linux/reboot.h>
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/async.h>
17#include <linux/kmod.h> 18#include <linux/kmod.h>
18#include <linux/delay.h> 19#include <linux/delay.h>
19#include <linux/fs.h> 20#include <linux/fs.h>
@@ -29,12 +30,14 @@
29#include "power.h" 30#include "power.h"
30 31
31 32
32static int nocompress = 0; 33static int nocompress;
33static int noresume = 0; 34static int noresume;
35static int resume_wait;
36static int resume_delay;
34static char resume_file[256] = CONFIG_PM_STD_PARTITION; 37static char resume_file[256] = CONFIG_PM_STD_PARTITION;
35dev_t swsusp_resume_device; 38dev_t swsusp_resume_device;
36sector_t swsusp_resume_block; 39sector_t swsusp_resume_block;
37int in_suspend __nosavedata = 0; 40int in_suspend __nosavedata;
38 41
39enum { 42enum {
40 HIBERNATION_INVALID, 43 HIBERNATION_INVALID,
@@ -334,13 +337,17 @@ int hibernation_snapshot(int platform_mode)
334 if (error) 337 if (error)
335 goto Close; 338 goto Close;
336 339
337 error = dpm_prepare(PMSG_FREEZE);
338 if (error)
339 goto Complete_devices;
340
341 /* Preallocate image memory before shutting down devices. */ 340 /* Preallocate image memory before shutting down devices. */
342 error = hibernate_preallocate_memory(); 341 error = hibernate_preallocate_memory();
343 if (error) 342 if (error)
343 goto Close;
344
345 error = freeze_kernel_threads();
346 if (error)
347 goto Close;
348
349 error = dpm_prepare(PMSG_FREEZE);
350 if (error)
344 goto Complete_devices; 351 goto Complete_devices;
345 352
346 suspend_console(); 353 suspend_console();
@@ -463,7 +470,7 @@ static int resume_target_kernel(bool platform_mode)
463 * @platform_mode: If set, use platform driver to prepare for the transition. 470 * @platform_mode: If set, use platform driver to prepare for the transition.
464 * 471 *
465 * This routine must be called with pm_mutex held. If it is successful, control 472 * This routine must be called with pm_mutex held. If it is successful, control
466 * reappears in the restored target kernel in hibernation_snaphot(). 473 * reappears in the restored target kernel in hibernation_snapshot().
467 */ 474 */
468int hibernation_restore(int platform_mode) 475int hibernation_restore(int platform_mode)
469{ 476{
@@ -650,6 +657,9 @@ int hibernate(void)
650 flags |= SF_PLATFORM_MODE; 657 flags |= SF_PLATFORM_MODE;
651 if (nocompress) 658 if (nocompress)
652 flags |= SF_NOCOMPRESS_MODE; 659 flags |= SF_NOCOMPRESS_MODE;
660 else
661 flags |= SF_CRC32_MODE;
662
653 pr_debug("PM: writing image.\n"); 663 pr_debug("PM: writing image.\n");
654 error = swsusp_write(flags); 664 error = swsusp_write(flags);
655 swsusp_free(); 665 swsusp_free();
@@ -724,6 +734,12 @@ static int software_resume(void)
724 734
725 pr_debug("PM: Checking hibernation image partition %s\n", resume_file); 735 pr_debug("PM: Checking hibernation image partition %s\n", resume_file);
726 736
737 if (resume_delay) {
738 printk(KERN_INFO "Waiting %dsec before reading resume device...\n",
739 resume_delay);
740 ssleep(resume_delay);
741 }
742
727 /* Check if the device is there */ 743 /* Check if the device is there */
728 swsusp_resume_device = name_to_dev_t(resume_file); 744 swsusp_resume_device = name_to_dev_t(resume_file);
729 if (!swsusp_resume_device) { 745 if (!swsusp_resume_device) {
@@ -732,6 +748,13 @@ static int software_resume(void)
732 * to wait for this to finish. 748 * to wait for this to finish.
733 */ 749 */
734 wait_for_device_probe(); 750 wait_for_device_probe();
751
752 if (resume_wait) {
753 while ((swsusp_resume_device = name_to_dev_t(resume_file)) == 0)
754 msleep(10);
755 async_synchronize_full();
756 }
757
735 /* 758 /*
736 * We can't depend on SCSI devices being available after loading 759 * We can't depend on SCSI devices being available after loading
737 * one of their modules until scsi_complete_async_scans() is 760 * one of their modules until scsi_complete_async_scans() is
@@ -1060,7 +1083,21 @@ static int __init noresume_setup(char *str)
1060 return 1; 1083 return 1;
1061} 1084}
1062 1085
1086static int __init resumewait_setup(char *str)
1087{
1088 resume_wait = 1;
1089 return 1;
1090}
1091
1092static int __init resumedelay_setup(char *str)
1093{
1094 resume_delay = simple_strtoul(str, NULL, 0);
1095 return 1;
1096}
1097
1063__setup("noresume", noresume_setup); 1098__setup("noresume", noresume_setup);
1064__setup("resume_offset=", resume_offset_setup); 1099__setup("resume_offset=", resume_offset_setup);
1065__setup("resume=", resume_setup); 1100__setup("resume=", resume_setup);
1066__setup("hibernate=", hibernate_setup); 1101__setup("hibernate=", hibernate_setup);
1102__setup("resumewait", resumewait_setup);
1103__setup("resumedelay=", resumedelay_setup);