aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-04-29 16:53:32 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-05-01 15:25:49 -0400
commit55850945e872531644f31fefd217d61dd15dcab8 (patch)
tree412ee1338d0b69e4d6e2a5e518e30e6660704921 /drivers/base
parent7483b4a4d9abf9dcf1ffe6e805ead2847ec3264e (diff)
PM / Sleep: Add "prevent autosleep time" statistics to wakeup sources
Android uses one wakelock statistics that is only necessary for opportunistic sleep. Namely, the prevent_suspend_time field accumulates the total time the given wakelock has been locked while "automatic suspend" was enabled. Add an analogous field, prevent_sleep_time, to wakeup sources and make it behave in a similar way. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/sysfs.c24
-rw-r--r--drivers/base/power/wakeup.c61
2 files changed, 81 insertions, 4 deletions
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 13e40b9021b9..48be2ad4dd2c 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -417,6 +417,27 @@ static ssize_t wakeup_last_time_show(struct device *dev,
417} 417}
418 418
419static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL); 419static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
420
421#ifdef CONFIG_PM_AUTOSLEEP
422static ssize_t wakeup_prevent_sleep_time_show(struct device *dev,
423 struct device_attribute *attr,
424 char *buf)
425{
426 s64 msec = 0;
427 bool enabled = false;
428
429 spin_lock_irq(&dev->power.lock);
430 if (dev->power.wakeup) {
431 msec = ktime_to_ms(dev->power.wakeup->prevent_sleep_time);
432 enabled = true;
433 }
434 spin_unlock_irq(&dev->power.lock);
435 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
436}
437
438static DEVICE_ATTR(wakeup_prevent_sleep_time_ms, 0444,
439 wakeup_prevent_sleep_time_show, NULL);
440#endif /* CONFIG_PM_AUTOSLEEP */
420#endif /* CONFIG_PM_SLEEP */ 441#endif /* CONFIG_PM_SLEEP */
421 442
422#ifdef CONFIG_PM_ADVANCED_DEBUG 443#ifdef CONFIG_PM_ADVANCED_DEBUG
@@ -511,6 +532,9 @@ static struct attribute *wakeup_attrs[] = {
511 &dev_attr_wakeup_total_time_ms.attr, 532 &dev_attr_wakeup_total_time_ms.attr,
512 &dev_attr_wakeup_max_time_ms.attr, 533 &dev_attr_wakeup_max_time_ms.attr,
513 &dev_attr_wakeup_last_time_ms.attr, 534 &dev_attr_wakeup_last_time_ms.attr,
535#ifdef CONFIG_PM_AUTOSLEEP
536 &dev_attr_wakeup_prevent_sleep_time_ms.attr,
537#endif
514#endif 538#endif
515 NULL, 539 NULL,
516}; 540};
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index cf1706df7610..2595b8d8fe1f 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -380,6 +380,8 @@ static void wakeup_source_activate(struct wakeup_source *ws)
380 ws->active = true; 380 ws->active = true;
381 ws->active_count++; 381 ws->active_count++;
382 ws->last_time = ktime_get(); 382 ws->last_time = ktime_get();
383 if (ws->autosleep_enabled)
384 ws->start_prevent_time = ws->last_time;
383 385
384 /* Increment the counter of events in progress. */ 386 /* Increment the counter of events in progress. */
385 cec = atomic_inc_return(&combined_event_count); 387 cec = atomic_inc_return(&combined_event_count);
@@ -449,6 +451,17 @@ void pm_stay_awake(struct device *dev)
449} 451}
450EXPORT_SYMBOL_GPL(pm_stay_awake); 452EXPORT_SYMBOL_GPL(pm_stay_awake);
451 453
454#ifdef CONFIG_PM_AUTOSLEEP
455static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now)
456{
457 ktime_t delta = ktime_sub(now, ws->start_prevent_time);
458 ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta);
459}
460#else
461static inline void update_prevent_sleep_time(struct wakeup_source *ws,
462 ktime_t now) {}
463#endif
464
452/** 465/**
453 * wakup_source_deactivate - Mark given wakeup source as inactive. 466 * wakup_source_deactivate - Mark given wakeup source as inactive.
454 * @ws: Wakeup source to handle. 467 * @ws: Wakeup source to handle.
@@ -490,6 +503,9 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
490 del_timer(&ws->timer); 503 del_timer(&ws->timer);
491 ws->timer_expires = 0; 504 ws->timer_expires = 0;
492 505
506 if (ws->autosleep_enabled)
507 update_prevent_sleep_time(ws, now);
508
493 /* 509 /*
494 * Increment the counter of registered wakeup events and decrement the 510 * Increment the counter of registered wakeup events and decrement the
495 * couter of wakeup events in progress simultaneously. 511 * couter of wakeup events in progress simultaneously.
@@ -718,6 +734,34 @@ bool pm_save_wakeup_count(unsigned int count)
718 return events_check_enabled; 734 return events_check_enabled;
719} 735}
720 736
737#ifdef CONFIG_PM_AUTOSLEEP
738/**
739 * pm_wakep_autosleep_enabled - Modify autosleep_enabled for all wakeup sources.
740 * @enabled: Whether to set or to clear the autosleep_enabled flags.
741 */
742void pm_wakep_autosleep_enabled(bool set)
743{
744 struct wakeup_source *ws;
745 ktime_t now = ktime_get();
746
747 rcu_read_lock();
748 list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
749 spin_lock_irq(&ws->lock);
750 if (ws->autosleep_enabled != set) {
751 ws->autosleep_enabled = set;
752 if (ws->active) {
753 if (set)
754 ws->start_prevent_time = now;
755 else
756 update_prevent_sleep_time(ws, now);
757 }
758 }
759 spin_unlock_irq(&ws->lock);
760 }
761 rcu_read_unlock();
762}
763#endif /* CONFIG_PM_AUTOSLEEP */
764
721static struct dentry *wakeup_sources_stats_dentry; 765static struct dentry *wakeup_sources_stats_dentry;
722 766
723/** 767/**
@@ -733,28 +777,37 @@ static int print_wakeup_source_stats(struct seq_file *m,
733 ktime_t max_time; 777 ktime_t max_time;
734 unsigned long active_count; 778 unsigned long active_count;
735 ktime_t active_time; 779 ktime_t active_time;
780 ktime_t prevent_sleep_time;
736 int ret; 781 int ret;
737 782
738 spin_lock_irqsave(&ws->lock, flags); 783 spin_lock_irqsave(&ws->lock, flags);
739 784
740 total_time = ws->total_time; 785 total_time = ws->total_time;
741 max_time = ws->max_time; 786 max_time = ws->max_time;
787 prevent_sleep_time = ws->prevent_sleep_time;
742 active_count = ws->active_count; 788 active_count = ws->active_count;
743 if (ws->active) { 789 if (ws->active) {
744 active_time = ktime_sub(ktime_get(), ws->last_time); 790 ktime_t now = ktime_get();
791
792 active_time = ktime_sub(now, ws->last_time);
745 total_time = ktime_add(total_time, active_time); 793 total_time = ktime_add(total_time, active_time);
746 if (active_time.tv64 > max_time.tv64) 794 if (active_time.tv64 > max_time.tv64)
747 max_time = active_time; 795 max_time = active_time;
796
797 if (ws->autosleep_enabled)
798 prevent_sleep_time = ktime_add(prevent_sleep_time,
799 ktime_sub(now, ws->start_prevent_time));
748 } else { 800 } else {
749 active_time = ktime_set(0, 0); 801 active_time = ktime_set(0, 0);
750 } 802 }
751 803
752 ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t" 804 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", 805 "%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
754 ws->name, active_count, ws->event_count, 806 ws->name, active_count, ws->event_count,
755 ws->wakeup_count, ws->expire_count, 807 ws->wakeup_count, ws->expire_count,
756 ktime_to_ms(active_time), ktime_to_ms(total_time), 808 ktime_to_ms(active_time), ktime_to_ms(total_time),
757 ktime_to_ms(max_time), ktime_to_ms(ws->last_time)); 809 ktime_to_ms(max_time), ktime_to_ms(ws->last_time),
810 ktime_to_ms(prevent_sleep_time));
758 811
759 spin_unlock_irqrestore(&ws->lock, flags); 812 spin_unlock_irqrestore(&ws->lock, flags);
760 813
@@ -771,7 +824,7 @@ static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
771 824
772 seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t" 825 seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
773 "expire_count\tactive_since\ttotal_time\tmax_time\t" 826 "expire_count\tactive_since\ttotal_time\tmax_time\t"
774 "last_change\n"); 827 "last_change\tprevent_suspend_time\n");
775 828
776 rcu_read_lock(); 829 rcu_read_lock();
777 list_for_each_entry_rcu(ws, &wakeup_sources, entry) 830 list_for_each_entry_rcu(ws, &wakeup_sources, entry)