Skip to content

Commit

Permalink
PM / Sleep: Use wait queue to signal "no wakeup events in progress"
Browse files Browse the repository at this point in the history
The current wakeup source deactivation code doesn't do anything when
the counter of wakeup events in progress goes down to zero, which
requires pm_get_wakeup_count() to poll that counter periodically.
Although this reduces the average time it takes to deactivate a
wakeup source, it also may lead to a substantial amount of unnecessary
polling if there are extended periods of wakeup activity.  Thus it
seems reasonable to use a wait queue for signaling the "no wakeup
events in progress" condition and remove the polling.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: mark gross <markgross@thegnar.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rafael J. Wysocki committed May 1, 2012
1 parent 52d136c commit 60af106
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions drivers/base/power/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

#include "power.h"

#define TIMEOUT 100

/*
* If set, the suspend/hibernate code will abort transitions to a sleep state
* if wakeup events are registered during or immediately before the transition.
Expand Down Expand Up @@ -52,6 +50,8 @@ static void pm_wakeup_timer_fn(unsigned long data);

static LIST_HEAD(wakeup_sources);

static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);

/**
* wakeup_source_prepare - Prepare a new wakeup source for initialization.
* @ws: Wakeup source to prepare.
Expand Down Expand Up @@ -442,6 +442,7 @@ EXPORT_SYMBOL_GPL(pm_stay_awake);
*/
static void wakeup_source_deactivate(struct wakeup_source *ws)
{
unsigned int cnt, inpr;
ktime_t duration;
ktime_t now;

Expand Down Expand Up @@ -476,6 +477,10 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
* couter of wakeup events in progress simultaneously.
*/
atomic_add(MAX_IN_PROGRESS, &combined_event_count);

split_counters(&cnt, &inpr);
if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
wake_up(&wakeup_count_wait_queue);
}

/**
Expand Down Expand Up @@ -667,14 +672,19 @@ bool pm_wakeup_pending(void)
bool pm_get_wakeup_count(unsigned int *count)
{
unsigned int cnt, inpr;
DEFINE_WAIT(wait);

for (;;) {
prepare_to_wait(&wakeup_count_wait_queue, &wait,
TASK_INTERRUPTIBLE);
split_counters(&cnt, &inpr);
if (inpr == 0 || signal_pending(current))
break;
pm_wakeup_update_hit_counts();
schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));

schedule();
}
finish_wait(&wakeup_count_wait_queue, &wait);

split_counters(&cnt, &inpr);
*count = cnt;
Expand Down

0 comments on commit 60af106

Please sign in to comment.