Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
PM: Provide generic subsystem-level callbacks
PM / Runtime: Document power.runtime_auto and related functions

+378 -6
+93
Documentation/power/runtime_pm.txt
··· 224 224 RPM_SUSPENDED, which means that each device is initially regarded by the 225 225 PM core as 'suspended', regardless of its real hardware status 226 226 227 + unsigned int runtime_auto; 228 + - if set, indicates that the user space has allowed the device driver to 229 + power manage the device at run time via the /sys/devices/.../power/control 230 + interface; it may only be modified with the help of the pm_runtime_allow() 231 + and pm_runtime_forbid() helper functions 232 + 227 233 All of the above fields are members of the 'power' member of 'struct device'. 228 234 229 235 4. Run-time PM Device Helper Functions ··· 335 329 'power.runtime_error' is set or 'power.disable_depth' is greater than 336 330 zero) 337 331 332 + bool pm_runtime_suspended(struct device *dev); 333 + - return true if the device's runtime PM status is 'suspended', or false 334 + otherwise 335 + 336 + void pm_runtime_allow(struct device *dev); 337 + - set the power.runtime_auto flag for the device and decrease its usage 338 + counter (used by the /sys/devices/.../power/control interface to 339 + effectively allow the device to be power managed at run time) 340 + 341 + void pm_runtime_forbid(struct device *dev); 342 + - unset the power.runtime_auto flag for the device and increase its usage 343 + counter (used by the /sys/devices/.../power/control interface to 344 + effectively prevent the device from being power managed at run time) 345 + 338 346 It is safe to execute the following helper functions from interrupt context: 339 347 340 348 pm_request_idle() ··· 402 382 finished, so the PM core uses pm_runtime_idle_sync() to invoke the 403 383 subsystem-level idle callback for the device at that time. 404 384 385 + The user space can effectively disallow the driver of the device to power manage 386 + it at run time by changing the value of its /sys/devices/.../power/control 387 + attribute to "on", which causes pm_runtime_forbid() to be called. In principle, 388 + this mechanism may also be used by the driver to effectively turn off the 389 + run-time power management of the device until the user space turns it on. 390 + Namely, during the initialization the driver can make sure that the run-time PM 391 + status of the device is 'active' and call pm_runtime_forbid(). It should be 392 + noted, however, that if the user space has already intentionally changed the 393 + value of /sys/devices/.../power/control to "auto" to allow the driver to power 394 + manage the device at run time, the driver may confuse it by using 395 + pm_runtime_forbid() this way. 396 + 405 397 6. Run-time PM and System Sleep 406 398 407 399 Run-time PM and system sleep (i.e., system suspend and hibernation, also known ··· 463 431 ->prepare() callback and decrements it after calling the ->complete() callback. 464 432 Hence disabling run-time PM temporarily like this will not cause any run-time 465 433 suspend callbacks to be lost. 434 + 435 + 7. Generic subsystem callbacks 436 + 437 + Subsystems may wish to conserve code space by using the set of generic power 438 + management callbacks provided by the PM core, defined in 439 + driver/base/power/generic_ops.c: 440 + 441 + int pm_generic_runtime_idle(struct device *dev); 442 + - invoke the ->runtime_idle() callback provided by the driver of this 443 + device, if defined, and call pm_runtime_suspend() for this device if the 444 + return value is 0 or the callback is not defined 445 + 446 + int pm_generic_runtime_suspend(struct device *dev); 447 + - invoke the ->runtime_suspend() callback provided by the driver of this 448 + device and return its result, or return -EINVAL if not defined 449 + 450 + int pm_generic_runtime_resume(struct device *dev); 451 + - invoke the ->runtime_resume() callback provided by the driver of this 452 + device and return its result, or return -EINVAL if not defined 453 + 454 + int pm_generic_suspend(struct device *dev); 455 + - if the device has not been suspended at run time, invoke the ->suspend() 456 + callback provided by its driver and return its result, or return 0 if not 457 + defined 458 + 459 + int pm_generic_resume(struct device *dev); 460 + - invoke the ->resume() callback provided by the driver of this device and, 461 + if successful, change the device's runtime PM status to 'active' 462 + 463 + int pm_generic_freeze(struct device *dev); 464 + - if the device has not been suspended at run time, invoke the ->freeze() 465 + callback provided by its driver and return its result, or return 0 if not 466 + defined 467 + 468 + int pm_generic_thaw(struct device *dev); 469 + - if the device has not been suspended at run time, invoke the ->thaw() 470 + callback provided by its driver and return its result, or return 0 if not 471 + defined 472 + 473 + int pm_generic_poweroff(struct device *dev); 474 + - if the device has not been suspended at run time, invoke the ->poweroff() 475 + callback provided by its driver and return its result, or return 0 if not 476 + defined 477 + 478 + int pm_generic_restore(struct device *dev); 479 + - invoke the ->restore() callback provided by the driver of this device and, 480 + if successful, change the device's runtime PM status to 'active' 481 + 482 + These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(), 483 + ->runtime_resume(), ->suspend(), ->resume(), ->freeze(), ->thaw(), ->poweroff(), 484 + or ->restore() callback pointers in the subsystem-level dev_pm_ops structures. 485 + 486 + If a subsystem wishes to use all of them at the same time, it can simply assign 487 + the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its 488 + dev_pm_ops structure pointer. 489 + 490 + Device drivers that wish to use the same function as a system suspend, freeze, 491 + poweroff and run-time suspend callback, and similarly for system resume, thaw, 492 + restore, and run-time resume, can achieve this with the help of the 493 + UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its 494 + last argument to NULL).
+1
drivers/base/power/Makefile
··· 1 1 obj-$(CONFIG_PM) += sysfs.o 2 2 obj-$(CONFIG_PM_SLEEP) += main.o 3 3 obj-$(CONFIG_PM_RUNTIME) += runtime.o 4 + obj-$(CONFIG_PM_OPS) += generic_ops.o 4 5 obj-$(CONFIG_PM_TRACE_RTC) += trace.o 5 6 6 7 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
+233
drivers/base/power/generic_ops.c
··· 1 + /* 2 + * drivers/base/power/generic_ops.c - Generic PM callbacks for subsystems 3 + * 4 + * Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. 5 + * 6 + * This file is released under the GPLv2. 7 + */ 8 + 9 + #include <linux/pm.h> 10 + #include <linux/pm_runtime.h> 11 + 12 + #ifdef CONFIG_PM_RUNTIME 13 + /** 14 + * pm_generic_runtime_idle - Generic runtime idle callback for subsystems. 15 + * @dev: Device to handle. 16 + * 17 + * If PM operations are defined for the @dev's driver and they include 18 + * ->runtime_idle(), execute it and return its error code, if nonzero. 19 + * Otherwise, execute pm_runtime_suspend() for the device and return 0. 20 + */ 21 + int pm_generic_runtime_idle(struct device *dev) 22 + { 23 + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 24 + 25 + if (pm && pm->runtime_idle) { 26 + int ret = pm->runtime_idle(dev); 27 + if (ret) 28 + return ret; 29 + } 30 + 31 + pm_runtime_suspend(dev); 32 + return 0; 33 + } 34 + EXPORT_SYMBOL_GPL(pm_generic_runtime_idle); 35 + 36 + /** 37 + * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems. 38 + * @dev: Device to suspend. 39 + * 40 + * If PM operations are defined for the @dev's driver and they include 41 + * ->runtime_suspend(), execute it and return its error code. Otherwise, 42 + * return -EINVAL. 43 + */ 44 + int pm_generic_runtime_suspend(struct device *dev) 45 + { 46 + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 47 + int ret; 48 + 49 + ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL; 50 + 51 + return ret; 52 + } 53 + EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend); 54 + 55 + /** 56 + * pm_generic_runtime_resume - Generic runtime resume callback for subsystems. 57 + * @dev: Device to resume. 58 + * 59 + * If PM operations are defined for the @dev's driver and they include 60 + * ->runtime_resume(), execute it and return its error code. Otherwise, 61 + * return -EINVAL. 62 + */ 63 + int pm_generic_runtime_resume(struct device *dev) 64 + { 65 + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 66 + int ret; 67 + 68 + ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL; 69 + 70 + return ret; 71 + } 72 + EXPORT_SYMBOL_GPL(pm_generic_runtime_resume); 73 + #endif /* CONFIG_PM_RUNTIME */ 74 + 75 + #ifdef CONFIG_PM_SLEEP 76 + /** 77 + * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback. 78 + * @dev: Device to handle. 79 + * @event: PM transition of the system under way. 80 + * 81 + * If the device has not been suspended at run time, execute the 82 + * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and 83 + * return its error code. Otherwise, return zero. 84 + */ 85 + static int __pm_generic_call(struct device *dev, int event) 86 + { 87 + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 88 + int (*callback)(struct device *); 89 + 90 + if (!pm || pm_runtime_suspended(dev)) 91 + return 0; 92 + 93 + switch (event) { 94 + case PM_EVENT_SUSPEND: 95 + callback = pm->suspend; 96 + break; 97 + case PM_EVENT_FREEZE: 98 + callback = pm->freeze; 99 + break; 100 + case PM_EVENT_HIBERNATE: 101 + callback = pm->poweroff; 102 + break; 103 + case PM_EVENT_THAW: 104 + callback = pm->thaw; 105 + break; 106 + default: 107 + callback = NULL; 108 + break; 109 + } 110 + 111 + return callback ? callback(dev) : 0; 112 + } 113 + 114 + /** 115 + * pm_generic_suspend - Generic suspend callback for subsystems. 116 + * @dev: Device to suspend. 117 + */ 118 + int pm_generic_suspend(struct device *dev) 119 + { 120 + return __pm_generic_call(dev, PM_EVENT_SUSPEND); 121 + } 122 + EXPORT_SYMBOL_GPL(pm_generic_suspend); 123 + 124 + /** 125 + * pm_generic_freeze - Generic freeze callback for subsystems. 126 + * @dev: Device to freeze. 127 + */ 128 + int pm_generic_freeze(struct device *dev) 129 + { 130 + return __pm_generic_call(dev, PM_EVENT_FREEZE); 131 + } 132 + EXPORT_SYMBOL_GPL(pm_generic_freeze); 133 + 134 + /** 135 + * pm_generic_poweroff - Generic poweroff callback for subsystems. 136 + * @dev: Device to handle. 137 + */ 138 + int pm_generic_poweroff(struct device *dev) 139 + { 140 + return __pm_generic_call(dev, PM_EVENT_HIBERNATE); 141 + } 142 + EXPORT_SYMBOL_GPL(pm_generic_poweroff); 143 + 144 + /** 145 + * pm_generic_thaw - Generic thaw callback for subsystems. 146 + * @dev: Device to thaw. 147 + */ 148 + int pm_generic_thaw(struct device *dev) 149 + { 150 + return __pm_generic_call(dev, PM_EVENT_THAW); 151 + } 152 + EXPORT_SYMBOL_GPL(pm_generic_thaw); 153 + 154 + /** 155 + * __pm_generic_resume - Generic resume/restore callback for subsystems. 156 + * @dev: Device to handle. 157 + * @event: PM transition of the system under way. 158 + * 159 + * Execute the resume/resotre callback provided by the @dev's driver, if 160 + * defined. If it returns 0, change the device's runtime PM status to 'active'. 161 + * Return the callback's error code. 162 + */ 163 + static int __pm_generic_resume(struct device *dev, int event) 164 + { 165 + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 166 + int (*callback)(struct device *); 167 + int ret; 168 + 169 + if (!pm) 170 + return 0; 171 + 172 + switch (event) { 173 + case PM_EVENT_RESUME: 174 + callback = pm->resume; 175 + break; 176 + case PM_EVENT_RESTORE: 177 + callback = pm->restore; 178 + break; 179 + default: 180 + callback = NULL; 181 + break; 182 + } 183 + 184 + if (!callback) 185 + return 0; 186 + 187 + ret = callback(dev); 188 + if (!ret) { 189 + pm_runtime_disable(dev); 190 + pm_runtime_set_active(dev); 191 + pm_runtime_enable(dev); 192 + } 193 + 194 + return ret; 195 + } 196 + 197 + /** 198 + * pm_generic_resume - Generic resume callback for subsystems. 199 + * @dev: Device to resume. 200 + */ 201 + int pm_generic_resume(struct device *dev) 202 + { 203 + return __pm_generic_resume(dev, PM_EVENT_RESUME); 204 + } 205 + EXPORT_SYMBOL_GPL(pm_generic_resume); 206 + 207 + /** 208 + * pm_generic_restore - Generic restore callback for subsystems. 209 + * @dev: Device to restore. 210 + */ 211 + int pm_generic_restore(struct device *dev) 212 + { 213 + return __pm_generic_resume(dev, PM_EVENT_RESTORE); 214 + } 215 + EXPORT_SYMBOL_GPL(pm_generic_restore); 216 + #endif /* CONFIG_PM_SLEEP */ 217 + 218 + struct dev_pm_ops generic_subsys_pm_ops = { 219 + #ifdef CONFIG_PM_SLEEP 220 + .suspend = pm_generic_suspend, 221 + .resume = pm_generic_resume, 222 + .freeze = pm_generic_freeze, 223 + .thaw = pm_generic_thaw, 224 + .poweroff = pm_generic_poweroff, 225 + .restore = pm_generic_restore, 226 + #endif 227 + #ifdef CONFIG_PM_RUNTIME 228 + .runtime_suspend = pm_generic_runtime_suspend, 229 + .runtime_resume = pm_generic_runtime_resume, 230 + .runtime_idle = pm_generic_runtime_idle, 231 + #endif 232 + }; 233 + EXPORT_SYMBOL_GPL(generic_subsys_pm_ops);
+45 -6
include/linux/pm.h
··· 215 215 int (*runtime_idle)(struct device *dev); 216 216 }; 217 217 218 + #ifdef CONFIG_PM_SLEEP 219 + #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ 220 + .suspend = suspend_fn, \ 221 + .resume = resume_fn, \ 222 + .freeze = suspend_fn, \ 223 + .thaw = resume_fn, \ 224 + .poweroff = suspend_fn, \ 225 + .restore = resume_fn, 226 + #else 227 + #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) 228 + #endif 229 + 230 + #ifdef CONFIG_PM_RUNTIME 231 + #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ 232 + .runtime_suspend = suspend_fn, \ 233 + .runtime_resume = resume_fn, \ 234 + .runtime_idle = idle_fn, 235 + #else 236 + #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) 237 + #endif 238 + 218 239 /* 219 240 * Use this if you want to use the same suspend and resume callbacks for suspend 220 241 * to RAM and hibernation. 221 242 */ 222 243 #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ 223 244 const struct dev_pm_ops name = { \ 224 - .suspend = suspend_fn, \ 225 - .resume = resume_fn, \ 226 - .freeze = suspend_fn, \ 227 - .thaw = resume_fn, \ 228 - .poweroff = suspend_fn, \ 229 - .restore = resume_fn, \ 245 + SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ 230 246 } 247 + 248 + /* 249 + * Use this for defining a set of PM operations to be used in all situations 250 + * (sustem suspend, hibernation or runtime PM). 251 + */ 252 + #define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \ 253 + const struct dev_pm_ops name = { \ 254 + SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ 255 + SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ 256 + } 257 + 258 + /* 259 + * Use this for subsystems (bus types, device types, device classes) that don't 260 + * need any special suspend/resume handling in addition to invoking the PM 261 + * callbacks provided by device drivers supporting both the system sleep PM and 262 + * runtime PM, make the pm member point to generic_subsys_pm_ops. 263 + */ 264 + #ifdef CONFIG_PM_OPS 265 + extern struct dev_pm_ops generic_subsys_pm_ops; 266 + #define GENERIC_SUBSYS_PM_OPS (&generic_subsys_pm_ops) 267 + #else 268 + #define GENERIC_SUBSYS_PM_OPS NULL 269 + #endif 231 270 232 271 /** 233 272 * PM_EVENT_ messages
+6
include/linux/pm_runtime.h
··· 62 62 dev->power.run_wake = enable; 63 63 } 64 64 65 + static inline bool pm_runtime_suspended(struct device *dev) 66 + { 67 + return dev->power.runtime_status == RPM_SUSPENDED; 68 + } 69 + 65 70 #else /* !CONFIG_PM_RUNTIME */ 66 71 67 72 static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; } ··· 94 89 static inline void pm_runtime_put_noidle(struct device *dev) {} 95 90 static inline bool device_run_wake(struct device *dev) { return false; } 96 91 static inline void device_set_run_wake(struct device *dev, bool enable) {} 92 + static inline bool pm_runtime_suspended(struct device *dev) { return false; } 97 93 98 94 #endif /* !CONFIG_PM_RUNTIME */ 99 95