It is possible during the processing of suspend_again() that a wake-up request (i.e. pm_stay_awake()) be made by a driver in response to an outside event (i.e. hw interrupt, etc.). Currently, when suspend_again() requests to re-enter suspend, suspend_enter() runs to re-enter suspend. The pm_wakeup_pending() function is called to check for any wake-up requests. However, this function is essentially disabled because the events_check_enabled flag is set to false by the previous run through suspend_enter(). This causes any wake-up request made during the processing of suspend_again() to be delayed until the next time the kernel resumes sometime in the future.
To resolve this issue, if suspend_again() votes to re-enter suspend_enter() the count of wake-up requests is re-evaluated and the events_check_enabled flag set correctly based on the presence of wake-up requests that occurred during suspend_again(). Signed-off-by: Joe Swantek <[email protected]> --- kernel/power/suspend.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 18c6219..f619492 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -188,8 +188,25 @@ static void platform_suspend_recover(suspend_state_t state) static bool platform_suspend_again(suspend_state_t state) { - return state != PM_SUSPEND_FREEZE && suspend_ops->suspend_again ? + int count; + bool suspend = state != PM_SUSPEND_FREEZE && + suspend_ops->suspend_again ? suspend_ops->suspend_again() : false; + + if (suspend) { + /* + * pm_get_wakeup_count() gets an updated count of wakeup events + * that have occured and will return false (i.e. abort suspend) + * if a wakeup event has been started during suspend_again() and + * is still active. pm_save_wakeup_count() stores the count + * and enables pm_wakeup_pending() to properly analyze wakeup + * events before entering suspend in suspend_enter(). + */ + suspend = pm_get_wakeup_count(&count, false) && + pm_save_wakeup_count(count); + } + + return suspend; } static int suspend_test(int level) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

