Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305833
b: refs/heads/master
c: 30e3ce6
h: refs/heads/master
i:
  305831: 688645d
v: v3
  • Loading branch information
Rafael J. Wysocki committed May 1, 2012
1 parent df01ca1 commit 7013b63
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 53 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 60af1066913162c5dd13fad3b872a67b1eb7da0f
refs/heads/master: 30e3ce6dcbe3fc29c343b17e768b07d4a795de21
24 changes: 17 additions & 7 deletions trunk/Documentation/ABI/testing/sysfs-devices-power
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,26 @@ Description:
is read-only. If the device is not enabled to wake up the
system from sleep states, this attribute is not present.

What: /sys/devices/.../power/wakeup_hit_count
Date: September 2010
What: /sys/devices/.../power/wakeup_abort_count
Date: February 2012
Contact: Rafael J. Wysocki <rjw@sisk.pl>
Description:
The /sys/devices/.../wakeup_hit_count attribute contains the
The /sys/devices/.../wakeup_abort_count attribute contains the
number of times the processing of a wakeup event associated with
the device might prevent the system from entering a sleep state.
This attribute is read-only. If the device is not enabled to
wake up the system from sleep states, this attribute is not
present.
the device might have aborted system transition into a sleep
state in progress. This attribute is read-only. If the device
is not enabled to wake up the system from sleep states, this
attribute is not present.

What: /sys/devices/.../power/wakeup_expire_count
Date: February 2012
Contact: Rafael J. Wysocki <rjw@sisk.pl>
Description:
The /sys/devices/.../wakeup_expire_count attribute contains the
number of times a wakeup event associated with the device has
been reported with a timeout that expired. This attribute is
read-only. If the device is not enabled to wake up the system
from sleep states, this attribute is not present.

What: /sys/devices/.../power/wakeup_active
Date: September 2010
Expand Down
30 changes: 25 additions & 5 deletions trunk/drivers/base/power/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,22 +314,41 @@ static ssize_t wakeup_active_count_show(struct device *dev,

static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);

static ssize_t wakeup_hit_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t wakeup_abort_count_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long count = 0;
bool enabled = false;

spin_lock_irq(&dev->power.lock);
if (dev->power.wakeup) {
count = dev->power.wakeup->wakeup_count;
enabled = true;
}
spin_unlock_irq(&dev->power.lock);
return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
}

static DEVICE_ATTR(wakeup_abort_count, 0444, wakeup_abort_count_show, NULL);

static ssize_t wakeup_expire_count_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long count = 0;
bool enabled = false;

spin_lock_irq(&dev->power.lock);
if (dev->power.wakeup) {
count = dev->power.wakeup->hit_count;
count = dev->power.wakeup->expire_count;
enabled = true;
}
spin_unlock_irq(&dev->power.lock);
return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
}

static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
static DEVICE_ATTR(wakeup_expire_count, 0444, wakeup_expire_count_show, NULL);

static ssize_t wakeup_active_show(struct device *dev,
struct device_attribute *attr, char *buf)
Expand Down Expand Up @@ -486,7 +505,8 @@ static struct attribute *wakeup_attrs[] = {
&dev_attr_wakeup.attr,
&dev_attr_wakeup_count.attr,
&dev_attr_wakeup_active_count.attr,
&dev_attr_wakeup_hit_count.attr,
&dev_attr_wakeup_abort_count.attr,
&dev_attr_wakeup_expire_count.attr,
&dev_attr_wakeup_active.attr,
&dev_attr_wakeup_total_time_ms.attr,
&dev_attr_wakeup_max_time_ms.attr,
Expand Down
64 changes: 28 additions & 36 deletions trunk/drivers/base/power/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* If set, the suspend/hibernate code will abort transitions to a sleep state
* if wakeup events are registered during or immediately before the transition.
*/
bool events_check_enabled;
bool events_check_enabled __read_mostly;

/*
* Combined counters of registered wakeup events and wakeup events in progress.
Expand Down Expand Up @@ -382,6 +382,21 @@ static void wakeup_source_activate(struct wakeup_source *ws)
atomic_inc(&combined_event_count);
}

/**
* wakeup_source_report_event - Report wakeup event using the given source.
* @ws: Wakeup source to report the event for.
*/
static void wakeup_source_report_event(struct wakeup_source *ws)
{
ws->event_count++;
/* This is racy, but the counter is approximate anyway. */
if (events_check_enabled)
ws->wakeup_count++;

if (!ws->active)
wakeup_source_activate(ws);
}

/**
* __pm_stay_awake - Notify the PM core of a wakeup event.
* @ws: Wakeup source object associated with the source of the event.
Expand All @@ -397,10 +412,7 @@ void __pm_stay_awake(struct wakeup_source *ws)

spin_lock_irqsave(&ws->lock, flags);

ws->event_count++;
if (!ws->active)
wakeup_source_activate(ws);

wakeup_source_report_event(ws);
del_timer(&ws->timer);
ws->timer_expires = 0;

Expand Down Expand Up @@ -469,6 +481,7 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
ws->max_time = duration;

ws->last_time = now;
del_timer(&ws->timer);
ws->timer_expires = 0;

Expand Down Expand Up @@ -541,8 +554,10 @@ static void pm_wakeup_timer_fn(unsigned long data)
spin_lock_irqsave(&ws->lock, flags);

if (ws->active && ws->timer_expires
&& time_after_eq(jiffies, ws->timer_expires))
&& time_after_eq(jiffies, ws->timer_expires)) {
wakeup_source_deactivate(ws);
ws->expire_count++;
}

spin_unlock_irqrestore(&ws->lock, flags);
}
Expand All @@ -569,9 +584,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)

spin_lock_irqsave(&ws->lock, flags);

ws->event_count++;
if (!ws->active)
wakeup_source_activate(ws);
wakeup_source_report_event(ws);

if (!msec) {
wakeup_source_deactivate(ws);
Expand Down Expand Up @@ -613,24 +626,6 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
}
EXPORT_SYMBOL_GPL(pm_wakeup_event);

/**
* pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
*/
static void pm_wakeup_update_hit_counts(void)
{
unsigned long flags;
struct wakeup_source *ws;

rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
spin_lock_irqsave(&ws->lock, flags);
if (ws->active)
ws->hit_count++;
spin_unlock_irqrestore(&ws->lock, flags);
}
rcu_read_unlock();
}

