diff options
Diffstat (limited to 'drivers/base/power/generic_ops.c')
-rw-r--r-- | drivers/base/power/generic_ops.c | 91 |
1 files changed, 14 insertions, 77 deletions
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index 265a0ee3b49e..10bdd793f0bd 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c | |||
@@ -97,16 +97,16 @@ int pm_generic_prepare(struct device *dev) | |||
97 | * @event: PM transition of the system under way. | 97 | * @event: PM transition of the system under way. |
98 | * @bool: Whether or not this is the "noirq" stage. | 98 | * @bool: Whether or not this is the "noirq" stage. |
99 | * | 99 | * |
100 | * If the device has not been suspended at run time, execute the | 100 | * Execute the PM callback corresponding to @event provided by the driver of |
101 | * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and | 101 | * @dev, if defined, and return its error code. Return 0 if the callback is |
102 | * return its error code. Otherwise, return zero. | 102 | * not present. |
103 | */ | 103 | */ |
104 | static int __pm_generic_call(struct device *dev, int event, bool noirq) | 104 | static int __pm_generic_call(struct device *dev, int event, bool noirq) |
105 | { | 105 | { |
106 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 106 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
107 | int (*callback)(struct device *); | 107 | int (*callback)(struct device *); |
108 | 108 | ||
109 | if (!pm || pm_runtime_suspended(dev)) | 109 | if (!pm) |
110 | return 0; | 110 | return 0; |
111 | 111 | ||
112 | switch (event) { | 112 | switch (event) { |
@@ -119,9 +119,15 @@ static int __pm_generic_call(struct device *dev, int event, bool noirq) | |||
119 | case PM_EVENT_HIBERNATE: | 119 | case PM_EVENT_HIBERNATE: |
120 | callback = noirq ? pm->poweroff_noirq : pm->poweroff; | 120 | callback = noirq ? pm->poweroff_noirq : pm->poweroff; |
121 | break; | 121 | break; |
122 | case PM_EVENT_RESUME: | ||
123 | callback = noirq ? pm->resume_noirq : pm->resume; | ||
124 | break; | ||
122 | case PM_EVENT_THAW: | 125 | case PM_EVENT_THAW: |
123 | callback = noirq ? pm->thaw_noirq : pm->thaw; | 126 | callback = noirq ? pm->thaw_noirq : pm->thaw; |
124 | break; | 127 | break; |
128 | case PM_EVENT_RESTORE: | ||
129 | callback = noirq ? pm->restore_noirq : pm->restore; | ||
130 | break; | ||
125 | default: | 131 | default: |
126 | callback = NULL; | 132 | callback = NULL; |
127 | break; | 133 | break; |
@@ -211,56 +217,12 @@ int pm_generic_thaw(struct device *dev) | |||
211 | EXPORT_SYMBOL_GPL(pm_generic_thaw); | 217 | EXPORT_SYMBOL_GPL(pm_generic_thaw); |
212 | 218 | ||
213 | /** | 219 | /** |
214 | * __pm_generic_resume - Generic resume/restore callback for subsystems. | ||
215 | * @dev: Device to handle. | ||
216 | * @event: PM transition of the system under way. | ||
217 | * @bool: Whether or not this is the "noirq" stage. | ||
218 | * | ||
219 | * Execute the resume/resotre callback provided by the @dev's driver, if | ||
220 | * defined. If it returns 0, change the device's runtime PM status to 'active'. | ||
221 | * Return the callback's error code. | ||
222 | */ | ||
223 | static int __pm_generic_resume(struct device *dev, int event, bool noirq) | ||
224 | { | ||
225 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
226 | int (*callback)(struct device *); | ||
227 | int ret; | ||
228 | |||
229 | if (!pm) | ||
230 | return 0; | ||
231 | |||
232 | switch (event) { | ||
233 | case PM_EVENT_RESUME: | ||
234 | callback = noirq ? pm->resume_noirq : pm->resume; | ||
235 | break; | ||
236 | case PM_EVENT_RESTORE: | ||
237 | callback = noirq ? pm->restore_noirq : pm->restore; | ||
238 | break; | ||
239 | default: | ||
240 | callback = NULL; | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | if (!callback) | ||
245 | return 0; | ||
246 | |||
247 | ret = callback(dev); | ||
248 | if (!ret && !noirq && pm_runtime_enabled(dev)) { | ||
249 | pm_runtime_disable(dev); | ||
250 | pm_runtime_set_active(dev); | ||
251 | pm_runtime_enable(dev); | ||
252 | } | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * pm_generic_resume_noirq - Generic resume_noirq callback for subsystems. | 220 | * pm_generic_resume_noirq - Generic resume_noirq callback for subsystems. |
259 | * @dev: Device to resume. | 221 | * @dev: Device to resume. |
260 | */ | 222 | */ |
261 | int pm_generic_resume_noirq(struct device *dev) | 223 | int pm_generic_resume_noirq(struct device *dev) |
262 | { | 224 | { |
263 | return __pm_generic_resume(dev, PM_EVENT_RESUME, true); | 225 | return __pm_generic_call(dev, PM_EVENT_RESUME, true); |
264 | } | 226 | } |
265 | EXPORT_SYMBOL_GPL(pm_generic_resume_noirq); | 227 | EXPORT_SYMBOL_GPL(pm_generic_resume_noirq); |
266 | 228 | ||
@@ -270,7 +232,7 @@ EXPORT_SYMBOL_GPL(pm_generic_resume_noirq); | |||
270 | */ | 232 | */ |
271 | int pm_generic_resume(struct device *dev) | 233 | int pm_generic_resume(struct device *dev) |
272 | { | 234 | { |
273 | return __pm_generic_resume(dev, PM_EVENT_RESUME, false); | 235 | return __pm_generic_call(dev, PM_EVENT_RESUME, false); |
274 | } | 236 | } |
275 | EXPORT_SYMBOL_GPL(pm_generic_resume); | 237 | EXPORT_SYMBOL_GPL(pm_generic_resume); |
276 | 238 | ||
@@ -280,7 +242,7 @@ EXPORT_SYMBOL_GPL(pm_generic_resume); | |||
280 | */ | 242 | */ |
281 | int pm_generic_restore_noirq(struct device *dev) | 243 | int pm_generic_restore_noirq(struct device *dev) |
282 | { | 244 | { |
283 | return __pm_generic_resume(dev, PM_EVENT_RESTORE, true); | 245 | return __pm_generic_call(dev, PM_EVENT_RESTORE, true); |
284 | } | 246 | } |
285 | EXPORT_SYMBOL_GPL(pm_generic_restore_noirq); | 247 | EXPORT_SYMBOL_GPL(pm_generic_restore_noirq); |
286 | 248 | ||
@@ -290,7 +252,7 @@ EXPORT_SYMBOL_GPL(pm_generic_restore_noirq); | |||
290 | */ | 252 | */ |
291 | int pm_generic_restore(struct device *dev) | 253 | int pm_generic_restore(struct device *dev) |
292 | { | 254 | { |
293 | return __pm_generic_resume(dev, PM_EVENT_RESTORE, false); | 255 | return __pm_generic_call(dev, PM_EVENT_RESTORE, false); |
294 | } | 256 | } |
295 | EXPORT_SYMBOL_GPL(pm_generic_restore); | 257 | EXPORT_SYMBOL_GPL(pm_generic_restore); |
296 | 258 | ||
@@ -314,28 +276,3 @@ void pm_generic_complete(struct device *dev) | |||
314 | pm_runtime_idle(dev); | 276 | pm_runtime_idle(dev); |
315 | } | 277 | } |
316 | #endif /* CONFIG_PM_SLEEP */ | 278 | #endif /* CONFIG_PM_SLEEP */ |
317 | |||
318 | struct dev_pm_ops generic_subsys_pm_ops = { | ||
319 | #ifdef CONFIG_PM_SLEEP | ||
320 | .prepare = pm_generic_prepare, | ||
321 | .suspend = pm_generic_suspend, | ||
322 | .suspend_noirq = pm_generic_suspend_noirq, | ||
323 | .resume = pm_generic_resume, | ||
324 | .resume_noirq = pm_generic_resume_noirq, | ||
325 | .freeze = pm_generic_freeze, | ||
326 | .freeze_noirq = pm_generic_freeze_noirq, | ||
327 | .thaw = pm_generic_thaw, | ||
328 | .thaw_noirq = pm_generic_thaw_noirq, | ||
329 | .poweroff = pm_generic_poweroff, | ||
330 | .poweroff_noirq = pm_generic_poweroff_noirq, | ||
331 | .restore = pm_generic_restore, | ||
332 | .restore_noirq = pm_generic_restore_noirq, | ||
333 | .complete = pm_generic_complete, | ||
334 | #endif | ||
335 | #ifdef CONFIG_PM_RUNTIME | ||
336 | .runtime_suspend = pm_generic_runtime_suspend, | ||
337 | .runtime_resume = pm_generic_runtime_resume, | ||
338 | .runtime_idle = pm_generic_runtime_idle, | ||
339 | #endif | ||
340 | }; | ||
341 | EXPORT_SYMBOL_GPL(generic_subsys_pm_ops); | ||