aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/wakeup.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-04-29 16:52:52 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-05-01 15:25:11 -0400
commit30e3ce6dcbe3fc29c343b17e768b07d4a795de21 (patch)
tree42af32f901aab0c9cbca0dc22f755f9fe3936d67 /drivers/base/power/wakeup.c
parent60af1066913162c5dd13fad3b872a67b1eb7da0f (diff)
PM / Sleep: Change wakeup source statistics to follow Android
Wakeup statistics used by Android are slightly different from what we have in wakeup sources at the moment and there aren't any known users of those statistics other than Android, so modify them to make it easier for Android to switch to wakeup sources. This removes the struct wakeup_source's hit_cout field, which is very rough and therefore not very useful, and adds two new fields, wakeup_count and expire_count. The first one tracks how many times the wakeup source is activated with events_check_enabled set (which roughly corresponds to the situations when a system power transition to a sleep state is in progress and would be aborted by this wakeup source if it were the only active one at that time) and the second one is the number of times the wakeup source has been activated with a timeout that expired. Additionally, the last_time field is now updated when the wakeup source is deactivated too (previously it was only updated during the wakeup source's activation), which seems to be what Android does with the analogous counter for wakelocks. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/power/wakeup.c')
-rw-r--r--drivers/base/power/wakeup.c64
1 files changed, 28 insertions, 36 deletions
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 92f220d89d35..7a6eada4534d 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -21,7 +21,7 @@
21 * 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
22 * if wakeup events are registered during or immediately before the transition. 22 * if wakeup events are registered during or immediately before the transition.
23 */ 23 */
24bool events_check_enabled; 24bool events_check_enabled __read_mostly;
25 25
26/* 26/*
27 * Combined counters of registered wakeup events and wakeup events in progress. 27 * Combined counters of registered wakeup events and wakeup events in progress.
@@ -383,6 +383,21 @@ static void wakeup_source_activate(struct wakeup_source *ws)
383} 383}
384 384
385/** 385/**
386 * wakeup_source_report_event - Report wakeup event using the given source.
387 * @ws: Wakeup source to report the event for.
388 */
389static void wakeup_source_report_event(struct wakeup_source *ws)
390{
391 ws->event_count++;
392 /* This is racy, but the counter is approximate anyway. */
393 if (events_check_enabled)
394 ws->wakeup_count++;
395
396 if (!ws->active)
397 wakeup_source_activate(ws);
398}
399
400/**
386 * __pm_stay_awake - Notify the PM core of a wakeup event. 401 * __pm_stay_awake - Notify the PM core of a wakeup event.
387 * @ws: Wakeup source object associated with the source of the event. 402 * @ws: Wakeup source object associated with the source of the event.
388 * 403 *
@@ -397,10 +412,7 @@ void __pm_stay_awake(struct wakeup_source *ws)
397 412
398 spin_lock_irqsave(&ws->lock, flags); 413 spin_lock_irqsave(&ws->lock, flags);
399 414
400 ws->event_count++; 415 wakeup_source_report_event(ws);
401 if (!ws->active)
402 wakeup_source_activate(ws);
403
404 del_timer(&ws->timer); 416 del_timer(&ws->timer);
405 ws->timer_expires = 0; 417 ws->timer_expires = 0;
406 418
@@ -469,6 +481,7 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
469 if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) 481 if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
470 ws->max_time = duration; 482 ws->max_time = duration;
471 483
484 ws->last_time = now;
472 del_timer(&ws->timer); 485 del_timer(&ws->timer);
473 ws->timer_expires = 0; 486 ws->timer_expires = 0;
474 487
@@ -541,8 +554,10 @@ static void pm_wakeup_timer_fn(unsigned long data)
541 spin_lock_irqsave(&ws->lock, flags); 554 spin_lock_irqsave(&ws->lock, flags);
542 555
543 if (ws->active && ws->timer_expires 556 if (ws->active && ws->timer_expires
544 && time_after_eq(jiffies, ws->timer_expires)) 557 && time_after_eq(jiffies, ws->timer_expires)) {
545 wakeup_source_deactivate(ws); 558 wakeup_source_deactivate(ws);
559 ws->expire_count++;
560 }
546 561
547 spin_unlock_irqrestore(&ws->lock, flags); 562 spin_unlock_irqrestore(&ws->lock, flags);
548} 563}
@@ -569,9 +584,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
569 584
570 spin_lock_irqsave(&ws->lock, flags); 585 spin_lock_irqsave(&ws->lock, flags);
571 586
572 ws->event_count++; 587 wakeup_source_report_event(ws);
573 if (!ws->active)
574 wakeup_source_activate(ws);
575 588
576 if (!msec) { 589 if (!msec) {
577 wakeup_source_deactivate(ws); 590 wakeup_source_deactivate(ws);
@@ -614,24 +627,6 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
614EXPORT_SYMBOL_GPL(pm_wakeup_event); 627EXPORT_SYMBOL_GPL(pm_wakeup_event);
615 628
616/** 629/**
617 * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
618 */
619static void pm_wakeup_update_hit_counts(void)
620{
621 unsigned long flags;
622 struct wakeup_source *ws;
623
624 rcu_read_lock();
625 list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
626 spin_lock_irqsave(&ws->lock, flags);
627 if (ws->active)
628 ws->hit_count++;
629 spin_unlock_irqrestore(&ws->lock, flags);
630 }
631 rcu_read_unlock();
632}
633
634/**
635 * pm_wakeup_pending - Check if power transition in progress should be aborted. 630 * pm_wakeup_pending - Check if power transition in progress should be aborted.
636 * 631 *
637 * Compare the current number of registered wakeup events with its preserved 632 * Compare the current number of registered wakeup events with its preserved
@@ -653,8 +648,6 @@ bool pm_wakeup_pending(void)
653 events_check_enabled = !ret; 648 events_check_enabled = !ret;
654 } 649 }
655 spin_unlock_irqrestore(&events_lock, flags); 650 spin_unlock_irqrestore(&events_lock, flags);
656 if (ret)
657 pm_wakeup_update_hit_counts();
658 return ret; 651 return ret;
659} 652}
660 653
@@ -680,7 +673,6 @@ bool pm_get_wakeup_count(unsigned int *count)
680 split_counters(&cnt, &inpr); 673 split_counters(&cnt, &inpr);
681 if (inpr == 0 || signal_pending(current)) 674 if (inpr == 0 || signal_pending(current))
682 break; 675 break;
683 pm_wakeup_update_hit_counts();
684 676
685 schedule(); 677 schedule();
686 } 678 }
@@ -713,8 +705,6 @@ bool pm_save_wakeup_count(unsigned int count)
713 events_check_enabled = true; 705 events_check_enabled = true;
714 } 706 }
715 spin_unlock_irq(&events_lock); 707 spin_unlock_irq(&events_lock);
716 if (!events_check_enabled)
717 pm_wakeup_update_hit_counts();
718 return events_check_enabled; 708 return events_check_enabled;
719} 709}
720 710
@@ -749,9 +739,10 @@ static int print_wakeup_source_stats(struct seq_file *m,
749 active_time = ktime_set(0, 0); 739 active_time = ktime_set(0, 0);
750 } 740 }
751 741
752 ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t" 742 ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t"
753 "%lld\t\t%lld\t\t%lld\t\t%lld\n", 743 "%lld\t\t%lld\t\t%lld\t\t%lld\n",
754 ws->name, active_count, ws->event_count, ws->hit_count, 744 ws->name, active_count, ws->event_count,
745 ws->wakeup_count, ws->expire_count,
755 ktime_to_ms(active_time), ktime_to_ms(total_time), 746 ktime_to_ms(active_time), ktime_to_ms(total_time),
756 ktime_to_ms(max_time), ktime_to_ms(ws->last_time)); 747 ktime_to_ms(max_time), ktime_to_ms(ws->last_time));
757 748
@@ -768,8 +759,9 @@ static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
768{ 759{
769 struct wakeup_source *ws; 760 struct wakeup_source *ws;
770 761
771 seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t" 762 seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
772 "active_since\ttotal_time\tmax_time\tlast_change\n"); 763 "expire_count\tactive_since\ttotal_time\tmax_time\t"
764 "last_change\n");
773 765
774 rcu_read_lock(); 766 rcu_read_lock();
775 list_for_each_entry_rcu(ws, &wakeup_sources, entry) 767 list_for_each_entry_rcu(ws, &wakeup_sources, entry)