diff options
Diffstat (limited to 'drivers/base/power/generic_ops.c')
-rw-r--r-- | drivers/base/power/generic_ops.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index 4b29d4981253..cb3bb368681c 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c | |||
@@ -39,14 +39,14 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_idle); | |||
39 | * | 39 | * |
40 | * If PM operations are defined for the @dev's driver and they include | 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, | 41 | * ->runtime_suspend(), execute it and return its error code. Otherwise, |
42 | * return -EINVAL. | 42 | * return 0. |
43 | */ | 43 | */ |
44 | int pm_generic_runtime_suspend(struct device *dev) | 44 | int pm_generic_runtime_suspend(struct device *dev) |
45 | { | 45 | { |
46 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 46 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
47 | int ret; | 47 | int ret; |
48 | 48 | ||
49 | ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL; | 49 | ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0; |
50 | 50 | ||
51 | return ret; | 51 | return ret; |
52 | } | 52 | } |
@@ -58,14 +58,14 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend); | |||
58 | * | 58 | * |
59 | * If PM operations are defined for the @dev's driver and they include | 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, | 60 | * ->runtime_resume(), execute it and return its error code. Otherwise, |
61 | * return -EINVAL. | 61 | * return 0. |
62 | */ | 62 | */ |
63 | int pm_generic_runtime_resume(struct device *dev) | 63 | int pm_generic_runtime_resume(struct device *dev) |
64 | { | 64 | { |
65 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 65 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
66 | int ret; | 66 | int ret; |
67 | 67 | ||
68 | ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL; | 68 | ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0; |
69 | 69 | ||
70 | return ret; | 70 | return ret; |
71 | } | 71 | } |
@@ -74,6 +74,23 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_resume); | |||
74 | 74 | ||
75 | #ifdef CONFIG_PM_SLEEP | 75 | #ifdef CONFIG_PM_SLEEP |
76 | /** | 76 | /** |
77 | * pm_generic_prepare - Generic routine preparing a device for power transition. | ||
78 | * @dev: Device to prepare. | ||
79 | * | ||
80 | * Prepare a device for a system-wide power transition. | ||
81 | */ | ||
82 | int pm_generic_prepare(struct device *dev) | ||
83 | { | ||
84 | struct device_driver *drv = dev->driver; | ||
85 | int ret = 0; | ||
86 | |||
87 | if (drv && drv->pm && drv->pm->prepare) | ||
88 | ret = drv->pm->prepare(dev); | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | /** | ||
77 | * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback. | 94 | * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback. |
78 | * @dev: Device to handle. | 95 | * @dev: Device to handle. |
79 | * @event: PM transition of the system under way. | 96 | * @event: PM transition of the system under way. |
@@ -185,7 +202,7 @@ static int __pm_generic_resume(struct device *dev, int event) | |||
185 | return 0; | 202 | return 0; |
186 | 203 | ||
187 | ret = callback(dev); | 204 | ret = callback(dev); |
188 | if (!ret) { | 205 | if (!ret && pm_runtime_enabled(dev)) { |
189 | pm_runtime_disable(dev); | 206 | pm_runtime_disable(dev); |
190 | pm_runtime_set_active(dev); | 207 | pm_runtime_set_active(dev); |
191 | pm_runtime_enable(dev); | 208 | pm_runtime_enable(dev); |
@@ -213,16 +230,38 @@ int pm_generic_restore(struct device *dev) | |||
213 | return __pm_generic_resume(dev, PM_EVENT_RESTORE); | 230 | return __pm_generic_resume(dev, PM_EVENT_RESTORE); |
214 | } | 231 | } |
215 | EXPORT_SYMBOL_GPL(pm_generic_restore); | 232 | EXPORT_SYMBOL_GPL(pm_generic_restore); |
233 | |||
234 | /** | ||
235 | * pm_generic_complete - Generic routine competing a device power transition. | ||
236 | * @dev: Device to handle. | ||
237 | * | ||
238 | * Complete a device power transition during a system-wide power transition. | ||
239 | */ | ||
240 | void pm_generic_complete(struct device *dev) | ||
241 | { | ||
242 | struct device_driver *drv = dev->driver; | ||
243 | |||
244 | if (drv && drv->pm && drv->pm->complete) | ||
245 | drv->pm->complete(dev); | ||
246 | |||
247 | /* | ||
248 | * Let runtime PM try to suspend devices that haven't been in use before | ||
249 | * going into the system-wide sleep state we're resuming from. | ||
250 | */ | ||
251 | pm_runtime_idle(dev); | ||
252 | } | ||
216 | #endif /* CONFIG_PM_SLEEP */ | 253 | #endif /* CONFIG_PM_SLEEP */ |
217 | 254 | ||
218 | struct dev_pm_ops generic_subsys_pm_ops = { | 255 | struct dev_pm_ops generic_subsys_pm_ops = { |
219 | #ifdef CONFIG_PM_SLEEP | 256 | #ifdef CONFIG_PM_SLEEP |
257 | .prepare = pm_generic_prepare, | ||
220 | .suspend = pm_generic_suspend, | 258 | .suspend = pm_generic_suspend, |
221 | .resume = pm_generic_resume, | 259 | .resume = pm_generic_resume, |
222 | .freeze = pm_generic_freeze, | 260 | .freeze = pm_generic_freeze, |
223 | .thaw = pm_generic_thaw, | 261 | .thaw = pm_generic_thaw, |
224 | .poweroff = pm_generic_poweroff, | 262 | .poweroff = pm_generic_poweroff, |
225 | .restore = pm_generic_restore, | 263 | .restore = pm_generic_restore, |
264 | .complete = pm_generic_complete, | ||
226 | #endif | 265 | #endif |
227 | #ifdef CONFIG_PM_RUNTIME | 266 | #ifdef CONFIG_PM_RUNTIME |
228 | .runtime_suspend = pm_generic_runtime_suspend, | 267 | .runtime_suspend = pm_generic_runtime_suspend, |