diff options
| author | Takashi Iwai <tiwai@suse.de> | 2012-01-31 15:13:14 +0100 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2012-01-31 15:13:14 +0100 | 
| commit | ea51e5040e24eefe44d70bc654a237ca1f0225b0 (patch) | |
| tree | df2e5922dcdfafae62a10d8cd97f98121064fc23 /kernel/power/hibernate.c | |
| parent | 3422a47041b8cb8f14ac1e3926bcf711121df6dc (diff) | |
| parent | 8dbd52daee38adaae4d5a674bcca837e694a4f4c (diff) | |
Merge branch 'fix/asoc' into for-linus
Diffstat (limited to 'kernel/power/hibernate.c')
| -rw-r--r-- | kernel/power/hibernate.c | 104 | 
1 files changed, 35 insertions, 69 deletions
| diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 196c01268ebd..6d6d28870335 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -43,8 +43,6 @@ int in_suspend __nosavedata;  enum {  	HIBERNATION_INVALID,  	HIBERNATION_PLATFORM, -	HIBERNATION_TEST, -	HIBERNATION_TESTPROC,  	HIBERNATION_SHUTDOWN,  	HIBERNATION_REBOOT,  	/* keep last */ @@ -55,7 +53,7 @@ enum {  static int hibernation_mode = HIBERNATION_SHUTDOWN; -static bool freezer_test_done; +bool freezer_test_done;  static const struct platform_hibernation_ops *hibernation_ops; @@ -71,14 +69,14 @@ void hibernation_set_ops(const struct platform_hibernation_ops *ops)  		WARN_ON(1);  		return;  	} -	mutex_lock(&pm_mutex); +	lock_system_sleep();  	hibernation_ops = ops;  	if (ops)  		hibernation_mode = HIBERNATION_PLATFORM;  	else if (hibernation_mode == HIBERNATION_PLATFORM)  		hibernation_mode = HIBERNATION_SHUTDOWN; -	mutex_unlock(&pm_mutex); +	unlock_system_sleep();  }  static bool entering_platform_hibernation; @@ -96,15 +94,6 @@ static void hibernation_debug_sleep(void)  	mdelay(5000);  } -static int hibernation_testmode(int mode) -{ -	if (hibernation_mode == mode) { -		hibernation_debug_sleep(); -		return 1; -	} -	return 0; -} -  static int hibernation_test(int level)  {  	if (pm_test_level == level) { @@ -114,7 +103,6 @@ static int hibernation_test(int level)  	return 0;  }  #else /* !CONFIG_PM_DEBUG */ -static int hibernation_testmode(int mode) { return 0; }  static int hibernation_test(int level) { return 0; }  #endif /* !CONFIG_PM_DEBUG */ @@ -278,8 +266,7 @@ static int create_image(int platform_mode)  		goto Platform_finish;  	error = disable_nonboot_cpus(); -	if (error || hibernation_test(TEST_CPUS) -	    || hibernation_testmode(HIBERNATION_TEST)) +	if (error || hibernation_test(TEST_CPUS))  		goto Enable_cpus;  	local_irq_disable(); @@ -333,7 +320,7 @@ static int create_image(int platform_mode)   */  int hibernation_snapshot(int platform_mode)  { -	pm_message_t msg = PMSG_RECOVER; +	pm_message_t msg;  	int error;  	error = platform_begin(platform_mode); @@ -347,39 +334,40 @@ int hibernation_snapshot(int platform_mode)  	error = freeze_kernel_threads();  	if (error) -		goto Close; +		goto Cleanup; -	if (hibernation_test(TEST_FREEZER) || -		hibernation_testmode(HIBERNATION_TESTPROC)) { +	if (hibernation_test(TEST_FREEZER)) {  		/*  		 * Indicate to the caller that we are returning due to a  		 * successful freezer test.  		 */  		freezer_test_done = true; -		goto Close; +		goto Cleanup;  	}  	error = dpm_prepare(PMSG_FREEZE); -	if (error) -		goto Complete_devices; +	if (error) { +		dpm_complete(PMSG_RECOVER); +		goto Cleanup; +	}  	suspend_console();  	pm_restrict_gfp_mask(); +  	error = dpm_suspend(PMSG_FREEZE); -	if (error) -		goto Recover_platform; -	if (hibernation_test(TEST_DEVICES)) -		goto Recover_platform; +	if (error || hibernation_test(TEST_DEVICES)) +		platform_recover(platform_mode); +	else +		error = create_image(platform_mode); -	error = create_image(platform_mode);  	/* -	 * Control returns here (1) after the image has been created or the +	 * In the case that we call create_image() above, the control +	 * returns here (1) after the image has been created or the  	 * image creation has failed and (2) after a successful restore.  	 */ - Resume_devices:  	/* We may need to release the preallocated image pages here. */  	if (error || !in_suspend)  		swsusp_free(); @@ -391,17 +379,15 @@ int hibernation_snapshot(int platform_mode)  		pm_restore_gfp_mask();  	resume_console(); - - Complete_devices:  	dpm_complete(msg);   Close:  	platform_end(platform_mode);  	return error; - Recover_platform: -	platform_recover(platform_mode); -	goto Resume_devices; + Cleanup: +	swsusp_free(); +	goto Close;  }  /** @@ -586,9 +572,6 @@ int hibernation_platform_enter(void)  static void power_down(void)  {  	switch (hibernation_mode) { -	case HIBERNATION_TEST: -	case HIBERNATION_TESTPROC: -		break;  	case HIBERNATION_REBOOT:  		kernel_restart(NULL);  		break; @@ -607,17 +590,6 @@ static void power_down(void)  	while(1);  } -static int prepare_processes(void) -{ -	int error = 0; - -	if (freeze_processes()) { -		error = -EBUSY; -		thaw_processes(); -	} -	return error; -} -  /**   * hibernate - Carry out system hibernation, including saving the image.   */ @@ -625,7 +597,7 @@ int hibernate(void)  {  	int error; -	mutex_lock(&pm_mutex); +	lock_system_sleep();  	/* The snapshot device should not be opened while we're running */  	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {  		error = -EBUSY; @@ -650,7 +622,7 @@ int hibernate(void)  	sys_sync();  	printk("done.\n"); -	error = prepare_processes(); +	error = freeze_processes();  	if (error)  		goto Finish; @@ -693,7 +665,7 @@ int hibernate(void)  	pm_restore_console();  	atomic_inc(&snapshot_device_available);   Unlock: -	mutex_unlock(&pm_mutex); +	unlock_system_sleep();  	return error;  } @@ -807,11 +779,13 @@ static int software_resume(void)  		goto close_finish;  	error = create_basic_memory_bitmaps(); -	if (error) +	if (error) { +		usermodehelper_enable();  		goto close_finish; +	}  	pr_debug("PM: Preparing processes for restore.\n"); -	error = prepare_processes(); +	error = freeze_processes();  	if (error) {  		swsusp_close(FMODE_READ);  		goto Done; @@ -851,8 +825,6 @@ static const char * const hibernation_modes[] = {  	[HIBERNATION_PLATFORM]	= "platform",  	[HIBERNATION_SHUTDOWN]	= "shutdown",  	[HIBERNATION_REBOOT]	= "reboot", -	[HIBERNATION_TEST]	= "test", -	[HIBERNATION_TESTPROC]	= "testproc",  };  /* @@ -861,17 +833,15 @@ static const char * const hibernation_modes[] = {   * Hibernation can be handled in several ways.  There are a few different ways   * to put the system into the sleep state: using the platform driver (e.g. ACPI   * or other hibernation_ops), powering it off or rebooting it (for testing - * mostly), or using one of the two available test modes. + * mostly).   *   * The sysfs file /sys/power/disk provides an interface for selecting the   * hibernation mode to use.  Reading from this file causes the available modes - * to be printed.  There are 5 modes that can be supported: + * to be printed.  There are 3 modes that can be supported:   *   *	'platform'   *	'shutdown'   *	'reboot' - *	'test' - *	'testproc'   *   * If a platform hibernation driver is in use, 'platform' will be supported   * and will be used by default.  Otherwise, 'shutdown' will be used by default. @@ -895,8 +865,6 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,  		switch (i) {  		case HIBERNATION_SHUTDOWN:  		case HIBERNATION_REBOOT: -		case HIBERNATION_TEST: -		case HIBERNATION_TESTPROC:  			break;  		case HIBERNATION_PLATFORM:  			if (hibernation_ops) @@ -925,7 +893,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,  	p = memchr(buf, '\n', n);  	len = p ? p - buf : n; -	mutex_lock(&pm_mutex); +	lock_system_sleep();  	for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {  		if (len == strlen(hibernation_modes[i])  		    && !strncmp(buf, hibernation_modes[i], len)) { @@ -937,8 +905,6 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,  		switch (mode) {  		case HIBERNATION_SHUTDOWN:  		case HIBERNATION_REBOOT: -		case HIBERNATION_TEST: -		case HIBERNATION_TESTPROC:  			hibernation_mode = mode;  			break;  		case HIBERNATION_PLATFORM: @@ -953,7 +919,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,  	if (!error)  		pr_debug("PM: Hibernation mode set to '%s'\n",  			 hibernation_modes[mode]); -	mutex_unlock(&pm_mutex); +	unlock_system_sleep();  	return error ? error : n;  } @@ -980,9 +946,9 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,  	if (maj != MAJOR(res) || min != MINOR(res))  		goto out; -	mutex_lock(&pm_mutex); +	lock_system_sleep();  	swsusp_resume_device = res; -	mutex_unlock(&pm_mutex); +	unlock_system_sleep();  	printk(KERN_INFO "PM: Starting manual resume from disk\n");  	noresume = 0;  	software_resume(); | 
