diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/power/main.c | 99 | ||||
| -rw-r--r-- | kernel/power/power.h | 3 | ||||
| -rw-r--r-- | kernel/power/user.c | 38 | 
3 files changed, 62 insertions, 78 deletions
| diff --git a/kernel/power/main.c b/kernel/power/main.c index 4d26ad394fb3..32147b57c3bf 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -65,14 +65,11 @@ static inline void pm_finish(suspend_state_t state)  /**   *	suspend_prepare - Do prep work before entering low-power state. - *	@state:		State we're entering.   * - *	This is common code that is called for each state that we're  - *	entering. Allocate a console, stop all processes, then make sure - *	the platform can enter the requested state. + *	This is common code that is called for each state that we're entering. + *	Run suspend notifiers, allocate a console and stop all processes.   */ - -static int suspend_prepare(suspend_state_t state) +static int suspend_prepare(void)  {  	int error;  	unsigned int free_pages; @@ -91,43 +88,18 @@ static int suspend_prepare(suspend_state_t state)  		goto Thaw;  	} -	if ((free_pages = global_page_state(NR_FREE_PAGES)) -			< FREE_PAGE_NUMBER) { +	free_pages = global_page_state(NR_FREE_PAGES); +	if (free_pages < FREE_PAGE_NUMBER) {  		pr_debug("PM: free some memory\n");  		shrink_all_memory(FREE_PAGE_NUMBER - free_pages);  		if (nr_free_pages() < FREE_PAGE_NUMBER) {  			error = -ENOMEM;  			printk(KERN_ERR "PM: No enough memory\n"); -			goto Thaw;  		}  	} - -	if (pm_ops->set_target) { -		error = pm_ops->set_target(state); -		if (error) -			goto Thaw; -	} -	suspend_console(); -	error = device_suspend(PMSG_SUSPEND); -	if (error) { -		printk(KERN_ERR "Some devices failed to suspend\n"); -		goto Resume_console; -	} -	if (pm_ops->prepare) { -		if ((error = pm_ops->prepare(state))) -			goto Resume_devices; -	} - -	error = disable_nonboot_cpus();  	if (!error)  		return 0; -	enable_nonboot_cpus(); -	pm_finish(state); - Resume_devices: -	device_resume(); - Resume_console: -	resume_console();   Thaw:  	thaw_processes();  	pm_restore_console(); @@ -148,6 +120,12 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)  	local_irq_enable();  } +/** + *	suspend_enter - enter the desired system sleep state. + *	@state:		state to enter + * + *	This function should be called after devices have been suspended. + */  int suspend_enter(suspend_state_t state)  {  	int error = 0; @@ -167,21 +145,55 @@ int suspend_enter(suspend_state_t state)  	return error;  } +/** + *	suspend_devices_and_enter - suspend devices and enter the desired system sleep + *			  state. + *	@state:		  state to enter + */ +int suspend_devices_and_enter(suspend_state_t state) +{ +	int error; + +	if (!pm_ops) +		return -ENOSYS; + +	if (pm_ops->set_target) { +		error = pm_ops->set_target(state); +		if (error) +			return error; +	} +	suspend_console(); +	error = device_suspend(PMSG_SUSPEND); +	if (error) { +		printk(KERN_ERR "Some devices failed to suspend\n"); +		goto Resume_console; +	} +	if (pm_ops->prepare) { +		error = pm_ops->prepare(state); +		if (error) +			goto Resume_devices; +	} +	error = disable_nonboot_cpus(); +	if (!error) +		suspend_enter(state); + +	enable_nonboot_cpus(); +	pm_finish(state); + Resume_devices: +	device_resume(); + Resume_console: +	resume_console(); +	return error; +}  /**   *	suspend_finish - Do final work before exiting suspend sequence. - *	@state:		State we're coming out of.   *   *	Call platform code to clean up, restart processes, and free the    *	console that we've allocated. This is not called for suspend-to-disk.   */ - -static void suspend_finish(suspend_state_t state) +static void suspend_finish(void)  { -	enable_nonboot_cpus(); -	pm_finish(state); -	device_resume(); -	resume_console();  	thaw_processes();  	pm_restore_console();  	pm_notifier_call_chain(PM_POST_SUSPEND); @@ -216,7 +228,6 @@ static inline int valid_state(suspend_state_t state)   *	Then, do the setup for suspend, enter the state, and cleaup (after   *	we've woken up).   */ -  static int enter_state(suspend_state_t state)  {  	int error; @@ -227,14 +238,14 @@ static int enter_state(suspend_state_t state)  		return -EBUSY;  	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); -	if ((error = suspend_prepare(state))) +	if ((error = suspend_prepare()))  		goto Unlock;  	pr_debug("PM: Entering %s sleep\n", pm_states[state]); -	error = suspend_enter(state); +	error = suspend_devices_and_enter(state);  	pr_debug("PM: Finishing wakeup.\n"); -	suspend_finish(state); +	suspend_finish();   Unlock:  	mutex_unlock(&pm_mutex);  	return error; diff --git a/kernel/power/power.h b/kernel/power/power.h index 01c2275b15b2..5f24c786f8ec 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -170,7 +170,6 @@ extern int swsusp_resume(void);  extern int swsusp_read(unsigned int *flags_p);  extern int swsusp_write(unsigned int flags);  extern void swsusp_close(void); -extern int suspend_enter(suspend_state_t state);  struct timeval;  /* kernel/power/swsusp.c */ @@ -178,6 +177,8 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *,  				unsigned int, char *);  /* kernel/power/main.c */ +extern int suspend_enter(suspend_state_t state); +extern int suspend_devices_and_enter(suspend_state_t state);  extern struct blocking_notifier_head pm_chain_head;  static inline int pm_notifier_call_chain(unsigned long val) diff --git a/kernel/power/user.c b/kernel/power/user.c index 7f19afe01b48..bd0723a7df3f 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -255,47 +255,19 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,  		break;  	case SNAPSHOT_S2RAM: -		if (!pm_ops) { -			error = -ENOSYS; -			break; -		} -  		if (!data->frozen) {  			error = -EPERM;  			break;  		} -  		if (!mutex_trylock(&pm_mutex)) {  			error = -EBUSY;  			break;  		} - -		if (pm_ops->prepare) { -			error = pm_ops->prepare(PM_SUSPEND_MEM); -			if (error) -				goto OutS3; -		} - -		/* Put devices to sleep */ -		suspend_console(); -		error = device_suspend(PMSG_SUSPEND); -		if (error) { -			printk(KERN_ERR "Failed to suspend some devices.\n"); -		} else { -			error = disable_nonboot_cpus(); -			if (!error) { -				/* Enter S3, system is already frozen */ -				suspend_enter(PM_SUSPEND_MEM); -				enable_nonboot_cpus(); -			} -			/* Wake up devices */ -			device_resume(); -		} -		resume_console(); -		if (pm_ops->finish) -			pm_ops->finish(PM_SUSPEND_MEM); - - OutS3: +		/* +		 * Tasks are frozen and the notifiers have been called with +		 * PM_HIBERNATION_PREPARE +		 */ +		error = suspend_devices_and_enter(PM_SUSPEND_MEM);  		mutex_unlock(&pm_mutex);  		break; | 
