diff options
Diffstat (limited to 'drivers/base')
| -rw-r--r-- | drivers/base/power/sysfs.c | 30 | ||||
| -rw-r--r-- | drivers/base/power/wakeup.c | 64 | 
2 files changed, 53 insertions, 41 deletions
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 95c12f6cb5b..13e40b9021b 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -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) @@ -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, diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 92f220d89d3..7a6eada4534 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -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. @@ -383,6 +383,21 @@ static void wakeup_source_activate(struct wakeup_source *ws)  }  /** + * 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.   * @@ -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; @@ -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; @@ -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);  } @@ -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); @@ -614,24 +627,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.   *   * Compare the current number of registered wakeup events with its preserved @@ -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;  } @@ -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();  	} @@ -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;  } @@ -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)); @@ -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)  |