aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-04-29 16:52:34 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-05-01 15:24:59 -0400
commit60af1066913162c5dd13fad3b872a67b1eb7da0f (patch)
treebd2c66ce4c9f78625c018674feedd482a4da97f4 /drivers/base
parent52d136cc2cf6659ee247dbcc88c9e7bd7428ad06 (diff)
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>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/wakeup.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 2a3e581b8dcd..92f220d89d35 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -17,8 +17,6 @@
17 17
18#include "power.h" 18#include "power.h"
19 19
20#define TIMEOUT 100
21
22/* 20/*
23 * If set, the suspend/hibernate code will abort transitions to a sleep state 21 * If set, the suspend/hibernate code will abort transitions to a sleep state
24 * if wakeup events are registered during or immediately before the transition. 22 * if wakeup events are registered during or immediately before the transition.
@@ -52,6 +50,8 @@ static void pm_wakeup_timer_fn(unsigned long data);
52 50
53static LIST_HEAD(wakeup_sources); 51static LIST_HEAD(wakeup_sources);
54 52
53static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
54
55/** 55/**
56 * wakeup_source_prepare - Prepare a new wakeup source for initialization. 56 * wakeup_source_prepare - Prepare a new wakeup source for initialization.
57 * @ws: Wakeup source to prepare. 57 * @ws: Wakeup source to prepare.
@@ -442,6 +442,7 @@ EXPORT_SYMBOL_GPL(pm_stay_awake);
442 */ 442 */
443static void wakeup_source_deactivate(struct wakeup_source *ws) 443static void wakeup_source_deactivate(struct wakeup_source *ws)
444{ 444{
445 unsigned int cnt, inpr;
445 ktime_t duration; 446 ktime_t duration;
446 ktime_t now; 447 ktime_t now;
447 448
@@ -476,6 +477,10 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
476 * couter of wakeup events in progress simultaneously. 477 * couter of wakeup events in progress simultaneously.
477 */ 478 */
478 atomic_add(MAX_IN_PROGRESS, &combined_event_count); 479 atomic_add(MAX_IN_PROGRESS, &combined_event_count);
480
481 split_counters(&cnt, &inpr);
482 if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
483 wake_up(&wakeup_count_wait_queue);
479} 484}
480 485
481/** 486/**
@@ -667,14 +672,19 @@ bool pm_wakeup_pending(void)
667bool pm_get_wakeup_count(unsigned int *count) 672bool pm_get_wakeup_count(unsigned int *count)
668{ 673{
669 unsigned int cnt, inpr; 674 unsigned int cnt, inpr;
675 DEFINE_WAIT(wait);
670 676
671 for (;;) { 677 for (;;) {
678 prepare_to_wait(&wakeup_count_wait_queue, &wait,
679 TASK_INTERRUPTIBLE);
672 split_counters(&cnt, &inpr); 680 split_counters(&cnt, &inpr);
673 if (inpr == 0 || signal_pending(current)) 681 if (inpr == 0 || signal_pending(current))
674 break; 682 break;
675 pm_wakeup_update_hit_counts(); 683 pm_wakeup_update_hit_counts();
676 schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT)); 684
685 schedule();
677 } 686 }
687 finish_wait(&wakeup_count_wait_queue, &wait);
678 688
679 split_counters(&cnt, &inpr); 689 split_counters(&cnt, &inpr);
680 *count = cnt; 690 *count = cnt;