PM / sleep: enable suspend-to-idle even without registered suspend_ops
Suspend-to-idle (aka the "freeze" sleep state) is a system sleep state in which all of the processors enter deepest possible idle state and wait for interrupts right after suspending all the devices. There is no hard requirement for a platform to support and register platform specific suspend_ops to enter suspend-to-idle/freeze state. Only deeper system sleep states like PM_SUSPEND_STANDBY and PM_SUSPEND_MEM rely on such low level support/implementation. suspend-to-idle can be entered as along as all the devices can be suspended. This patch enables the support for suspend-to-idle even on systems that don't have any low level support for deeper system sleep states and/or don't register any platform specific suspend_ops. Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Andy Gross <andy.gross@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Родитель
5b3f249c94
Коммит
fa7fd6fa38
|
@ -245,6 +245,7 @@ static inline bool idle_should_freeze(void)
|
|||
return unlikely(suspend_freeze_state == FREEZE_STATE_ENTER);
|
||||
}
|
||||
|
||||
extern void __init pm_states_init(void);
|
||||
extern void freeze_set_ops(const struct platform_freeze_ops *ops);
|
||||
extern void freeze_wake(void);
|
||||
|
||||
|
@ -279,6 +280,7 @@ static inline bool pm_resume_via_firmware(void) { return false; }
|
|||
static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {}
|
||||
static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
|
||||
static inline bool idle_should_freeze(void) { return false; }
|
||||
static inline void __init pm_states_init(void) {}
|
||||
static inline void freeze_set_ops(const struct platform_freeze_ops *ops) {}
|
||||
static inline void freeze_wake(void) {}
|
||||
#endif /* !CONFIG_SUSPEND */
|
||||
|
|
|
@ -644,6 +644,7 @@ static int __init pm_init(void)
|
|||
return error;
|
||||
hibernate_image_size_init();
|
||||
hibernate_reserved_size_init();
|
||||
pm_states_init();
|
||||
power_kobj = kobject_create_and_add("power", NULL);
|
||||
if (!power_kobj)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -118,10 +118,18 @@ static bool valid_state(suspend_state_t state)
|
|||
*/
|
||||
static bool relative_states;
|
||||
|
||||
void __init pm_states_init(void)
|
||||
{
|
||||
/*
|
||||
* freeze state should be supported even without any suspend_ops,
|
||||
* initialize pm_states accordingly here
|
||||
*/
|
||||
pm_states[PM_SUSPEND_FREEZE] = pm_labels[relative_states ? 0 : 2];
|
||||
}
|
||||
|
||||
static int __init sleep_states_setup(char *str)
|
||||
{
|
||||
relative_states = !strncmp(str, "1", 1);
|
||||
pm_states[PM_SUSPEND_FREEZE] = pm_labels[relative_states ? 0 : 2];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -211,7 +219,7 @@ 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)
|
||||
else if (suspend_ops && suspend_ops->begin)
|
||||
return suspend_ops->begin(state);
|
||||
else
|
||||
return 0;
|
||||
|
@ -221,7 +229,7 @@ static void platform_resume_end(suspend_state_t state)
|
|||
{
|
||||
if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end)
|
||||
freeze_ops->end();
|
||||
else if (suspend_ops->end)
|
||||
else if (suspend_ops && suspend_ops->end)
|
||||
suspend_ops->end();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче