diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-12-22 14:43:17 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2009-12-22 14:43:17 -0500 |
commit | a6ab7aa9f432f722808c6fea5a8b7f5f229de031 (patch) | |
tree | 94cc8cddba15a02c4dd3989fbcebb0be1542d586 | |
parent | aa0baaef97c89de2ef216fcc017215ee01662a10 (diff) |
PM / Runtime: Use device type and device class callbacks
The power management of some devices is handled through device types
and device classes rather than through bus types. Since these
devices may also benefit from using the run-time power management
core, extend it so that the device type and device class run-time PM
callbacks can be taken into consideration by it if the bus type
callback is not defined.
Update the run-time PM core documentation to reflect this change.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r-- | Documentation/power/runtime_pm.txt | 173 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 45 |
2 files changed, 132 insertions, 86 deletions
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 4a3109b28847..7b5ab2701247 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -42,80 +42,81 @@ struct dev_pm_ops { | |||
42 | ... | 42 | ... |
43 | }; | 43 | }; |
44 | 44 | ||
45 | The ->runtime_suspend() callback is executed by the PM core for the bus type of | 45 | The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are |
46 | the device being suspended. The bus type's callback is then _entirely_ | 46 | executed by the PM core for either the bus type, or device type (if the bus |
47 | _responsible_ for handling the device as appropriate, which may, but need not | 47 | type's callback is not defined), or device class (if the bus type's and device |
48 | include executing the device driver's own ->runtime_suspend() callback (from the | 48 | type's callbacks are not defined) of given device. The bus type, device type |
49 | and device class callbacks are referred to as subsystem-level callbacks in what | ||
50 | follows. | ||
51 | |||
52 | The subsystem-level suspend callback is _entirely_ _responsible_ for handling | ||
53 | the suspend of the device as appropriate, which may, but need not include | ||
54 | executing the device driver's own ->runtime_suspend() callback (from the | ||
49 | PM core's point of view it is not necessary to implement a ->runtime_suspend() | 55 | PM core's point of view it is not necessary to implement a ->runtime_suspend() |
50 | callback in a device driver as long as the bus type's ->runtime_suspend() knows | 56 | callback in a device driver as long as the subsystem-level suspend callback |
51 | what to do to handle the device). | 57 | knows what to do to handle the device). |
52 | 58 | ||
53 | * Once the bus type's ->runtime_suspend() callback has completed successfully | 59 | * Once the subsystem-level suspend callback has completed successfully |
54 | for given device, the PM core regards the device as suspended, which need | 60 | for given device, the PM core regards the device as suspended, which need |
55 | not mean that the device has been put into a low power state. It is | 61 | not mean that the device has been put into a low power state. It is |
56 | supposed to mean, however, that the device will not process data and will | 62 | supposed to mean, however, that the device will not process data and will |
57 | not communicate with the CPU(s) and RAM until its bus type's | 63 | not communicate with the CPU(s) and RAM until the subsystem-level resume |
58 | ->runtime_resume() callback is executed for it. The run-time PM status of | 64 | callback is executed for it. The run-time PM status of a device after |
59 | a device after successful execution of its bus type's ->runtime_suspend() | 65 | successful execution of the subsystem-level suspend callback is 'suspended'. |
60 | callback is 'suspended'. | 66 | |
61 | 67 | * If the subsystem-level suspend callback returns -EBUSY or -EAGAIN, | |
62 | * If the bus type's ->runtime_suspend() callback returns -EBUSY or -EAGAIN, | 68 | the device's run-time PM status is 'active', which means that the device |
63 | the device's run-time PM status is supposed to be 'active', which means that | 69 | _must_ be fully operational afterwards. |
64 | the device _must_ be fully operational afterwards. | 70 | |
65 | 71 | * If the subsystem-level suspend callback returns an error code different | |
66 | * If the bus type's ->runtime_suspend() callback returns an error code | 72 | from -EBUSY or -EAGAIN, the PM core regards this as a fatal error and will |
67 | different from -EBUSY or -EAGAIN, the PM core regards this as a fatal | 73 | refuse to run the helper functions described in Section 4 for the device, |
68 | error and will refuse to run the helper functions described in Section 4 | 74 | until the status of it is directly set either to 'active', or to 'suspended' |
69 | for the device, until the status of it is directly set either to 'active' | 75 | (the PM core provides special helper functions for this purpose). |
70 | or to 'suspended' (the PM core provides special helper functions for this | 76 | |
71 | purpose). | 77 | In particular, if the driver requires remote wake-up capability (i.e. hardware |
72 | 78 | mechanism allowing the device to request a change of its power state, such as | |
73 | In particular, if the driver requires remote wakeup capability for proper | 79 | PCI PME) for proper functioning and device_run_wake() returns 'false' for the |
74 | functioning and device_run_wake() returns 'false' for the device, then | 80 | device, then ->runtime_suspend() should return -EBUSY. On the other hand, if |
75 | ->runtime_suspend() should return -EBUSY. On the other hand, if | 81 | device_run_wake() returns 'true' for the device and the device is put into a low |
76 | device_run_wake() returns 'true' for the device and the device is put | 82 | power state during the execution of the subsystem-level suspend callback, it is |
77 | into a low power state during the execution of its bus type's | 83 | expected that remote wake-up will be enabled for the device. Generally, remote |
78 | ->runtime_suspend(), it is expected that remote wake-up (i.e. hardware mechanism | 84 | wake-up should be enabled for all input devices put into a low power state at |
79 | allowing the device to request a change of its power state, such as PCI PME) | 85 | run time. |
80 | will be enabled for the device. Generally, remote wake-up should be enabled | 86 | |
81 | for all input devices put into a low power state at run time. | 87 | The subsystem-level resume callback is _entirely_ _responsible_ for handling the |
82 | 88 | resume of the device as appropriate, which may, but need not include executing | |
83 | The ->runtime_resume() callback is executed by the PM core for the bus type of | 89 | the device driver's own ->runtime_resume() callback (from the PM core's point of |
84 | the device being woken up. The bus type's callback is then _entirely_ | 90 | view it is not necessary to implement a ->runtime_resume() callback in a device |
85 | _responsible_ for handling the device as appropriate, which may, but need not | 91 | driver as long as the subsystem-level resume callback knows what to do to handle |
86 | include executing the device driver's own ->runtime_resume() callback (from the | 92 | the device). |
87 | PM core's point of view it is not necessary to implement a ->runtime_resume() | 93 | |
88 | callback in a device driver as long as the bus type's ->runtime_resume() knows | 94 | * Once the subsystem-level resume callback has completed successfully, the PM |
89 | what to do to handle the device). | 95 | core regards the device as fully operational, which means that the device |
90 | 96 | _must_ be able to complete I/O operations as needed. The run-time PM status | |
91 | * Once the bus type's ->runtime_resume() callback has completed successfully, | 97 | of the device is then 'active'. |
92 | the PM core regards the device as fully operational, which means that the | 98 | |
93 | device _must_ be able to complete I/O operations as needed. The run-time | 99 | * If the subsystem-level resume callback returns an error code, the PM core |
94 | PM status of the device is then 'active'. | 100 | regards this as a fatal error and will refuse to run the helper functions |
95 | 101 | described in Section 4 for the device, until its status is directly set | |
96 | * If the bus type's ->runtime_resume() callback returns an error code, the PM | 102 | either to 'active' or to 'suspended' (the PM core provides special helper |
97 | core regards this as a fatal error and will refuse to run the helper | 103 | functions for this purpose). |
98 | functions described in Section 4 for the device, until its status is | 104 | |
99 | directly set either to 'active' or to 'suspended' (the PM core provides | 105 | The subsystem-level idle callback is executed by the PM core whenever the device |
100 | special helper functions for this purpose). | 106 | appears to be idle, which is indicated to the PM core by two counters, the |
101 | 107 | device's usage counter and the counter of 'active' children of the device. | |
102 | The ->runtime_idle() callback is executed by the PM core for the bus type of | ||
103 | given device whenever the device appears to be idle, which is indicated to the | ||
104 | PM core by two counters, the device's usage counter and the counter of 'active' | ||
105 | children of the device. | ||
106 | 108 | ||
107 | * If any of these counters is decreased using a helper function provided by | 109 | * If any of these counters is decreased using a helper function provided by |
108 | the PM core and it turns out to be equal to zero, the other counter is | 110 | the PM core and it turns out to be equal to zero, the other counter is |
109 | checked. If that counter also is equal to zero, the PM core executes the | 111 | checked. If that counter also is equal to zero, the PM core executes the |
110 | device bus type's ->runtime_idle() callback (with the device as an | 112 | subsystem-level idle callback with the device as an argument. |
111 | argument). | ||
112 | 113 | ||
113 | The action performed by a bus type's ->runtime_idle() callback is totally | 114 | The action performed by a subsystem-level idle callback is totally dependent on |
114 | dependent on the bus type in question, but the expected and recommended action | 115 | the subsystem in question, but the expected and recommended action is to check |
115 | is to check if the device can be suspended (i.e. if all of the conditions | 116 | if the device can be suspended (i.e. if all of the conditions necessary for |
116 | necessary for suspending the device are satisfied) and to queue up a suspend | 117 | suspending the device are satisfied) and to queue up a suspend request for the |
117 | request for the device in that case. The value returned by this callback is | 118 | device in that case. The value returned by this callback is ignored by the PM |
118 | ignored by the PM core. | 119 | core. |
119 | 120 | ||
120 | The helper functions provided by the PM core, described in Section 4, guarantee | 121 | The helper functions provided by the PM core, described in Section 4, guarantee |
121 | that the following constraints are met with respect to the bus type's run-time | 122 | that the following constraints are met with respect to the bus type's run-time |
@@ -238,41 +239,41 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: | |||
238 | removing the device from device hierarchy | 239 | removing the device from device hierarchy |
239 | 240 | ||
240 | int pm_runtime_idle(struct device *dev); | 241 | int pm_runtime_idle(struct device *dev); |
241 | - execute ->runtime_idle() for the device's bus type; returns 0 on success | 242 | - execute the subsystem-level idle callback for the device; returns 0 on |
242 | or error code on failure, where -EINPROGRESS means that ->runtime_idle() | 243 | success or error code on failure, where -EINPROGRESS means that |
243 | is already being executed | 244 | ->runtime_idle() is already being executed |
244 | 245 | ||
245 | int pm_runtime_suspend(struct device *dev); | 246 | int pm_runtime_suspend(struct device *dev); |
246 | - execute ->runtime_suspend() for the device's bus type; returns 0 on | 247 | - execute the subsystem-level suspend callback for the device; returns 0 on |
247 | success, 1 if the device's run-time PM status was already 'suspended', or | 248 | success, 1 if the device's run-time PM status was already 'suspended', or |
248 | error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt | 249 | error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt |
249 | to suspend the device again in future | 250 | to suspend the device again in future |
250 | 251 | ||
251 | int pm_runtime_resume(struct device *dev); | 252 | int pm_runtime_resume(struct device *dev); |
252 | - execute ->runtime_resume() for the device's bus type; returns 0 on | 253 | - execute the subsystem-leve resume callback for the device; returns 0 on |
253 | success, 1 if the device's run-time PM status was already 'active' or | 254 | success, 1 if the device's run-time PM status was already 'active' or |
254 | error code on failure, where -EAGAIN means it may be safe to attempt to | 255 | error code on failure, where -EAGAIN means it may be safe to attempt to |
255 | resume the device again in future, but 'power.runtime_error' should be | 256 | resume the device again in future, but 'power.runtime_error' should be |
256 | checked additionally | 257 | checked additionally |
257 | 258 | ||
258 | int pm_request_idle(struct device *dev); | 259 | int pm_request_idle(struct device *dev); |
259 | - submit a request to execute ->runtime_idle() for the device's bus type | 260 | - submit a request to execute the subsystem-level idle callback for the |
260 | (the request is represented by a work item in pm_wq); returns 0 on success | 261 | device (the request is represented by a work item in pm_wq); returns 0 on |
261 | or error code if the request has not been queued up | 262 | success or error code if the request has not been queued up |
262 | 263 | ||
263 | int pm_schedule_suspend(struct device *dev, unsigned int delay); | 264 | int pm_schedule_suspend(struct device *dev, unsigned int delay); |
264 | - schedule the execution of ->runtime_suspend() for the device's bus type | 265 | - schedule the execution of the subsystem-level suspend callback for the |
265 | in future, where 'delay' is the time to wait before queuing up a suspend | 266 | device in future, where 'delay' is the time to wait before queuing up a |
266 | work item in pm_wq, in milliseconds (if 'delay' is zero, the work item is | 267 | suspend work item in pm_wq, in milliseconds (if 'delay' is zero, the work |
267 | queued up immediately); returns 0 on success, 1 if the device's PM | 268 | item is queued up immediately); returns 0 on success, 1 if the device's PM |
268 | run-time status was already 'suspended', or error code if the request | 269 | run-time status was already 'suspended', or error code if the request |
269 | hasn't been scheduled (or queued up if 'delay' is 0); if the execution of | 270 | hasn't been scheduled (or queued up if 'delay' is 0); if the execution of |
270 | ->runtime_suspend() is already scheduled and not yet expired, the new | 271 | ->runtime_suspend() is already scheduled and not yet expired, the new |
271 | value of 'delay' will be used as the time to wait | 272 | value of 'delay' will be used as the time to wait |
272 | 273 | ||
273 | int pm_request_resume(struct device *dev); | 274 | int pm_request_resume(struct device *dev); |
274 | - submit a request to execute ->runtime_resume() for the device's bus type | 275 | - submit a request to execute the subsystem-level resume callback for the |
275 | (the request is represented by a work item in pm_wq); returns 0 on | 276 | device (the request is represented by a work item in pm_wq); returns 0 on |
276 | success, 1 if the device's run-time PM status was already 'active', or | 277 | success, 1 if the device's run-time PM status was already 'active', or |
277 | error code if the request hasn't been queued up | 278 | error code if the request hasn't been queued up |
278 | 279 | ||
@@ -303,12 +304,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: | |||
303 | run-time PM callbacks described in Section 2 | 304 | run-time PM callbacks described in Section 2 |
304 | 305 | ||
305 | int pm_runtime_disable(struct device *dev); | 306 | int pm_runtime_disable(struct device *dev); |
306 | - prevent the run-time PM helper functions from running the device bus | 307 | - prevent the run-time PM helper functions from running subsystem-level |
307 | type's run-time PM callbacks, make sure that all of the pending run-time | 308 | run-time PM callbacks for the device, make sure that all of the pending |
308 | PM operations on the device are either completed or canceled; returns | 309 | run-time PM operations on the device are either completed or canceled; |
309 | 1 if there was a resume request pending and it was necessary to execute | 310 | returns 1 if there was a resume request pending and it was necessary to |
310 | ->runtime_resume() for the device's bus type to satisfy that request, | 311 | execute the subsystem-level resume callback for the device to satisfy that |
311 | otherwise 0 is returned | 312 | request, otherwise 0 is returned |
312 | 313 | ||
313 | void pm_suspend_ignore_children(struct device *dev, bool enable); | 314 | void pm_suspend_ignore_children(struct device *dev, bool enable); |
314 | - set/unset the power.ignore_children flag of the device | 315 | - set/unset the power.ignore_children flag of the device |
@@ -378,5 +379,5 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, | |||
378 | they will fail returning -EAGAIN, because the device's usage counter is | 379 | they will fail returning -EAGAIN, because the device's usage counter is |
379 | incremented by the core before executing ->probe() and ->remove(). Still, it | 380 | incremented by the core before executing ->probe() and ->remove(). Still, it |
380 | may be desirable to suspend the device as soon as ->probe() or ->remove() has | 381 | may be desirable to suspend the device as soon as ->probe() or ->remove() has |
381 | finished, so the PM core uses pm_runtime_idle_sync() to invoke the device bus | 382 | finished, so the PM core uses pm_runtime_idle_sync() to invoke the |
382 | type's ->runtime_idle() callback at that time. | 383 | subsystem-level idle callback for the device at that time. |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 40d7720a4b21..f8b044e8aef7 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -85,6 +85,19 @@ static int __pm_runtime_idle(struct device *dev) | |||
85 | dev->bus->pm->runtime_idle(dev); | 85 | dev->bus->pm->runtime_idle(dev); |
86 | 86 | ||
87 | spin_lock_irq(&dev->power.lock); | 87 | spin_lock_irq(&dev->power.lock); |
88 | } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) { | ||
89 | spin_unlock_irq(&dev->power.lock); | ||
90 | |||
91 | dev->type->pm->runtime_idle(dev); | ||
92 | |||
93 | spin_lock_irq(&dev->power.lock); | ||
94 | } else if (dev->class && dev->class->pm | ||
95 | && dev->class->pm->runtime_idle) { | ||
96 | spin_unlock_irq(&dev->power.lock); | ||
97 | |||
98 | dev->class->pm->runtime_idle(dev); | ||
99 | |||
100 | spin_lock_irq(&dev->power.lock); | ||
88 | } | 101 | } |
89 | 102 | ||
90 | dev->power.idle_notification = false; | 103 | dev->power.idle_notification = false; |
@@ -194,6 +207,22 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
194 | 207 | ||
195 | spin_lock_irq(&dev->power.lock); | 208 | spin_lock_irq(&dev->power.lock); |
196 | dev->power.runtime_error = retval; | 209 | dev->power.runtime_error = retval; |
210 | } else if (dev->type && dev->type->pm | ||
211 | && dev->type->pm->runtime_suspend) { | ||
212 | spin_unlock_irq(&dev->power.lock); | ||
213 | |||
214 | retval = dev->type->pm->runtime_suspend(dev); | ||
215 | |||
216 | spin_lock_irq(&dev->power.lock); | ||
217 | dev->power.runtime_error = retval; | ||
218 | } else if (dev->class && dev->class->pm | ||
219 | && dev->class->pm->runtime_suspend) { | ||
220 | spin_unlock_irq(&dev->power.lock); | ||
221 | |||
222 | retval = dev->class->pm->runtime_suspend(dev); | ||
223 | |||
224 | spin_lock_irq(&dev->power.lock); | ||
225 | dev->power.runtime_error = retval; | ||
197 | } else { | 226 | } else { |
198 | retval = -ENOSYS; | 227 | retval = -ENOSYS; |
199 | } | 228 | } |
@@ -359,6 +388,22 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
359 | 388 | ||
360 | spin_lock_irq(&dev->power.lock); | 389 | spin_lock_irq(&dev->power.lock); |
361 | dev->power.runtime_error = retval; | 390 | dev->power.runtime_error = retval; |
391 | } else if (dev->type && dev->type->pm | ||
392 | && dev->type->pm->runtime_resume) { | ||
393 | spin_unlock_irq(&dev->power.lock); | ||
394 | |||
395 | retval = dev->type->pm->runtime_resume(dev); | ||
396 | |||
397 | spin_lock_irq(&dev->power.lock); | ||
398 | dev->power.runtime_error = retval; | ||
399 | } else if (dev->class && dev->class->pm | ||
400 | && dev->class->pm->runtime_resume) { | ||
401 | spin_unlock_irq(&dev->power.lock); | ||
402 | |||
403 | retval = dev->class->pm->runtime_resume(dev); | ||
404 | |||
405 | spin_lock_irq(&dev->power.lock); | ||
406 | dev->power.runtime_error = retval; | ||
362 | } else { | 407 | } else { |
363 | retval = -ENOSYS; | 408 | retval = -ENOSYS; |
364 | } | 409 | } |