Skip to content

Commit

Permalink
power: catch wake-up requests in suspend_again
Browse files Browse the repository at this point in the history
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 <jswantek@motorola.com>
Reviewed-by: Patrick Auchter <auchter@motorola.com>
Reviewed-by: Christopher Fries <cfries@motorola.com>
SLTApproved: Christopher Fries <cfries@motorola.com>
Reviewed-by: Ravi Chebolu <arc095@motorola.com>
Reviewed-by: Fred Fettinger <fettinge@motorola.com>
Reviewed-by: Jeffrey Carlyle <jeff.carlyle@motorola.com>
Reviewed-by: Russell Knize <rknize@motorola.com>
Submit-Approved: Jira Key <jirakey@motorola.com>
  • Loading branch information
Joe Swantek authored and javilonas committed Jun 9, 2015
1 parent 264cebf commit 3713b42
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion kernel/power/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,28 @@ int suspend_valid_only_mem(suspend_state_t state)
}
EXPORT_SYMBOL_GPL(suspend_valid_only_mem);

static bool platform_suspend_again(void)
{
int count;
bool suspend = 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)
{
#ifdef CONFIG_PM_DEBUG
Expand Down Expand Up @@ -300,7 +322,7 @@ 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());
&& platform_suspend_again());

Resume_devices:
suspend_test_start();
Expand Down

0 comments on commit 3713b42

Please sign in to comment.