PM / Sleep: Use wait queue to signal "no wakeup events in progress"
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>
This commit is contained in:
parent
52d136cc2c
commit
60af106691
1 changed files with 13 additions and 3 deletions
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
#define TIMEOUT 100
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If set, the suspend/hibernate code will abort transitions to a sleep state
|
* If set, the suspend/hibernate code will abort transitions to a sleep state
|
||||||
* if wakeup events are registered during or immediately before the transition.
|
* if wakeup events are registered during or immediately before the transition.
|
||||||
|
@ -52,6 +50,8 @@ static void pm_wakeup_timer_fn(unsigned long data);
|
||||||
|
|
||||||
static LIST_HEAD(wakeup_sources);
|
static LIST_HEAD(wakeup_sources);
|
||||||
|
|
||||||
|
static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wakeup_source_prepare - Prepare a new wakeup source for initialization.
|
* wakeup_source_prepare - Prepare a new wakeup source for initialization.
|
||||||
* @ws: Wakeup source to prepare.
|
* @ws: Wakeup source to prepare.
|
||||||
|
@ -442,6 +442,7 @@ EXPORT_SYMBOL_GPL(pm_stay_awake);
|
||||||
*/
|
*/
|
||||||
static void wakeup_source_deactivate(struct wakeup_source *ws)
|
static void wakeup_source_deactivate(struct wakeup_source *ws)
|
||||||
{
|
{
|
||||||
|
unsigned int cnt, inpr;
|
||||||
ktime_t duration;
|
ktime_t duration;
|
||||||
ktime_t now;
|
ktime_t now;
|
||||||
|
|
||||||
|
@ -476,6 +477,10 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
|
||||||
* couter of wakeup events in progress simultaneously.
|
* couter of wakeup events in progress simultaneously.
|
||||||
*/
|
*/
|
||||||
atomic_add(MAX_IN_PROGRESS, &combined_event_count);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -667,14 +672,19 @@ bool pm_wakeup_pending(void)
|
||||||
bool pm_get_wakeup_count(unsigned int *count)
|
bool pm_get_wakeup_count(unsigned int *count)
|
||||||
{
|
{
|
||||||
unsigned int cnt, inpr;
|
unsigned int cnt, inpr;
|
||||||
|
DEFINE_WAIT(wait);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
prepare_to_wait(&wakeup_count_wait_queue, &wait,
|
||||||
|
TASK_INTERRUPTIBLE);
|
||||||
split_counters(&cnt, &inpr);
|
split_counters(&cnt, &inpr);
|
||||||
if (inpr == 0 || signal_pending(current))
|
if (inpr == 0 || signal_pending(current))
|
||||||
break;
|
break;
|
||||||
pm_wakeup_update_hit_counts();
|
pm_wakeup_update_hit_counts();
|
||||||
schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
|
|
||||||
|
schedule();
|
||||||
}
|
}
|
||||||
|
finish_wait(&wakeup_count_wait_queue, &wait);
|
||||||
|
|
||||||
split_counters(&cnt, &inpr);
|
split_counters(&cnt, &inpr);
|
||||||
*count = cnt;
|
*count = cnt;
|
||||||
|
|
Loading…
Reference in a new issue