Commit a938da0682c2487f6aafc9a7c3caa8d675acdb38

Authored by Todd Poynor
Committed by Rafael J. Wysocki
1 parent d9875690d9

PM / Sleep: Print name of wakeup source that aborts suspend

A driver or app may repeatedly request a wakeup source while the system
is attempting to enter suspend, which may indicate a bug or at least
point out a highly active system component that is responsible for
decreased battery life on a mobile device.  Even when the incidence
of suspend abort is not severe, identifying wakeup sources that
frequently abort suspend can be a useful clue for power management
analysis.

In some cases the existing stats can point out the offender where there is
an unexpectedly high activation count that stands out from the others, but
in other cases the wakeup source frequently taken just after the rest of
the system thinks its time to suspend might not stand out in the overall
stats.

It is also often useful to have information about what's been happening
recently, rather than totals of all activity for the system boot.

It's suggested to dump a line about which wakeup source
aborted suspend to aid analysis of these situations.

Signed-off-by: Todd Poynor <toddpoynor@google.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

Showing 1 changed file with 29 additions and 0 deletions Side-by-side Diff

drivers/base/power/wakeup.c
... ... @@ -649,6 +649,31 @@
649 649 }
650 650 EXPORT_SYMBOL_GPL(pm_wakeup_event);
651 651  
  652 +static void print_active_wakeup_sources(void)
  653 +{
  654 + struct wakeup_source *ws;
  655 + int active = 0;
  656 + struct wakeup_source *last_activity_ws = NULL;
  657 +
  658 + rcu_read_lock();
  659 + list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
  660 + if (ws->active) {
  661 + pr_info("active wakeup source: %s\n", ws->name);
  662 + active = 1;
  663 + } else if (!active &&
  664 + (!last_activity_ws ||
  665 + ktime_to_ns(ws->last_time) >
  666 + ktime_to_ns(last_activity_ws->last_time))) {
  667 + last_activity_ws = ws;
  668 + }
  669 + }
  670 +
  671 + if (!active && last_activity_ws)
  672 + pr_info("last active wakeup source: %s\n",
  673 + last_activity_ws->name);
  674 + rcu_read_unlock();
  675 +}
  676 +
652 677 /**
653 678 * pm_wakeup_pending - Check if power transition in progress should be aborted.
654 679 *
... ... @@ -671,6 +696,10 @@
671 696 events_check_enabled = !ret;
672 697 }
673 698 spin_unlock_irqrestore(&events_lock, flags);
  699 +
  700 + if (ret)
  701 + print_active_wakeup_sources();
  702 +
674 703 return ret;
675 704 }
676 705