aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/sysfs.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-09-22 16:09:10 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2010-10-16 19:57:43 -0400
commit074037ec79bea73edf1b1ec72fef1010e83e3cc5 (patch)
tree1876caa07f755e680da5ea102d985efe4b508d56 /drivers/base/power/sysfs.c
parent0702d9ee0f1dcb6258789032f03b3208bfafaffc (diff)
PM / Wakeup: Introduce wakeup source objects and event statistics (v3)
Introduce struct wakeup_source for representing system wakeup sources within the kernel and for collecting statistics related to them. Make the recently introduced helper functions pm_wakeup_event(), pm_stay_awake() and pm_relax() use struct wakeup_source objects internally, so that wakeup statistics associated with wakeup devices can be collected and reported in a consistent way (the definition of pm_relax() is changed, which is harmless, because this function is not called directly by anyone yet). Introduce new wakeup-related sysfs device attributes in /sys/devices/.../power for reporting the device wakeup statistics. Change the global wakeup events counters event_count and events_in_progress into atomic variables, so that it is not necessary to acquire a global spinlock in pm_wakeup_event(), pm_stay_awake() and pm_relax(), which should allow us to avoid lock contention in these functions on SMP systems with many wakeup devices. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/power/sysfs.c')
-rw-r--r--drivers/base/power/sysfs.c121
1 files changed, 119 insertions, 2 deletions
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index e56b4388fe61..8859780817e1 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -210,11 +210,122 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
210static ssize_t wakeup_count_show(struct device *dev, 210static ssize_t wakeup_count_show(struct device *dev,
211 struct device_attribute *attr, char *buf) 211 struct device_attribute *attr, char *buf)
212{ 212{
213 return sprintf(buf, "%lu\n", dev->power.wakeup_count); 213 unsigned long count = 0;
214 bool enabled = false;
215
216 spin_lock_irq(&dev->power.lock);
217 if (dev->power.wakeup) {
218 count = dev->power.wakeup->event_count;
219 enabled = true;
220 }
221 spin_unlock_irq(&dev->power.lock);
222 return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
214} 223}
215 224
216static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL); 225static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL);
217#endif 226
227static ssize_t wakeup_active_count_show(struct device *dev,
228 struct device_attribute *attr, char *buf)
229{
230 unsigned long count = 0;
231 bool enabled = false;
232
233 spin_lock_irq(&dev->power.lock);
234 if (dev->power.wakeup) {
235 count = dev->power.wakeup->active_count;
236 enabled = true;
237 }
238 spin_unlock_irq(&dev->power.lock);
239 return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
240}
241
242static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);
243
244static ssize_t wakeup_hit_count_show(struct device *dev,
245 struct device_attribute *attr, char *buf)
246{
247 unsigned long count = 0;
248 bool enabled = false;
249
250 spin_lock_irq(&dev->power.lock);
251 if (dev->power.wakeup) {
252 count = dev->power.wakeup->hit_count;
253 enabled = true;
254 }
255 spin_unlock_irq(&dev->power.lock);
256 return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
257}
258
259static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
260
261static ssize_t wakeup_active_show(struct device *dev,
262 struct device_attribute *attr, char *buf)
263{
264 unsigned int active = 0;
265 bool enabled = false;
266
267 spin_lock_irq(&dev->power.lock);
268 if (dev->power.wakeup) {
269 active = dev->power.wakeup->active;
270 enabled = true;
271 }
272 spin_unlock_irq(&dev->power.lock);
273 return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n");
274}
275
276static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL);
277
278static ssize_t wakeup_total_time_show(struct device *dev,
279 struct device_attribute *attr, char *buf)
280{
281 s64 msec = 0;
282 bool enabled = false;
283
284 spin_lock_irq(&dev->power.lock);
285 if (dev->power.wakeup) {
286 msec = ktime_to_ms(dev->power.wakeup->total_time);
287 enabled = true;
288 }
289 spin_unlock_irq(&dev->power.lock);
290 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
291}
292
293static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL);
294
295static ssize_t wakeup_max_time_show(struct device *dev,
296 struct device_attribute *attr, char *buf)
297{
298 s64 msec = 0;
299 bool enabled = false;
300
301 spin_lock_irq(&dev->power.lock);
302 if (dev->power.wakeup) {
303 msec = ktime_to_ms(dev->power.wakeup->max_time);
304 enabled = true;
305 }
306 spin_unlock_irq(&dev->power.lock);
307 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
308}
309
310static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL);
311
312static ssize_t wakeup_last_time_show(struct device *dev,
313 struct device_attribute *attr, char *buf)
314{
315 s64 msec = 0;
316 bool enabled = false;
317
318 spin_lock_irq(&dev->power.lock);
319 if (dev->power.wakeup) {
320 msec = ktime_to_ms(dev->power.wakeup->last_time);
321 enabled = true;
322 }
323 spin_unlock_irq(&dev->power.lock);
324 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
325}
326
327static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
328#endif /* CONFIG_PM_SLEEP */
218 329
219#ifdef CONFIG_PM_ADVANCED_DEBUG 330#ifdef CONFIG_PM_ADVANCED_DEBUG
220#ifdef CONFIG_PM_RUNTIME 331#ifdef CONFIG_PM_RUNTIME
@@ -288,6 +399,12 @@ static struct attribute * power_attrs[] = {
288 &dev_attr_wakeup.attr, 399 &dev_attr_wakeup.attr,
289#ifdef CONFIG_PM_SLEEP 400#ifdef CONFIG_PM_SLEEP
290 &dev_attr_wakeup_count.attr, 401 &dev_attr_wakeup_count.attr,
402 &dev_attr_wakeup_active_count.attr,
403 &dev_attr_wakeup_hit_count.attr,
404 &dev_attr_wakeup_active.attr,
405 &dev_attr_wakeup_total_time_ms.attr,
406 &dev_attr_wakeup_max_time_ms.attr,
407 &dev_attr_wakeup_last_time_ms.attr,
291#endif 408#endif
292#ifdef CONFIG_PM_ADVANCED_DEBUG 409#ifdef CONFIG_PM_ADVANCED_DEBUG
293 &dev_attr_async.attr, 410 &dev_attr_async.attr,