aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-12-17 18:34:01 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2011-12-21 16:00:56 -0500
commit9cf519d1c15fa05a538c2b3963c5f3903daf765a (patch)
tree44500e7eba98e682663ab253e4ba7edff7e9f875 /drivers/base
parentb00f4dc5ff022cb9cbaffd376d9454d7fa1e496f (diff)
PM / Sleep: Make pm_op() and pm_noirq_op() return callback pointers
Make the pm_op() and pm_noirq_op() functions return pointers to appropriate callbacks instead of executing those callbacks and returning their results. This change is required for a subsequent modification that will execute the corresponding driver callback if the subsystem callback returned by either pm_op(), or pm_noirq_op() is NULL. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c197
1 files changed, 95 insertions, 102 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index b570189d4f2d..b5cef7e7de23 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -32,6 +32,8 @@
32#include "../base.h" 32#include "../base.h"
33#include "power.h" 33#include "power.h"
34 34
35typedef int (*pm_callback_t)(struct device *);
36
35/* 37/*
36 * The entries in the dpm_list list are in a depth first order, simply 38 * The entries in the dpm_list list are in a depth first order, simply
37 * because children are guaranteed to be discovered after parents, and 39 * because children are guaranteed to be discovered after parents, and
@@ -211,113 +213,70 @@ static void dpm_wait_for_children(struct device *dev, bool async)
211 device_for_each_child(dev, &async, dpm_wait_fn); 213 device_for_each_child(dev, &async, dpm_wait_fn);
212} 214}
213 215
214static int dpm_run_callback(struct device *dev, int (*cb)(struct device *))
215{
216 ktime_t calltime;
217 int error;
218
219 if (!cb)
220 return 0;
221
222 calltime = initcall_debug_start(dev);
223
224 error = cb(dev);
225 suspend_report_result(cb, error);
226
227 initcall_debug_report(dev, calltime, error);
228
229 return error;
230}
231
232/** 216/**
233 * pm_op - Execute the PM operation appropriate for given PM event. 217 * pm_op - Return the PM operation appropriate for given PM event.
234 * @dev: Device to handle.
235 * @ops: PM operations to choose from. 218 * @ops: PM operations to choose from.
236 * @state: PM transition of the system being carried out. 219 * @state: PM transition of the system being carried out.
237 */ 220 */
238static int pm_op(struct device *dev, 221static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
239 const struct dev_pm_ops *ops,
240 pm_message_t state)
241{ 222{
242 int error = 0;
243
244 switch (state.event) { 223 switch (state.event) {
245#ifdef CONFIG_SUSPEND 224#ifdef CONFIG_SUSPEND
246 case PM_EVENT_SUSPEND: 225 case PM_EVENT_SUSPEND:
247 error = dpm_run_callback(dev, ops->suspend); 226 return ops->suspend;
248 break;
249 case PM_EVENT_RESUME: 227 case PM_EVENT_RESUME:
250 error = dpm_run_callback(dev, ops->resume); 228 return ops->resume;
251 break;
252#endif /* CONFIG_SUSPEND */ 229#endif /* CONFIG_SUSPEND */
253#ifdef CONFIG_HIBERNATE_CALLBACKS 230#ifdef CONFIG_HIBERNATE_CALLBACKS
254 case PM_EVENT_FREEZE: 231 case PM_EVENT_FREEZE:
255 case PM_EVENT_QUIESCE: 232 case PM_EVENT_QUIESCE:
256 error = dpm_run_callback(dev, ops->freeze); 233 return ops->freeze;
257 break;
258 case PM_EVENT_HIBERNATE: 234 case PM_EVENT_HIBERNATE:
259 error = dpm_run_callback(dev, ops->poweroff); 235 return ops->poweroff;
260 break;
261 case PM_EVENT_THAW: 236 case PM_EVENT_THAW:
262 case PM_EVENT_RECOVER: 237 case PM_EVENT_RECOVER:
263 error = dpm_run_callback(dev, ops->thaw); 238 return ops->thaw;
264 break; 239 break;
265 case PM_EVENT_RESTORE: 240 case PM_EVENT_RESTORE:
266 error = dpm_run_callback(dev, ops->restore); 241 return ops->restore;
267 break;
268#endif /* CONFIG_HIBERNATE_CALLBACKS */ 242#endif /* CONFIG_HIBERNATE_CALLBACKS */
269 default:
270 error = -EINVAL;
271 } 243 }
272 244
273 return error; 245 return NULL;
274} 246}
275 247
276/** 248/**
277 * pm_noirq_op - Execute the PM operation appropriate for given PM event. 249 * pm_noirq_op - Return the PM operation appropriate for given PM event.
278 * @dev: Device to handle.
279 * @ops: PM operations to choose from. 250 * @ops: PM operations to choose from.
280 * @state: PM transition of the system being carried out. 251 * @state: PM transition of the system being carried out.
281 * 252 *
282 * The driver of @dev will not receive interrupts while this function is being 253 * The driver of @dev will not receive interrupts while this function is being
283 * executed. 254 * executed.
284 */ 255 */
285static int pm_noirq_op(struct device *dev, 256static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
286 const struct dev_pm_ops *ops,
287 pm_message_t state)
288{ 257{
289 int error = 0;
290
291 switch (state.event) { 258 switch (state.event) {
292#ifdef CONFIG_SUSPEND 259#ifdef CONFIG_SUSPEND
293 case PM_EVENT_SUSPEND: 260 case PM_EVENT_SUSPEND:
294 error = dpm_run_callback(dev, ops->suspend_noirq); 261 return ops->suspend_noirq;
295 break;
296 case PM_EVENT_RESUME: 262 case PM_EVENT_RESUME:
297 error = dpm_run_callback(dev, ops->resume_noirq); 263 return ops->resume_noirq;
298 break;
299#endif /* CONFIG_SUSPEND */ 264#endif /* CONFIG_SUSPEND */
300#ifdef CONFIG_HIBERNATE_CALLBACKS 265#ifdef CONFIG_HIBERNATE_CALLBACKS
301 case PM_EVENT_FREEZE: 266 case PM_EVENT_FREEZE:
302 case PM_EVENT_QUIESCE: 267 case PM_EVENT_QUIESCE:
303 error = dpm_run_callback(dev, ops->freeze_noirq); 268 return ops->freeze_noirq;
304 break;
305 case PM_EVENT_HIBERNATE: 269 case PM_EVENT_HIBERNATE:
306 error = dpm_run_callback(dev, ops->poweroff_noirq); 270 return ops->poweroff_noirq;
307 break;
308 case PM_EVENT_THAW: 271 case PM_EVENT_THAW:
309 case PM_EVENT_RECOVER: 272 case PM_EVENT_RECOVER:
310 error = dpm_run_callback(dev, ops->thaw_noirq); 273 return ops->thaw_noirq;
311 break;
312 case PM_EVENT_RESTORE: 274 case PM_EVENT_RESTORE:
313 error = dpm_run_callback(dev, ops->restore_noirq); 275 return ops->restore_noirq;
314 break;
315#endif /* CONFIG_HIBERNATE_CALLBACKS */ 276#endif /* CONFIG_HIBERNATE_CALLBACKS */
316 default:
317 error = -EINVAL;
318 } 277 }
319 278
320 return error; 279 return NULL;
321} 280}
322 281
323static char *pm_verb(int event) 282static char *pm_verb(int event)
@@ -375,6 +334,26 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
375 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC); 334 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
376} 335}
377 336
337static int dpm_run_callback(pm_callback_t cb, struct device *dev,
338 pm_message_t state, char *info)
339{
340 ktime_t calltime;
341 int error;
342
343 if (!cb)
344 return 0;
345
346 calltime = initcall_debug_start(dev);
347
348 pm_dev_dbg(dev, state, info);
349 error = cb(dev);
350 suspend_report_result(cb, error);
351
352 initcall_debug_report(dev, calltime, error);
353
354 return error;
355}
356
378/*------------------------- Resume routines -------------------------*/ 357/*------------------------- Resume routines -------------------------*/
379 358
380/** 359/**
@@ -387,25 +366,29 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
387 */ 366 */
388static int device_resume_noirq(struct device *dev, pm_message_t state) 367static int device_resume_noirq(struct device *dev, pm_message_t state)
389{ 368{
369 pm_callback_t callback = NULL;
370 char *info = NULL;
390 int error = 0; 371 int error = 0;
391 372
392 TRACE_DEVICE(dev); 373 TRACE_DEVICE(dev);
393 TRACE_RESUME(0); 374 TRACE_RESUME(0);
394 375
395 if (dev->pm_domain) { 376 if (dev->pm_domain) {
396 pm_dev_dbg(dev, state, "EARLY power domain "); 377 info = "EARLY power domain ";
397 error = pm_noirq_op(dev, &dev->pm_domain->ops, state); 378 callback = pm_noirq_op(&dev->pm_domain->ops, state);
398 } else if (dev->type && dev->type->pm) { 379 } else if (dev->type && dev->type->pm) {
399 pm_dev_dbg(dev, state, "EARLY type "); 380 info = "EARLY type ";
400 error = pm_noirq_op(dev, dev->type->pm, state); 381 callback = pm_noirq_op(dev->type->pm, state);
401 } else if (dev->class && dev->class->pm) { 382 } else if (dev->class && dev->class->pm) {
402 pm_dev_dbg(dev, state, "EARLY class "); 383 info = "EARLY class ";
403 error = pm_noirq_op(dev, dev->class->pm, state); 384 callback = pm_noirq_op(dev->class->pm, state);
404 } else if (dev->bus && dev->bus->pm) { 385 } else if (dev->bus && dev->bus->pm) {
405 pm_dev_dbg(dev, state, "EARLY "); 386 info = "EARLY ";
406 error = pm_noirq_op(dev, dev->bus->pm, state); 387 callback = pm_noirq_op(dev->bus->pm, state);
407 } 388 }
408 389
390 error = dpm_run_callback(callback, dev, state, info);
391
409 TRACE_RESUME(error); 392 TRACE_RESUME(error);
410 return error; 393 return error;
411} 394}
@@ -455,6 +438,8 @@ EXPORT_SYMBOL_GPL(dpm_resume_noirq);
455 */ 438 */
456static int device_resume(struct device *dev, pm_message_t state, bool async) 439static int device_resume(struct device *dev, pm_message_t state, bool async)
457{ 440{
441 pm_callback_t callback = NULL;
442 char *info = NULL;
458 int error = 0; 443 int error = 0;
459 bool put = false; 444 bool put = false;
460 445
@@ -477,40 +462,41 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
477 put = true; 462 put = true;
478 463
479 if (dev->pm_domain) { 464 if (dev->pm_domain) {
480 pm_dev_dbg(dev, state, "power domain "); 465 info = "power domain ";
481 error = pm_op(dev, &dev->pm_domain->ops, state); 466 callback = pm_op(&dev->pm_domain->ops, state);
482 goto End; 467 goto End;
483 } 468 }
484 469
485 if (dev->type && dev->type->pm) { 470 if (dev->type && dev->type->pm) {
486 pm_dev_dbg(dev, state, "type "); 471 info = "type ";
487 error = pm_op(dev, dev->type->pm, state); 472 callback = pm_op(dev->type->pm, state);
488 goto End; 473 goto End;
489 } 474 }
490 475
491 if (dev->class) { 476 if (dev->class) {
492 if (dev->class->pm) { 477 if (dev->class->pm) {
493 pm_dev_dbg(dev, state, "class "); 478 info = "class ";
494 error = pm_op(dev, dev->class->pm, state); 479 callback = pm_op(dev->class->pm, state);
495 goto End; 480 goto End;
496 } else if (dev->class->resume) { 481 } else if (dev->class->resume) {
497 pm_dev_dbg(dev, state, "legacy class "); 482 info = "legacy class ";
498 error = dpm_run_callback(dev, dev->class->resume); 483 callback = dev->class->resume;
499 goto End; 484 goto End;
500 } 485 }
501 } 486 }
502 487
503 if (dev->bus) { 488 if (dev->bus) {
504 if (dev->bus->pm) { 489 if (dev->bus->pm) {
505 pm_dev_dbg(dev, state, ""); 490 info = "";
506 error = pm_op(dev, dev->bus->pm, state); 491 callback = pm_op(dev->bus->pm, state);
507 } else if (dev->bus->resume) { 492 } else if (dev->bus->resume) {
508 pm_dev_dbg(dev, state, "legacy "); 493 info = "legacy ";
509 error = dpm_run_callback(dev, dev->bus->resume); 494 callback = dev->bus->resume;
510 } 495 }
511 } 496 }
512 497
513 End: 498 End:
499 error = dpm_run_callback(callback, dev, state, info);
514 dev->power.is_suspended = false; 500 dev->power.is_suspended = false;
515 501
516 Unlock: 502 Unlock:
@@ -705,23 +691,24 @@ static pm_message_t resume_event(pm_message_t sleep_state)
705 */ 691 */
706static int device_suspend_noirq(struct device *dev, pm_message_t state) 692static int device_suspend_noirq(struct device *dev, pm_message_t state)
707{ 693{
708 int error = 0; 694 pm_callback_t callback = NULL;
695 char *info = NULL;
709 696
710 if (dev->pm_domain) { 697 if (dev->pm_domain) {
711 pm_dev_dbg(dev, state, "LATE power domain "); 698 info = "LATE power domain ";
712 error = pm_noirq_op(dev, &dev->pm_domain->ops, state); 699 callback = pm_noirq_op(&dev->pm_domain->ops, state);
713 } else if (dev->type && dev->type->pm) { 700 } else if (dev->type && dev->type->pm) {
714 pm_dev_dbg(dev, state, "LATE type "); 701 info = "LATE type ";
715 error = pm_noirq_op(dev, dev->type->pm, state); 702 callback = pm_noirq_op(dev->type->pm, state);
716 } else if (dev->class && dev->class->pm) { 703 } else if (dev->class && dev->class->pm) {
717 pm_dev_dbg(dev, state, "LATE class "); 704 info = "LATE class ";
718 error = pm_noirq_op(dev, dev->class->pm, state); 705 callback = pm_noirq_op(dev->class->pm, state);
719 } else if (dev->bus && dev->bus->pm) { 706 } else if (dev->bus && dev->bus->pm) {
720 pm_dev_dbg(dev, state, "LATE "); 707 info = "LATE ";
721 error = pm_noirq_op(dev, dev->bus->pm, state); 708 callback = pm_noirq_op(dev->bus->pm, state);
722 } 709 }
723 710
724 return error; 711 return dpm_run_callback(callback, dev, state, info);
725} 712}
726 713
727/** 714/**
@@ -798,6 +785,8 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
798 */ 785 */
799static int __device_suspend(struct device *dev, pm_message_t state, bool async) 786static int __device_suspend(struct device *dev, pm_message_t state, bool async)
800{ 787{
788 pm_callback_t callback = NULL;
789 char *info = NULL;
801 int error = 0; 790 int error = 0;
802 791
803 dpm_wait_for_children(dev, async); 792 dpm_wait_for_children(dev, async);
@@ -818,22 +807,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
818 device_lock(dev); 807 device_lock(dev);
819 808
820 if (dev->pm_domain) { 809 if (dev->pm_domain) {
821 pm_dev_dbg(dev, state, "power domain "); 810 info = "power domain ";
822 error = pm_op(dev, &dev->pm_domain->ops, state); 811 callback = pm_op(&dev->pm_domain->ops, state);
823 goto End; 812 goto Run;
824 } 813 }
825 814
826 if (dev->type && dev->type->pm) { 815 if (dev->type && dev->type->pm) {
827 pm_dev_dbg(dev, state, "type "); 816 info = "type ";
828 error = pm_op(dev, dev->type->pm, state); 817 callback = pm_op(dev->type->pm, state);
829 goto End; 818 goto Run;
830 } 819 }
831 820
832 if (dev->class) { 821 if (dev->class) {
833 if (dev->class->pm) { 822 if (dev->class->pm) {
834 pm_dev_dbg(dev, state, "class "); 823 info = "class ";
835 error = pm_op(dev, dev->class->pm, state); 824 callback = pm_op(dev->class->pm, state);
836 goto End; 825 goto Run;
837 } else if (dev->class->suspend) { 826 } else if (dev->class->suspend) {
838 pm_dev_dbg(dev, state, "legacy class "); 827 pm_dev_dbg(dev, state, "legacy class ");
839 error = legacy_suspend(dev, state, dev->class->suspend); 828 error = legacy_suspend(dev, state, dev->class->suspend);
@@ -843,14 +832,18 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
843 832
844 if (dev->bus) { 833 if (dev->bus) {
845 if (dev->bus->pm) { 834 if (dev->bus->pm) {
846 pm_dev_dbg(dev, state, ""); 835 info = "";
847 error = pm_op(dev, dev->bus->pm, state); 836 callback = pm_op(dev->bus->pm, state);
848 } else if (dev->bus->suspend) { 837 } else if (dev->bus->suspend) {
849 pm_dev_dbg(dev, state, "legacy "); 838 pm_dev_dbg(dev, state, "legacy ");
850 error = legacy_suspend(dev, state, dev->bus->suspend); 839 error = legacy_suspend(dev, state, dev->bus->suspend);
840 goto End;
851 } 841 }
852 } 842 }
853 843
844 Run:
845 error = dpm_run_callback(callback, dev, state, info);
846
854 End: 847 End:
855 if (!error) { 848 if (!error) {
856 dev->power.is_suspended = true; 849 dev->power.is_suspended = true;