/**
* pm_wakeup_pending - Check if power transition in progress should be aborted.
*
Expand All @@ -653,8 +648,6 @@ bool pm_wakeup_pending(void)
events_check_enabled = !ret;
}
spin_unlock_irqrestore(&events_lock, flags);
if (ret)
pm_wakeup_update_hit_counts();
return ret;
}

Expand All @@ -680,7 +673,6 @@ bool pm_get_wakeup_count(unsigned int *count)
split_counters(&cnt, &inpr);
if (inpr == 0 || signal_pending(current))
break;
pm_wakeup_update_hit_counts();

schedule();
}
Expand Down Expand Up @@ -713,8 +705,6 @@ bool pm_save_wakeup_count(unsigned int count)
events_check_enabled = true;
}
spin_unlock_irq(&events_lock);
if (!events_check_enabled)
pm_wakeup_update_hit_counts();
return events_check_enabled;
}

Expand Down Expand Up @@ -749,9 +739,10 @@ static int print_wakeup_source_stats(struct seq_file *m,
active_time = ktime_set(0, 0);
}

ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t"
ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t"
"%lld\t\t%lld\t\t%lld\t\t%lld\n",
ws->name, active_count, ws->event_count, ws->hit_count,
ws->name, active_count, ws->event_count,
ws->wakeup_count, ws->expire_count,
ktime_to_ms(active_time), ktime_to_ms(total_time),
ktime_to_ms(max_time), ktime_to_ms(ws->last_time));

Expand All @@ -768,8 +759,9 @@ static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
{
struct wakeup_source *ws;

seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t"
"active_since\ttotal_time\tmax_time\tlast_change\n");
seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
"expire_count\tactive_since\ttotal_time\tmax_time\t"
"last_change\n");

rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
Expand Down
11 changes: 7 additions & 4 deletions trunk/include/linux/pm_wakeup.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
*
* @total_time: Total time this wakeup source has been active.
* @max_time: Maximum time this wakeup source has been continuously active.
* @last_time: Monotonic clock when the wakeup source's was activated last time.
* @last_time: Monotonic clock when the wakeup source's was touched last time.
* @event_count: Number of signaled wakeup events.
* @active_count: Number of times the wakeup sorce was activated.
* @relax_count: Number of times the wakeup sorce was deactivated.
* @hit_count: Number of times the wakeup sorce might abort system suspend.
* @expire_count: Number of times the wakeup source's timeout has expired.
* @wakeup_count: Number of times the wakeup source might abort suspend.
* @active: Status of the wakeup source.
* @has_timeout: The wakeup source has been activated with a timeout.
*/
struct wakeup_source {
const char *name;
Expand All @@ -52,8 +54,9 @@ struct wakeup_source {
unsigned long event_count;
unsigned long active_count;
unsigned long relax_count;
unsigned long hit_count;
unsigned int active:1;
unsigned long expire_count;
unsigned long wakeup_count;
bool active:1;
};

#ifdef CONFIG_PM_SLEEP
Expand Down

0 comments on commit 7013b63

Please sign in to comment.