diff options
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/suspend.c | 120 | 
1 files changed, 77 insertions, 43 deletions
| diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 83f5b3e70d95..9a071bea80eb 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -36,12 +36,6 @@ const char *pm_states[PM_SUSPEND_MAX];  static const struct platform_suspend_ops *suspend_ops;  static const struct platform_freeze_ops *freeze_ops; - -static bool need_suspend_ops(suspend_state_t state) -{ -	return state > PM_SUSPEND_FREEZE; -} -  static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head);  static bool suspend_freeze_wake; @@ -139,6 +133,65 @@ int suspend_valid_only_mem(suspend_state_t state)  }  EXPORT_SYMBOL_GPL(suspend_valid_only_mem); +static bool sleep_state_supported(suspend_state_t state) +{ +	return state == PM_SUSPEND_FREEZE || (suspend_ops && suspend_ops->enter); +} + +static int platform_suspend_prepare(suspend_state_t state) +{ +	return state != PM_SUSPEND_FREEZE && suspend_ops->prepare ? +		suspend_ops->prepare() : 0; +} + +static int platform_suspend_prepare_late(suspend_state_t state) +{ +	return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ? +		suspend_ops->prepare_late() : 0; +} + +static void platform_suspend_wake(suspend_state_t state) +{ +	if (state != PM_SUSPEND_FREEZE && suspend_ops->wake) +		suspend_ops->wake(); +} + +static void platform_suspend_finish(suspend_state_t state) +{ +	if (state != PM_SUSPEND_FREEZE && suspend_ops->finish) +		suspend_ops->finish(); +} + +static int platform_suspend_begin(suspend_state_t state) +{ +	if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin) +		return freeze_ops->begin(); +	else if (suspend_ops->begin) +		return suspend_ops->begin(state); +	else +		return 0; +} + +static void platform_suspend_end(suspend_state_t state) +{ +	if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end) +		freeze_ops->end(); +	else if (suspend_ops->end) +		suspend_ops->end(); +} + +static void platform_suspend_recover(suspend_state_t state) +{ +	if (state != PM_SUSPEND_FREEZE && suspend_ops->recover) +		suspend_ops->recover(); +} + +static bool platform_suspend_again(suspend_state_t state) +{ +	return state != PM_SUSPEND_FREEZE && suspend_ops->suspend_again ? +		suspend_ops->suspend_again() : false; +} +  static int suspend_test(int level)  {  #ifdef CONFIG_PM_DEBUG @@ -162,7 +215,7 @@ static int suspend_prepare(suspend_state_t state)  {  	int error; -	if (need_suspend_ops(state) && (!suspend_ops || !suspend_ops->enter)) +	if (!sleep_state_supported(state))  		return -EPERM;  	pm_prepare_console(); @@ -208,23 +261,18 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)  {  	int error; -	if (need_suspend_ops(state) && suspend_ops->prepare) { -		error = suspend_ops->prepare(); -		if (error) -			goto Platform_finish; -	} +	error = platform_suspend_prepare(state); +	if (error) +		goto Platform_finish;  	error = dpm_suspend_end(PMSG_SUSPEND);  	if (error) {  		printk(KERN_ERR "PM: Some devices failed to power down\n");  		goto Platform_finish;  	} - -	if (need_suspend_ops(state) && suspend_ops->prepare_late) { -		error = suspend_ops->prepare_late(); -		if (error) -			goto Platform_wake; -	} +	error = platform_suspend_prepare_late(state); +	if (error) +		goto Platform_wake;  	if (suspend_test(TEST_PLATFORM))  		goto Platform_wake; @@ -272,15 +320,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)  	ftrace_start();   Platform_wake: -	if (need_suspend_ops(state) && suspend_ops->wake) -		suspend_ops->wake(); - +	platform_suspend_wake(state);  	dpm_resume_start(PMSG_RESUME);   Platform_finish: -	if (need_suspend_ops(state) && suspend_ops->finish) -		suspend_ops->finish(); - +	platform_suspend_finish(state);  	return error;  } @@ -293,18 +337,13 @@ int suspend_devices_and_enter(suspend_state_t state)  	int error;  	bool wakeup = false; -	if (need_suspend_ops(state) && !suspend_ops) +	if (!sleep_state_supported(state))  		return -ENOSYS; -	if (need_suspend_ops(state) && suspend_ops->begin) { -		error = suspend_ops->begin(state); -		if (error) -			goto Close; -	} else if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin) { -		error = freeze_ops->begin(); -		if (error) -			goto Close; -	} +	error = platform_suspend_begin(state); +	if (error) +		goto Close; +  	suspend_console();  	suspend_test_start();  	error = dpm_suspend_start(PMSG_SUSPEND); @@ -318,25 +357,20 @@ int suspend_devices_and_enter(suspend_state_t state)  	do {  		error = suspend_enter(state, &wakeup); -	} while (!error && !wakeup && need_suspend_ops(state) -		&& suspend_ops->suspend_again && suspend_ops->suspend_again()); +	} while (!error && !wakeup && platform_suspend_again(state));   Resume_devices:  	suspend_test_start();  	dpm_resume_end(PMSG_RESUME);  	suspend_test_finish("resume devices");  	resume_console(); - Close: -	if (need_suspend_ops(state) && suspend_ops->end) -		suspend_ops->end(); -	else if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end) -		freeze_ops->end(); + Close: +	platform_suspend_end(state);  	return error;   Recover_platform: -	if (need_suspend_ops(state) && suspend_ops->recover) -		suspend_ops->recover(); +	platform_suspend_recover(state);  	goto Resume_devices;  } | 
