diff options
Diffstat (limited to 'kernel/power/hibernate.c')
| -rw-r--r-- | kernel/power/hibernate.c | 53 | 
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 @@  #include <linux/reboot.h>  #include <linux/string.h>  #include <linux/device.h> +#include <linux/async.h>  #include <linux/kmod.h>  #include <linux/delay.h>  #include <linux/fs.h> @@ -29,12 +30,14 @@  #include "power.h" -static int nocompress = 0; -static int noresume = 0; +static int nocompress; +static int noresume; +static int resume_wait; +static int resume_delay;  static char resume_file[256] = CONFIG_PM_STD_PARTITION;  dev_t swsusp_resume_device;  sector_t swsusp_resume_block; -int in_suspend __nosavedata = 0; +int in_suspend __nosavedata;  enum {  	HIBERNATION_INVALID, @@ -334,13 +337,17 @@ int hibernation_snapshot(int platform_mode)  	if (error)  		goto Close; -	error = dpm_prepare(PMSG_FREEZE); -	if (error) -		goto Complete_devices; -  	/* Preallocate image memory before shutting down devices. */  	error = hibernate_preallocate_memory();  	if (error) +		goto Close; + +	error = freeze_kernel_threads(); +	if (error) +		goto Close; + +	error = dpm_prepare(PMSG_FREEZE); +	if (error)  		goto Complete_devices;  	suspend_console(); @@ -463,7 +470,7 @@ static int resume_target_kernel(bool platform_mode)   * @platform_mode: If set, use platform driver to prepare for the transition.   *   * This routine must be called with pm_mutex held.  If it is successful, control - * reappears in the restored target kernel in hibernation_snaphot(). + * reappears in the restored target kernel in hibernation_snapshot().   */  int hibernation_restore(int platform_mode)  { @@ -650,6 +657,9 @@ int hibernate(void)  			flags |= SF_PLATFORM_MODE;  		if (nocompress)  			flags |= SF_NOCOMPRESS_MODE; +		else +		        flags |= SF_CRC32_MODE; +  		pr_debug("PM: writing image.\n");  		error = swsusp_write(flags);  		swsusp_free(); @@ -724,6 +734,12 @@ static int software_resume(void)  	pr_debug("PM: Checking hibernation image partition %s\n", resume_file); +	if (resume_delay) { +		printk(KERN_INFO "Waiting %dsec before reading resume device...\n", +			resume_delay); +		ssleep(resume_delay); +	} +  	/* Check if the device is there */  	swsusp_resume_device = name_to_dev_t(resume_file);  	if (!swsusp_resume_device) { @@ -732,6 +748,13 @@ static int software_resume(void)  		 * to wait for this to finish.  		 */  		wait_for_device_probe(); + +		if (resume_wait) { +			while ((swsusp_resume_device = name_to_dev_t(resume_file)) == 0) +				msleep(10); +			async_synchronize_full(); +		} +  		/*  		 * We can't depend on SCSI devices being available after loading  		 * one of their modules until scsi_complete_async_scans() is @@ -1060,7 +1083,21 @@ static int __init noresume_setup(char *str)  	return 1;  } +static int __init resumewait_setup(char *str) +{ +	resume_wait = 1; +	return 1; +} + +static int __init resumedelay_setup(char *str) +{ +	resume_delay = simple_strtoul(str, NULL, 0); +	return 1; +} +  __setup("noresume", noresume_setup);  __setup("resume_offset=", resume_offset_setup);  __setup("resume=", resume_setup);  __setup("hibernate=", hibernate_setup); +__setup("resumewait", resumewait_setup); +__setup("resumedelay=", resumedelay_setup);  | 
