Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+121 -69
+10 -10
Documentation/ABI/testing/sysfs-devices-power
··· 29 29 "disabled" to it. 30 30 31 31 For the devices that are not capable of generating system wakeup 32 - events this file contains "\n". In that cases the user space 33 - cannot modify the contents of this file and the device cannot be 34 - enabled to wake up the system. 32 + events this file is not present. In that case the device cannot 33 + be enabled to wake up the system from sleep states. 35 34 36 35 What: /sys/devices/.../power/control 37 36 Date: January 2009 ··· 84 85 The /sys/devices/.../wakeup_count attribute contains the number 85 86 of signaled wakeup events associated with the device. This 86 87 attribute is read-only. If the device is not enabled to wake up 87 - the system from sleep states, this attribute is empty. 88 + the system from sleep states, this attribute is not present. 88 89 89 90 What: /sys/devices/.../power/wakeup_active_count 90 91 Date: September 2010 ··· 94 95 number of times the processing of wakeup events associated with 95 96 the device was completed (at the kernel level). This attribute 96 97 is read-only. If the device is not enabled to wake up the 97 - system from sleep states, this attribute is empty. 98 + system from sleep states, this attribute is not present. 98 99 99 100 What: /sys/devices/.../power/wakeup_hit_count 100 101 Date: September 2010 ··· 104 105 number of times the processing of a wakeup event associated with 105 106 the device might prevent the system from entering a sleep state. 106 107 This attribute is read-only. If the device is not enabled to 107 - wake up the system from sleep states, this attribute is empty. 108 + wake up the system from sleep states, this attribute is not 109 + present. 108 110 109 111 What: /sys/devices/.../power/wakeup_active 110 112 Date: September 2010 ··· 115 115 or 0, depending on whether or not a wakeup event associated with 116 116 the device is being processed (1). This attribute is read-only. 117 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 120 120 What: /sys/devices/.../power/wakeup_total_time_ms 121 121 Date: September 2010 ··· 125 125 the total time of processing wakeup events associated with the 126 126 device, in milliseconds. This attribute is read-only. If the 127 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 130 130 What: /sys/devices/.../power/wakeup_max_time_ms 131 131 Date: September 2010 ··· 135 135 the maximum time of processing a single wakeup event associated 136 136 with the device, in milliseconds. This attribute is read-only. 137 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 140 140 What: /sys/devices/.../power/wakeup_last_time_ms 141 141 Date: September 2010 ··· 146 146 signaling the last wakeup event associated with the device, in 147 147 milliseconds. This attribute is read-only. If the device is 148 148 not enabled to wake up the system from sleep states, this 149 - attribute is empty. 149 + attribute is not present. 150 150 151 151 What: /sys/devices/.../power/autosuspend_delay_ms 152 152 Date: September 2010
+10 -10
Documentation/power/devices.txt
··· 159 159 whether or not a wakeup-capable device should issue wakeup events is a policy 160 160 decision, and it is managed by user space through a sysfs attribute: the 161 161 power/wakeup file. User space can write the strings "enabled" or "disabled" to 162 - set or clear the should_wakeup flag, respectively. Reads from the file will 163 - return the corresponding string if can_wakeup is true, but if can_wakeup is 164 - false then reads will return an empty string, to indicate that the device 165 - doesn't support wakeup events. (But even though the file appears empty, writes 166 - will still affect the should_wakeup flag.) 162 + set or clear the "should_wakeup" flag, respectively. This file is only present 163 + for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set) 164 + and is created (or removed) by device_set_wakeup_capable(). Reads from the 165 + file will return the corresponding string. 167 166 168 167 The device_may_wakeup() routine returns true only if both flags are set. 169 - Drivers should check this routine when putting devices in a low-power state 170 - during a system sleep transition, to see whether or not to enable the devices' 171 - wakeup mechanisms. However for runtime power management, wakeup events should 172 - be enabled whenever the device and driver both support them, regardless of the 173 - should_wakeup flag. 168 + This information is used by subsystems, like the PCI bus type code, to see 169 + whether or not to enable the devices' wakeup mechanisms. If device wakeup 170 + mechanisms are enabled or disabled directly by drivers, they also should use 171 + device_may_wakeup() to decide what to do during a system sleep transition. 172 + However for runtime power management, wakeup events should be enabled whenever 173 + the device and driver both support them, regardless of the should_wakeup flag. 174 174 175 175 176 176 /sys/devices/.../power/control files
+10 -11
drivers/base/power/power.h
··· 58 58 * sysfs.c 59 59 */ 60 60 61 - extern int dpm_sysfs_add(struct device *); 62 - extern void dpm_sysfs_remove(struct device *); 63 - extern void rpm_sysfs_remove(struct device *); 61 + extern int dpm_sysfs_add(struct device *dev); 62 + extern void dpm_sysfs_remove(struct device *dev); 63 + extern void rpm_sysfs_remove(struct device *dev); 64 + extern int wakeup_sysfs_add(struct device *dev); 65 + extern void wakeup_sysfs_remove(struct device *dev); 64 66 65 67 #else /* CONFIG_PM */ 66 68 67 - static inline int dpm_sysfs_add(struct device *dev) 68 - { 69 - return 0; 70 - } 71 - 72 - static inline void dpm_sysfs_remove(struct device *dev) 73 - { 74 - } 69 + static inline int dpm_sysfs_add(struct device *dev) { return 0; } 70 + static inline void dpm_sysfs_remove(struct device *dev) {} 71 + static inline void rpm_sysfs_remove(struct device *dev) {} 72 + static inline int wakeup_sysfs_add(struct device *dev) { return 0; } 73 + static inline void wakeup_sysfs_remove(struct device *dev) {} 75 74 76 75 #endif
+55 -31
drivers/base/power/sysfs.c
··· 431 431 static DEVICE_ATTR(async, 0644, async_show, async_store); 432 432 #endif /* CONFIG_PM_ADVANCED_DEBUG */ 433 433 434 - static struct attribute * power_attrs[] = { 435 - &dev_attr_wakeup.attr, 434 + static struct attribute *power_attrs[] = { 435 + #ifdef CONFIG_PM_ADVANCED_DEBUG 436 436 #ifdef CONFIG_PM_SLEEP 437 + &dev_attr_async.attr, 438 + #endif 439 + #ifdef CONFIG_PM_RUNTIME 440 + &dev_attr_runtime_status.attr, 441 + &dev_attr_runtime_usage.attr, 442 + &dev_attr_runtime_active_kids.attr, 443 + &dev_attr_runtime_enabled.attr, 444 + #endif 445 + #endif /* CONFIG_PM_ADVANCED_DEBUG */ 446 + NULL, 447 + }; 448 + static struct attribute_group pm_attr_group = { 449 + .name = power_group_name, 450 + .attrs = power_attrs, 451 + }; 452 + 453 + static struct attribute *wakeup_attrs[] = { 454 + #ifdef CONFIG_PM_SLEEP 455 + &dev_attr_wakeup.attr, 437 456 &dev_attr_wakeup_count.attr, 438 457 &dev_attr_wakeup_active_count.attr, 439 458 &dev_attr_wakeup_hit_count.attr, ··· 461 442 &dev_attr_wakeup_max_time_ms.attr, 462 443 &dev_attr_wakeup_last_time_ms.attr, 463 444 #endif 464 - #ifdef CONFIG_PM_ADVANCED_DEBUG 465 - &dev_attr_async.attr, 466 - #ifdef CONFIG_PM_RUNTIME 467 - &dev_attr_runtime_status.attr, 468 - &dev_attr_runtime_usage.attr, 469 - &dev_attr_runtime_active_kids.attr, 470 - &dev_attr_runtime_enabled.attr, 471 - #endif 472 - #endif 473 445 NULL, 474 446 }; 475 - static struct attribute_group pm_attr_group = { 447 + static struct attribute_group pm_wakeup_attr_group = { 476 448 .name = power_group_name, 477 - .attrs = power_attrs, 449 + .attrs = wakeup_attrs, 478 450 }; 479 451 480 - #ifdef CONFIG_PM_RUNTIME 481 - 482 452 static struct attribute *runtime_attrs[] = { 453 + #ifdef CONFIG_PM_RUNTIME 483 454 #ifndef CONFIG_PM_ADVANCED_DEBUG 484 455 &dev_attr_runtime_status.attr, 485 456 #endif ··· 477 468 &dev_attr_runtime_suspended_time.attr, 478 469 &dev_attr_runtime_active_time.attr, 479 470 &dev_attr_autosuspend_delay_ms.attr, 471 + #endif /* CONFIG_PM_RUNTIME */ 480 472 NULL, 481 473 }; 482 474 static struct attribute_group pm_runtime_attr_group = { ··· 490 480 int rc; 491 481 492 482 rc = sysfs_create_group(&dev->kobj, &pm_attr_group); 493 - if (rc == 0 && !dev->power.no_callbacks) { 483 + if (rc) 484 + return rc; 485 + 486 + if (pm_runtime_callbacks_present(dev)) { 494 487 rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group); 495 488 if (rc) 496 - sysfs_remove_group(&dev->kobj, &pm_attr_group); 489 + goto err_out; 497 490 } 491 + 492 + if (device_can_wakeup(dev)) { 493 + rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); 494 + if (rc) { 495 + if (pm_runtime_callbacks_present(dev)) 496 + sysfs_unmerge_group(&dev->kobj, 497 + &pm_runtime_attr_group); 498 + goto err_out; 499 + } 500 + } 501 + return 0; 502 + 503 + err_out: 504 + sysfs_remove_group(&dev->kobj, &pm_attr_group); 498 505 return rc; 506 + } 507 + 508 + int wakeup_sysfs_add(struct device *dev) 509 + { 510 + return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); 511 + } 512 + 513 + void wakeup_sysfs_remove(struct device *dev) 514 + { 515 + sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); 499 516 } 500 517 501 518 void rpm_sysfs_remove(struct device *dev) ··· 533 496 void dpm_sysfs_remove(struct device *dev) 534 497 { 535 498 rpm_sysfs_remove(dev); 499 + sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); 536 500 sysfs_remove_group(&dev->kobj, &pm_attr_group); 537 501 } 538 - 539 - #else /* CONFIG_PM_RUNTIME */ 540 - 541 - int dpm_sysfs_add(struct device * dev) 542 - { 543 - return sysfs_create_group(&dev->kobj, &pm_attr_group); 544 - } 545 - 546 - void dpm_sysfs_remove(struct device * dev) 547 - { 548 - sysfs_remove_group(&dev->kobj, &pm_attr_group); 549 - } 550 - 551 - #endif
+29
drivers/base/power/wakeup.c
··· 242 242 EXPORT_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 + */ 256 + void 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 + } 271 + EXPORT_SYMBOL_GPL(device_set_wakeup_capable); 272 + 273 + /** 245 274 * device_init_wakeup - Device wakeup initialization. 246 275 * @dev: Device to handle. 247 276 * @enable: Whether or not to enable @dev as a wakeup device.
+6
include/linux/pm_runtime.h
··· 87 87 return !dev->power.disable_depth; 88 88 } 89 89 90 + static inline bool pm_runtime_callbacks_present(struct device *dev) 91 + { 92 + return !dev->power.no_callbacks; 93 + } 94 + 90 95 static inline void pm_runtime_mark_last_busy(struct device *dev) 91 96 { 92 97 ACCESS_ONCE(dev->power.last_busy) = jiffies; ··· 138 133 static inline void pm_runtime_no_callbacks(struct device *dev) {} 139 134 static inline void pm_runtime_irq_safe(struct device *dev) {} 140 135 136 + static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; } 141 137 static inline void pm_runtime_mark_last_busy(struct device *dev) {} 142 138 static inline void __pm_runtime_use_autosuspend(struct device *dev, 143 139 bool use) {}
+1 -7
include/linux/pm_wakeup.h
··· 62 62 * Changes to device_may_wakeup take effect on the next pm state change. 63 63 */ 64 64 65 - static inline void device_set_wakeup_capable(struct device *dev, bool capable) 66 - { 67 - dev->power.can_wakeup = capable; 68 - } 69 - 70 65 static inline bool device_can_wakeup(struct device *dev) 71 66 { 72 67 return dev->power.can_wakeup; 73 68 } 74 - 75 - 76 69 77 70 static inline bool device_may_wakeup(struct device *dev) 78 71 { ··· 81 88 extern void wakeup_source_unregister(struct wakeup_source *ws); 82 89 extern int device_wakeup_enable(struct device *dev); 83 90 extern int device_wakeup_disable(struct device *dev); 91 + extern void device_set_wakeup_capable(struct device *dev, bool capable); 84 92 extern int device_init_wakeup(struct device *dev, bool val); 85 93 extern int device_set_wakeup_enable(struct device *dev, bool enable); 86 94 extern void __pm_stay_awake(struct wakeup_source *ws);