aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-02-08 17:26:02 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2011-03-14 19:43:14 -0400
commitcb8f51bdadb7969139c2e39c2defd4cde98c1ea8 (patch)
treea6d6e20878460d50b8f61d5fe3237818c54065eb
parent4681b17154b3fd81f898802262985f662344e6ed (diff)
PM: Do not create wakeup sysfs files for devices that cannot wake up
Currently, wakeup sysfs attributes are created for all devices, regardless of whether or not they are wakeup-capable. This is excessive and complicates wakeup device identification from user space (i.e. to identify wakeup-capable devices user space has to read /sys/devices/.../power/wakeup for all devices and see if they are not empty). Fix this issue by avoiding to create wakeup sysfs files for devices that cannot wake up the system from sleep states (i.e. whose power.can_wakeup flags are unset during registration) and modify device_set_wakeup_capable() so that it adds (or removes) the relevant sysfs attributes if a device's wakeup capability status is changed. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power20
-rw-r--r--Documentation/power/devices.txt20
-rw-r--r--drivers/base/power/power.h21
-rw-r--r--drivers/base/power/sysfs.c78
-rw-r--r--drivers/base/power/wakeup.c29
-rw-r--r--include/linux/pm_runtime.h6
-rw-r--r--include/linux/pm_wakeup.h8
7 files changed, 117 insertions, 65 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 7628cd1bc36a..8ffbc25376a0 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -29,9 +29,8 @@ Description:
29 "disabled" to it. 29 "disabled" to it.
30 30
31 For the devices that are not capable of generating system wakeup 31 For the devices that are not capable of generating system wakeup
32 events this file contains "\n". In that cases the user space 32 events this file is not present. In that case the device cannot
33 cannot modify the contents of this file and the device cannot be 33 be enabled to wake up the system from sleep states.
34 enabled to wake up the system.
35 34
36What: /sys/devices/.../power/control 35What: /sys/devices/.../power/control
37Date: January 2009 36Date: January 2009
@@ -85,7 +84,7 @@ Description:
85 The /sys/devices/.../wakeup_count attribute contains the number 84 The /sys/devices/.../wakeup_count attribute contains the number
86 of signaled wakeup events associated with the device. This 85 of signaled wakeup events associated with the device. This
87 attribute is read-only. If the device is not enabled to wake up 86 attribute is read-only. If the device is not enabled to wake up
88 the system from sleep states, this attribute is empty. 87 the system from sleep states, this attribute is not present.
89 88
90What: /sys/devices/.../power/wakeup_active_count 89What: /sys/devices/.../power/wakeup_active_count
91Date: September 2010 90Date: September 2010
@@ -95,7 +94,7 @@ Description:
95 number of times the processing of wakeup events associated with 94 number of times the processing of wakeup events associated with
96 the device was completed (at the kernel level). This attribute 95 the device was completed (at the kernel level). This attribute
97 is read-only. If the device is not enabled to wake up the 96 is read-only. If the device is not enabled to wake up the
98 system from sleep states, this attribute is empty. 97 system from sleep states, this attribute is not present.
99 98
100What: /sys/devices/.../power/wakeup_hit_count 99What: /sys/devices/.../power/wakeup_hit_count
101Date: September 2010 100Date: September 2010
@@ -105,7 +104,8 @@ Description:
105 number of times the processing of a wakeup event associated with 104 number of times the processing of a wakeup event associated with
106 the device might prevent the system from entering a sleep state. 105 the device might prevent the system from entering a sleep state.
107 This attribute is read-only. If the device is not enabled to 106 This attribute is read-only. If the device is not enabled to
108 wake up the system from sleep states, this attribute is empty. 107 wake up the system from sleep states, this attribute is not
108 present.
109 109
110What: /sys/devices/.../power/wakeup_active 110What: /sys/devices/.../power/wakeup_active
111Date: September 2010 111Date: September 2010
@@ -115,7 +115,7 @@ Description:
115 or 0, depending on whether or not a wakeup event associated with 115 or 0, depending on whether or not a wakeup event associated with
116 the device is being processed (1). This attribute is read-only. 116 the device is being processed (1). This attribute is read-only.
117 If the device is not enabled to wake up the system from sleep 117 If the device is not enabled to wake up the system from sleep
118 states, this attribute is empty. 118 states, this attribute is not present.
119 119
120What: /sys/devices/.../power/wakeup_total_time_ms 120What: /sys/devices/.../power/wakeup_total_time_ms
121Date: September 2010 121Date: September 2010
@@ -125,7 +125,7 @@ Description:
125 the total time of processing wakeup events associated with the 125 the total time of processing wakeup events associated with the
126 device, in milliseconds. This attribute is read-only. If the 126 device, in milliseconds. This attribute is read-only. If the
127 device is not enabled to wake up the system from sleep states, 127 device is not enabled to wake up the system from sleep states,
128 this attribute is empty. 128 this attribute is not present.
129 129
130What: /sys/devices/.../power/wakeup_max_time_ms 130What: /sys/devices/.../power/wakeup_max_time_ms
131Date: September 2010 131Date: September 2010
@@ -135,7 +135,7 @@ Description:
135 the maximum time of processing a single wakeup event associated 135 the maximum time of processing a single wakeup event associated
136 with the device, in milliseconds. This attribute is read-only. 136 with the device, in milliseconds. This attribute is read-only.
137 If the device is not enabled to wake up the system from sleep 137 If the device is not enabled to wake up the system from sleep
138 states, this attribute is empty. 138 states, this attribute is not present.
139 139
140What: /sys/devices/.../power/wakeup_last_time_ms 140What: /sys/devices/.../power/wakeup_last_time_ms
141Date: September 2010 141Date: September 2010
@@ -146,7 +146,7 @@ Description:
146 signaling the last wakeup event associated with the device, in 146 signaling the last wakeup event associated with the device, in
147 milliseconds. This attribute is read-only. If the device is 147 milliseconds. This attribute is read-only. If the device is
148 not enabled to wake up the system from sleep states, this 148 not enabled to wake up the system from sleep states, this
149 attribute is empty. 149 attribute is not present.
150 150
151What: /sys/devices/.../power/autosuspend_delay_ms 151What: /sys/devices/.../power/autosuspend_delay_ms
152Date: September 2010 152Date: September 2010
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 57080cd74575..dd9b49251db3 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -159,18 +159,18 @@ matter, and the kernel is responsible for keeping track of it. By contrast,
159whether or not a wakeup-capable device should issue wakeup events is a policy 159whether or not a wakeup-capable device should issue wakeup events is a policy
160decision, and it is managed by user space through a sysfs attribute: the 160decision, and it is managed by user space through a sysfs attribute: the
161power/wakeup file. User space can write the strings "enabled" or "disabled" to 161power/wakeup file. User space can write the strings "enabled" or "disabled" to
162set or clear the should_wakeup flag, respectively. Reads from the file will 162set or clear the "should_wakeup" flag, respectively. This file is only present
163return the corresponding string if can_wakeup is true, but if can_wakeup is 163for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
164false then reads will return an empty string, to indicate that the device 164and is created (or removed) by device_set_wakeup_capable(). Reads from the
165doesn't support wakeup events. (But even though the file appears empty, writes 165file will return the corresponding string.
166will still affect the should_wakeup flag.)
167 166
168The device_may_wakeup() routine returns true only if both flags are set. 167The device_may_wakeup() routine returns true only if both flags are set.
169Drivers should check this routine when putting devices in a low-power state 168This information is used by subsystems, like the PCI bus type code, to see
170during a system sleep transition, to see whether or not to enable the devices' 169whether or not to enable the devices' wakeup mechanisms. If device wakeup
171wakeup mechanisms. However for runtime power management, wakeup events should 170mechanisms are enabled or disabled directly by drivers, they also should use
172be enabled whenever the device and driver both support them, regardless of the 171device_may_wakeup() to decide what to do during a system sleep transition.
173should_wakeup flag. 172However for runtime power management, wakeup events should be enabled whenever
173the device and driver both support them, regardless of the should_wakeup flag.
174 174
175 175
176/sys/devices/.../power/control files 176/sys/devices/.../power/control files
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 698dde742587..f2a25f18fde7 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -58,19 +58,18 @@ static inline void device_pm_move_last(struct device *dev) {}
58 * sysfs.c 58 * sysfs.c
59 */ 59 */
60 60
61extern int dpm_sysfs_add(struct device *); 61extern int dpm_sysfs_add(struct device *dev);
62extern void dpm_sysfs_remove(struct device *); 62extern void dpm_sysfs_remove(struct device *dev);
63extern void rpm_sysfs_remove(struct device *); 63extern void rpm_sysfs_remove(struct device *dev);
64extern int wakeup_sysfs_add(struct device *dev);
65extern void wakeup_sysfs_remove(struct device *dev);
64 66
65#else /* CONFIG_PM */ 67#else /* CONFIG_PM */
66 68
67static inline int dpm_sysfs_add(struct device *dev) 69static inline int dpm_sysfs_add(struct device *dev) { return 0; }
68{ 70static inline void dpm_sysfs_remove(struct device *dev) {}
69 return 0; 71static inline void rpm_sysfs_remove(struct device *dev) {}
70} 72static inline int wakeup_sysfs_add(struct device *dev) { return 0; }
71 73static inline void wakeup_sysfs_remove(struct device *dev) {}
72static inline void dpm_sysfs_remove(struct device *dev)
73{
74}
75 74
76#endif 75#endif
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 0b1e46bf3e56..fff49bee781d 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -431,26 +431,18 @@ static ssize_t async_store(struct device *dev, struct device_attribute *attr,
431static DEVICE_ATTR(async, 0644, async_show, async_store); 431static DEVICE_ATTR(async, 0644, async_show, async_store);
432#endif /* CONFIG_PM_ADVANCED_DEBUG */ 432#endif /* CONFIG_PM_ADVANCED_DEBUG */
433 433
434static struct attribute * power_attrs[] = { 434static struct attribute *power_attrs[] = {
435 &dev_attr_wakeup.attr,
436#ifdef CONFIG_PM_SLEEP
437 &dev_attr_wakeup_count.attr,
438 &dev_attr_wakeup_active_count.attr,
439 &dev_attr_wakeup_hit_count.attr,
440 &dev_attr_wakeup_active.attr,
441 &dev_attr_wakeup_total_time_ms.attr,
442 &dev_attr_wakeup_max_time_ms.attr,
443 &dev_attr_wakeup_last_time_ms.attr,
444#endif
445#ifdef CONFIG_PM_ADVANCED_DEBUG 435#ifdef CONFIG_PM_ADVANCED_DEBUG
436#ifdef CONFIG_PM_SLEEP
446 &dev_attr_async.attr, 437 &dev_attr_async.attr,
438#endif
447#ifdef CONFIG_PM_RUNTIME 439#ifdef CONFIG_PM_RUNTIME
448 &dev_attr_runtime_status.attr, 440 &dev_attr_runtime_status.attr,
449 &dev_attr_runtime_usage.attr, 441 &dev_attr_runtime_usage.attr,
450 &dev_attr_runtime_active_kids.attr, 442 &dev_attr_runtime_active_kids.attr,
451 &dev_attr_runtime_enabled.attr, 443 &dev_attr_runtime_enabled.attr,
452#endif 444#endif
453#endif 445#endif /* CONFIG_PM_ADVANCED_DEBUG */
454 NULL, 446 NULL,
455}; 447};
456static struct attribute_group pm_attr_group = { 448static struct attribute_group pm_attr_group = {
@@ -458,9 +450,26 @@ static struct attribute_group pm_attr_group = {
458 .attrs = power_attrs, 450 .attrs = power_attrs,
459}; 451};
460 452
461#ifdef CONFIG_PM_RUNTIME 453static struct attribute *wakeup_attrs[] = {
454#ifdef CONFIG_PM_SLEEP
455 &dev_attr_wakeup.attr,
456 &dev_attr_wakeup_count.attr,
457 &dev_attr_wakeup_active_count.attr,
458 &dev_attr_wakeup_hit_count.attr,
459 &dev_attr_wakeup_active.attr,
460 &dev_attr_wakeup_total_time_ms.attr,
461 &dev_attr_wakeup_max_time_ms.attr,
462 &dev_attr_wakeup_last_time_ms.attr,
463#endif
464 NULL,
465};
466static struct attribute_group pm_wakeup_attr_group = {
467 .name = power_group_name,
468 .attrs = wakeup_attrs,
469};
462 470
463static struct attribute *runtime_attrs[] = { 471static struct attribute *runtime_attrs[] = {
472#ifdef CONFIG_PM_RUNTIME
464#ifndef CONFIG_PM_ADVANCED_DEBUG 473#ifndef CONFIG_PM_ADVANCED_DEBUG
465 &dev_attr_runtime_status.attr, 474 &dev_attr_runtime_status.attr,
466#endif 475#endif
@@ -468,6 +477,7 @@ static struct attribute *runtime_attrs[] = {
468 &dev_attr_runtime_suspended_time.attr, 477 &dev_attr_runtime_suspended_time.attr,
469 &dev_attr_runtime_active_time.attr, 478 &dev_attr_runtime_active_time.attr,
470 &dev_attr_autosuspend_delay_ms.attr, 479 &dev_attr_autosuspend_delay_ms.attr,
480#endif /* CONFIG_PM_RUNTIME */
471 NULL, 481 NULL,
472}; 482};
473static struct attribute_group pm_runtime_attr_group = { 483static struct attribute_group pm_runtime_attr_group = {
@@ -480,35 +490,49 @@ int dpm_sysfs_add(struct device *dev)
480 int rc; 490 int rc;
481 491
482 rc = sysfs_create_group(&dev->kobj, &pm_attr_group); 492 rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
483 if (rc == 0 && !dev->power.no_callbacks) { 493 if (rc)
494 return rc;
495
496 if (pm_runtime_callbacks_present(dev)) {
484 rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group); 497 rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
485 if (rc) 498 if (rc)
486 sysfs_remove_group(&dev->kobj, &pm_attr_group); 499 goto err_out;
500 }
501
502 if (device_can_wakeup(dev)) {
503 rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
504 if (rc) {
505 if (pm_runtime_callbacks_present(dev))
506 sysfs_unmerge_group(&dev->kobj,
507 &pm_runtime_attr_group);
508 goto err_out;
509 }
487 } 510 }
511 return 0;
512
513 err_out:
514 sysfs_remove_group(&dev->kobj, &pm_attr_group);
488 return rc; 515 return rc;
489} 516}
490 517
491void rpm_sysfs_remove(struct device *dev) 518int wakeup_sysfs_add(struct device *dev)
492{ 519{
493 sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group); 520 return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
494} 521}
495 522
496void dpm_sysfs_remove(struct device *dev) 523void wakeup_sysfs_remove(struct device *dev)
497{ 524{
498 rpm_sysfs_remove(dev); 525 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
499 sysfs_remove_group(&dev->kobj, &pm_attr_group);
500} 526}
501 527
502#else /* CONFIG_PM_RUNTIME */ 528void rpm_sysfs_remove(struct device *dev)
503
504int dpm_sysfs_add(struct device * dev)
505{ 529{
506 return sysfs_create_group(&dev->kobj, &pm_attr_group); 530 sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
507} 531}
508 532
509void dpm_sysfs_remove(struct device * dev) 533void dpm_sysfs_remove(struct device *dev)
510{ 534{
535 rpm_sysfs_remove(dev);
536 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
511 sysfs_remove_group(&dev->kobj, &pm_attr_group); 537 sysfs_remove_group(&dev->kobj, &pm_attr_group);
512} 538}
513
514#endif
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 82836383997f..4573c83df6dd 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -242,6 +242,35 @@ int device_wakeup_disable(struct device *dev)
242EXPORT_SYMBOL_GPL(device_wakeup_disable); 242EXPORT_SYMBOL_GPL(device_wakeup_disable);
243 243
244/** 244/**
245 * device_set_wakeup_capable - Set/reset device wakeup capability flag.
246 * @dev: Device to handle.
247 * @capable: Whether or not @dev is capable of waking up the system from sleep.
248 *
249 * If @capable is set, set the @dev's power.can_wakeup flag and add its
250 * wakeup-related attributes to sysfs. Otherwise, unset the @dev's
251 * power.can_wakeup flag and remove its wakeup-related attributes from sysfs.
252 *
253 * This function may sleep and it can't be called from any context where
254 * sleeping is not allowed.
255 */
256void device_set_wakeup_capable(struct device *dev, bool capable)
257{
258 if (!!dev->power.can_wakeup == !!capable)
259 return;
260
261 if (device_is_registered(dev)) {
262 if (capable) {
263 if (wakeup_sysfs_add(dev))
264 return;
265 } else {
266 wakeup_sysfs_remove(dev);
267 }
268 }
269 dev->power.can_wakeup = capable;
270}
271EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
272
273/**
245 * device_init_wakeup - Device wakeup initialization. 274 * device_init_wakeup - Device wakeup initialization.
246 * @dev: Device to handle. 275 * @dev: Device to handle.
247 * @enable: Whether or not to enable @dev as a wakeup device. 276 * @enable: Whether or not to enable @dev as a wakeup device.
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index d34f067e2a7f..8de9aa6e7def 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -87,6 +87,11 @@ static inline bool pm_runtime_enabled(struct device *dev)
87 return !dev->power.disable_depth; 87 return !dev->power.disable_depth;
88} 88}
89 89
90static inline bool pm_runtime_callbacks_present(struct device *dev)
91{
92 return !dev->power.no_callbacks;
93}
94
90static inline void pm_runtime_mark_last_busy(struct device *dev) 95static inline void pm_runtime_mark_last_busy(struct device *dev)
91{ 96{
92 ACCESS_ONCE(dev->power.last_busy) = jiffies; 97 ACCESS_ONCE(dev->power.last_busy) = jiffies;
@@ -133,6 +138,7 @@ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
133static inline void pm_runtime_no_callbacks(struct device *dev) {} 138static inline void pm_runtime_no_callbacks(struct device *dev) {}
134static inline void pm_runtime_irq_safe(struct device *dev) {} 139static inline void pm_runtime_irq_safe(struct device *dev) {}
135 140
141static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; }
136static inline void pm_runtime_mark_last_busy(struct device *dev) {} 142static inline void pm_runtime_mark_last_busy(struct device *dev) {}
137static inline void __pm_runtime_use_autosuspend(struct device *dev, 143static inline void __pm_runtime_use_autosuspend(struct device *dev,
138 bool use) {} 144 bool use) {}
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 03a67db03d01..a32da962d693 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -62,18 +62,11 @@ struct wakeup_source {
62 * Changes to device_may_wakeup take effect on the next pm state change. 62 * Changes to device_may_wakeup take effect on the next pm state change.
63 */ 63 */
64 64
65static inline void device_set_wakeup_capable(struct device *dev, bool capable)
66{
67 dev->power.can_wakeup = capable;
68}
69
70static inline bool device_can_wakeup(struct device *dev) 65static inline bool device_can_wakeup(struct device *dev)
71{ 66{
72 return dev->power.can_wakeup; 67 return dev->power.can_wakeup;
73} 68}
74 69
75
76
77static inline bool device_may_wakeup(struct device *dev) 70static inline bool device_may_wakeup(struct device *dev)
78{ 71{
79 return dev->power.can_wakeup && !!dev->power.wakeup; 72 return dev->power.can_wakeup && !!dev->power.wakeup;
@@ -88,6 +81,7 @@ extern struct wakeup_source *wakeup_source_register(const char *name);
88extern void wakeup_source_unregister(struct wakeup_source *ws); 81extern void wakeup_source_unregister(struct wakeup_source *ws);
89extern int device_wakeup_enable(struct device *dev); 82extern int device_wakeup_enable(struct device *dev);
90extern int device_wakeup_disable(struct device *dev); 83extern int device_wakeup_disable(struct device *dev);
84extern void device_set_wakeup_capable(struct device *dev, bool capable);
91extern int device_init_wakeup(struct device *dev, bool val); 85extern int device_init_wakeup(struct device *dev, bool val);
92extern int device_set_wakeup_enable(struct device *dev, bool enable); 86extern int device_set_wakeup_enable(struct device *dev, bool enable);
93extern void __pm_stay_awake(struct wakeup_source *ws); 87extern void __pm_stay_awake(struct wakeup_source *ws);