diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-17 20:25:38 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-17 20:25:38 +0200 |
commit | d6a56ae7ac6121ef99500b3380e98f83a3d9e102 (patch) | |
tree | 372217920c4cbbf11eb7e332ddfa54e63eaa9d25 /drivers | |
parent | 079d364b042afbe811c4bb0cb57fcbf4f1cfab6d (diff) | |
parent | bbdc18a3fb6740619f0d037241c85dc6cd4517aa (diff) |
Merge branch 'pm-sleep'
* pm-sleep:
properly __init-annotate pm_sysrq_init()
PM / wakeup: Use irqsave/irqrestore for events_lock
PM / Freezer: Fix small typo "regrigerator"
PM / Sleep: Print name of wakeup source that aborts suspend
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/power/wakeup.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index cbb463b3a75..e6ee5e80e54 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -127,6 +127,8 @@ EXPORT_SYMBOL_GPL(wakeup_source_destroy); */ void wakeup_source_add(struct wakeup_source *ws) { + unsigned long flags; + if (WARN_ON(!ws)) return; @@ -135,9 +137,9 @@ void wakeup_source_add(struct wakeup_source *ws) ws->active = false; ws->last_time = ktime_get(); - spin_lock_irq(&events_lock); + spin_lock_irqsave(&events_lock, flags); list_add_rcu(&ws->entry, &wakeup_sources); - spin_unlock_irq(&events_lock); + spin_unlock_irqrestore(&events_lock, flags); } EXPORT_SYMBOL_GPL(wakeup_source_add); @@ -147,12 +149,14 @@ EXPORT_SYMBOL_GPL(wakeup_source_add); */ void wakeup_source_remove(struct wakeup_source *ws) { + unsigned long flags; + if (WARN_ON(!ws)) return; - spin_lock_irq(&events_lock); + spin_lock_irqsave(&events_lock, flags); list_del_rcu(&ws->entry); - spin_unlock_irq(&events_lock); + spin_unlock_irqrestore(&events_lock, flags); synchronize_rcu(); } EXPORT_SYMBOL_GPL(wakeup_source_remove); @@ -649,6 +653,31 @@ void pm_wakeup_event(struct device *dev, unsigned int msec) } EXPORT_SYMBOL_GPL(pm_wakeup_event); +static void print_active_wakeup_sources(void) +{ + struct wakeup_source *ws; + int active = 0; + struct wakeup_source *last_activity_ws = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(ws, &wakeup_sources, entry) { + if (ws->active) { + pr_info("active wakeup source: %s\n", ws->name); + active = 1; + } else if (!active && + (!last_activity_ws || + ktime_to_ns(ws->last_time) > + ktime_to_ns(last_activity_ws->last_time))) { + last_activity_ws = ws; + } + } + + if (!active && last_activity_ws) + pr_info("last active wakeup source: %s\n", + last_activity_ws->name); + rcu_read_unlock(); +} + /** * pm_wakeup_pending - Check if power transition in progress should be aborted. * @@ -671,6 +700,10 @@ bool pm_wakeup_pending(void) events_check_enabled = !ret; } spin_unlock_irqrestore(&events_lock, flags); + + if (ret) + print_active_wakeup_sources(); + return ret; } @@ -723,15 +756,16 @@ bool pm_get_wakeup_count(unsigned int *count, bool block) bool pm_save_wakeup_count(unsigned int count) { unsigned int cnt, inpr; + unsigned long flags; events_check_enabled = false; - spin_lock_irq(&events_lock); + spin_lock_irqsave(&events_lock, flags); split_counters(&cnt, &inpr); if (cnt == count && inpr == 0) { saved_count = count; events_check_enabled = true; } - spin_unlock_irq(&events_lock); + spin_unlock_irqrestore(&events_lock, flags); return events_check_enabled; } |