aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/main.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-08 16:10:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-08 16:10:57 -0500
commiteb59c505f8a5906ad2e053d14fab50eb8574fd6f (patch)
treec6e875adc12b481b916e847e8f80b8881a0fb02c /drivers/base/power/main.c
parent1619ed8f60959829d070d8f39cd2f8ca0e7135ce (diff)
parentc233523b3d392e530033a7587d7970dc62a02361 (diff)
Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
* 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (76 commits) PM / Hibernate: Implement compat_ioctl for /dev/snapshot PM / Freezer: fix return value of freezable_schedule_timeout_killable() PM / shmobile: Allow the A4R domain to be turned off at run time PM / input / touchscreen: Make st1232 use device PM QoS constraints PM / QoS: Introduce dev_pm_qos_add_ancestor_request() PM / shmobile: Remove the stay_on flag from SH7372's PM domains PM / shmobile: Don't include SH7372's INTCS in syscore suspend/resume PM / shmobile: Add support for the sh7372 A4S power domain / sleep mode PM: Drop generic_subsys_pm_ops PM / Sleep: Remove forward-only callbacks from AMBA bus type PM / Sleep: Remove forward-only callbacks from platform bus type PM: Run the driver callback directly if the subsystem one is not there PM / Sleep: Make pm_op() and pm_noirq_op() return callback pointers PM/Devfreq: Add Exynos4-bus device DVFS driver for Exynos4210/4212/4412. PM / Sleep: Merge internal functions in generic_ops.c PM / Sleep: Simplify generic system suspend callbacks PM / Hibernate: Remove deprecated hibernation snapshot ioctls PM / Sleep: Fix freezer failures due to racy usermodehelper_is_disabled() ARM: S3C64XX: Implement basic power domain support PM / shmobile: Use common always on power domain governor ... Fix up trivial conflict in fs/xfs/xfs_buf.c due to removal of unused XBT_FORCE_SLEEP bit
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r--drivers/base/power/main.c375
1 files changed, 165 insertions, 210 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index c3d2dfcf438d..e2cc3d2e0ecc 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
@@ -164,8 +166,9 @@ static ktime_t initcall_debug_start(struct device *dev)
164 ktime_t calltime = ktime_set(0, 0); 166 ktime_t calltime = ktime_set(0, 0);
165 167
166 if (initcall_debug) { 168 if (initcall_debug) {
167 pr_info("calling %s+ @ %i\n", 169 pr_info("calling %s+ @ %i, parent: %s\n",
168 dev_name(dev), task_pid_nr(current)); 170 dev_name(dev), task_pid_nr(current),
171 dev->parent ? dev_name(dev->parent) : "none");
169 calltime = ktime_get(); 172 calltime = ktime_get();
170 } 173 }
171 174
@@ -211,151 +214,69 @@ static void dpm_wait_for_children(struct device *dev, bool async)
211} 214}
212 215
213/** 216/**
214 * pm_op - Execute the PM operation appropriate for given PM event. 217 * pm_op - Return the PM operation appropriate for given PM event.
215 * @dev: Device to handle.
216 * @ops: PM operations to choose from. 218 * @ops: PM operations to choose from.
217 * @state: PM transition of the system being carried out. 219 * @state: PM transition of the system being carried out.
218 */ 220 */
219static int pm_op(struct device *dev, 221static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
220 const struct dev_pm_ops *ops,
221 pm_message_t state)
222{ 222{
223 int error = 0;
224 ktime_t calltime;
225
226 calltime = initcall_debug_start(dev);
227
228 switch (state.event) { 223 switch (state.event) {
229#ifdef CONFIG_SUSPEND 224#ifdef CONFIG_SUSPEND
230 case PM_EVENT_SUSPEND: 225 case PM_EVENT_SUSPEND:
231 if (ops->suspend) { 226 return ops->suspend;
232 error = ops->suspend(dev);
233 suspend_report_result(ops->suspend, error);
234 }
235 break;
236 case PM_EVENT_RESUME: 227 case PM_EVENT_RESUME:
237 if (ops->resume) { 228 return ops->resume;
238 error = ops->resume(dev);
239 suspend_report_result(ops->resume, error);
240 }
241 break;
242#endif /* CONFIG_SUSPEND */ 229#endif /* CONFIG_SUSPEND */
243#ifdef CONFIG_HIBERNATE_CALLBACKS 230#ifdef CONFIG_HIBERNATE_CALLBACKS
244 case PM_EVENT_FREEZE: 231 case PM_EVENT_FREEZE:
245 case PM_EVENT_QUIESCE: 232 case PM_EVENT_QUIESCE:
246 if (ops->freeze) { 233 return ops->freeze;
247 error = ops->freeze(dev);
248 suspend_report_result(ops->freeze, error);
249 }
250 break;
251 case PM_EVENT_HIBERNATE: 234 case PM_EVENT_HIBERNATE:
252 if (ops->poweroff) { 235 return ops->poweroff;
253 error = ops->poweroff(dev);
254 suspend_report_result(ops->poweroff, error);
255 }
256 break;
257 case PM_EVENT_THAW: 236 case PM_EVENT_THAW:
258 case PM_EVENT_RECOVER: 237 case PM_EVENT_RECOVER:
259 if (ops->thaw) { 238 return ops->thaw;
260 error = ops->thaw(dev);
261 suspend_report_result(ops->thaw, error);
262 }
263 break; 239 break;
264 case PM_EVENT_RESTORE: 240 case PM_EVENT_RESTORE:
265 if (ops->restore) { 241 return ops->restore;
266 error = ops->restore(dev);
267 suspend_report_result(ops->restore, error);
268 }
269 break;
270#endif /* CONFIG_HIBERNATE_CALLBACKS */ 242#endif /* CONFIG_HIBERNATE_CALLBACKS */
271 default:
272 error = -EINVAL;
273 } 243 }
274 244
275 initcall_debug_report(dev, calltime, error); 245 return NULL;
276
277 return error;
278} 246}
279 247
280/** 248/**
281 * 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.
282 * @dev: Device to handle.
283 * @ops: PM operations to choose from. 250 * @ops: PM operations to choose from.
284 * @state: PM transition of the system being carried out. 251 * @state: PM transition of the system being carried out.
285 * 252 *
286 * 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
287 * executed. 254 * executed.
288 */ 255 */
289static int pm_noirq_op(struct device *dev, 256static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
290 const struct dev_pm_ops *ops,
291 pm_message_t state)
292{ 257{
293 int error = 0;
294 ktime_t calltime = ktime_set(0, 0), delta, rettime;
295
296 if (initcall_debug) {
297 pr_info("calling %s+ @ %i, parent: %s\n",
298 dev_name(dev), task_pid_nr(current),
299 dev->parent ? dev_name(dev->parent) : "none");
300 calltime = ktime_get();
301 }
302
303 switch (state.event) { 258 switch (state.event) {
304#ifdef CONFIG_SUSPEND 259#ifdef CONFIG_SUSPEND
305 case PM_EVENT_SUSPEND: 260 case PM_EVENT_SUSPEND:
306 if (ops->suspend_noirq) { 261 return ops->suspend_noirq;
307 error = ops->suspend_noirq(dev);
308 suspend_report_result(ops->suspend_noirq, error);
309 }
310 break;
311 case PM_EVENT_RESUME: 262 case PM_EVENT_RESUME:
312 if (ops->resume_noirq) { 263 return ops->resume_noirq;
313 error = ops->resume_noirq(dev);
314 suspend_report_result(ops->resume_noirq, error);
315 }
316 break;
317#endif /* CONFIG_SUSPEND */ 264#endif /* CONFIG_SUSPEND */
318#ifdef CONFIG_HIBERNATE_CALLBACKS 265#ifdef CONFIG_HIBERNATE_CALLBACKS
319 case PM_EVENT_FREEZE: 266 case PM_EVENT_FREEZE:
320 case PM_EVENT_QUIESCE: 267 case PM_EVENT_QUIESCE:
321 if (ops->freeze_noirq) { 268 return ops->freeze_noirq;
322 error = ops->freeze_noirq(dev);
323 suspend_report_result(ops->freeze_noirq, error);
324 }
325 break;
326 case PM_EVENT_HIBERNATE: 269 case PM_EVENT_HIBERNATE:
327 if (ops->poweroff_noirq) { 270 return ops->poweroff_noirq;
328 error = ops->poweroff_noirq(dev);
329 suspend_report_result(ops->poweroff_noirq, error);
330 }
331 break;
332 case PM_EVENT_THAW: 271 case PM_EVENT_THAW:
333 case PM_EVENT_RECOVER: 272 case PM_EVENT_RECOVER:
334 if (ops->thaw_noirq) { 273 return ops->thaw_noirq;
335 error = ops->thaw_noirq(dev);
336 suspend_report_result(ops->thaw_noirq, error);
337 }
338 break;
339 case PM_EVENT_RESTORE: 274 case PM_EVENT_RESTORE:
340 if (ops->restore_noirq) { 275 return ops->restore_noirq;
341 error = ops->restore_noirq(dev);
342 suspend_report_result(ops->restore_noirq, error);
343 }
344 break;
345#endif /* CONFIG_HIBERNATE_CALLBACKS */ 276#endif /* CONFIG_HIBERNATE_CALLBACKS */
346 default:
347 error = -EINVAL;
348 }
349
350 if (initcall_debug) {
351 rettime = ktime_get();
352 delta = ktime_sub(rettime, calltime);
353 printk("initcall %s_i+ returned %d after %Ld usecs\n",
354 dev_name(dev), error,
355 (unsigned long long)ktime_to_ns(delta) >> 10);
356 } 277 }
357 278
358 return error; 279 return NULL;
359} 280}
360 281
361static char *pm_verb(int event) 282static char *pm_verb(int event)
@@ -413,6 +334,26 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
413 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC); 334 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
414} 335}
415 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
416/*------------------------- Resume routines -------------------------*/ 357/*------------------------- Resume routines -------------------------*/
417 358
418/** 359/**
@@ -425,25 +366,34 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
425 */ 366 */
426static int device_resume_noirq(struct device *dev, pm_message_t state) 367static int device_resume_noirq(struct device *dev, pm_message_t state)
427{ 368{
369 pm_callback_t callback = NULL;
370 char *info = NULL;
428 int error = 0; 371 int error = 0;
429 372
430 TRACE_DEVICE(dev); 373 TRACE_DEVICE(dev);
431 TRACE_RESUME(0); 374 TRACE_RESUME(0);
432 375
433 if (dev->pm_domain) { 376 if (dev->pm_domain) {
434 pm_dev_dbg(dev, state, "EARLY power domain "); 377 info = "EARLY power domain ";
435 error = pm_noirq_op(dev, &dev->pm_domain->ops, state); 378 callback = pm_noirq_op(&dev->pm_domain->ops, state);
436 } else if (dev->type && dev->type->pm) { 379 } else if (dev->type && dev->type->pm) {
437 pm_dev_dbg(dev, state, "EARLY type "); 380 info = "EARLY type ";
438 error = pm_noirq_op(dev, dev->type->pm, state); 381 callback = pm_noirq_op(dev->type->pm, state);
439 } else if (dev->class && dev->class->pm) { 382 } else if (dev->class && dev->class->pm) {
440 pm_dev_dbg(dev, state, "EARLY class "); 383 info = "EARLY class ";
441 error = pm_noirq_op(dev, dev->class->pm, state); 384 callback = pm_noirq_op(dev->class->pm, state);
442 } else if (dev->bus && dev->bus->pm) { 385 } else if (dev->bus && dev->bus->pm) {
443 pm_dev_dbg(dev, state, "EARLY "); 386 info = "EARLY bus ";
444 error = pm_noirq_op(dev, dev->bus->pm, state); 387 callback = pm_noirq_op(dev->bus->pm, state);
445 } 388 }
446 389
390 if (!callback && dev->driver && dev->driver->pm) {
391 info = "EARLY driver ";
392 callback = pm_noirq_op(dev->driver->pm, state);
393 }
394
395 error = dpm_run_callback(callback, dev, state, info);
396
447 TRACE_RESUME(error); 397 TRACE_RESUME(error);
448 return error; 398 return error;
449} 399}
@@ -486,26 +436,6 @@ void dpm_resume_noirq(pm_message_t state)
486EXPORT_SYMBOL_GPL(dpm_resume_noirq); 436EXPORT_SYMBOL_GPL(dpm_resume_noirq);
487 437
488/** 438/**
489 * legacy_resume - Execute a legacy (bus or class) resume callback for device.
490 * @dev: Device to resume.
491 * @cb: Resume callback to execute.
492 */
493static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
494{
495 int error;
496 ktime_t calltime;
497
498 calltime = initcall_debug_start(dev);
499
500 error = cb(dev);
501 suspend_report_result(cb, error);
502
503 initcall_debug_report(dev, calltime, error);
504
505 return error;
506}
507
508/**
509 * device_resume - Execute "resume" callbacks for given device. 439 * device_resume - Execute "resume" callbacks for given device.
510 * @dev: Device to handle. 440 * @dev: Device to handle.
511 * @state: PM transition of the system being carried out. 441 * @state: PM transition of the system being carried out.
@@ -513,6 +443,8 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
513 */ 443 */
514static int device_resume(struct device *dev, pm_message_t state, bool async) 444static int device_resume(struct device *dev, pm_message_t state, bool async)
515{ 445{
446 pm_callback_t callback = NULL;
447 char *info = NULL;
516 int error = 0; 448 int error = 0;
517 bool put = false; 449 bool put = false;
518 450
@@ -535,40 +467,48 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
535 put = true; 467 put = true;
536 468
537 if (dev->pm_domain) { 469 if (dev->pm_domain) {
538 pm_dev_dbg(dev, state, "power domain "); 470 info = "power domain ";
539 error = pm_op(dev, &dev->pm_domain->ops, state); 471 callback = pm_op(&dev->pm_domain->ops, state);
540 goto End; 472 goto Driver;
541 } 473 }
542 474
543 if (dev->type && dev->type->pm) { 475 if (dev->type && dev->type->pm) {
544 pm_dev_dbg(dev, state, "type "); 476 info = "type ";
545 error = pm_op(dev, dev->type->pm, state); 477 callback = pm_op(dev->type->pm, state);
546 goto End; 478 goto Driver;
547 } 479 }
548 480
549 if (dev->class) { 481 if (dev->class) {
550 if (dev->class->pm) { 482 if (dev->class->pm) {
551 pm_dev_dbg(dev, state, "class "); 483 info = "class ";
552 error = pm_op(dev, dev->class->pm, state); 484 callback = pm_op(dev->class->pm, state);
553 goto End; 485 goto Driver;
554 } else if (dev->class->resume) { 486 } else if (dev->class->resume) {
555 pm_dev_dbg(dev, state, "legacy class "); 487 info = "legacy class ";
556 error = legacy_resume(dev, dev->class->resume); 488 callback = dev->class->resume;
557 goto End; 489 goto End;
558 } 490 }
559 } 491 }
560 492
561 if (dev->bus) { 493 if (dev->bus) {
562 if (dev->bus->pm) { 494 if (dev->bus->pm) {
563 pm_dev_dbg(dev, state, ""); 495 info = "bus ";
564 error = pm_op(dev, dev->bus->pm, state); 496 callback = pm_op(dev->bus->pm, state);
565 } else if (dev->bus->resume) { 497 } else if (dev->bus->resume) {
566 pm_dev_dbg(dev, state, "legacy "); 498 info = "legacy bus ";
567 error = legacy_resume(dev, dev->bus->resume); 499 callback = dev->bus->resume;
500 goto End;
568 } 501 }
569 } 502 }
570 503
504 Driver:
505 if (!callback && dev->driver && dev->driver->pm) {
506 info = "driver ";
507 callback = pm_op(dev->driver->pm, state);
508 }
509
571 End: 510 End:
511 error = dpm_run_callback(callback, dev, state, info);
572 dev->power.is_suspended = false; 512 dev->power.is_suspended = false;
573 513
574 Unlock: 514 Unlock:
@@ -660,24 +600,33 @@ void dpm_resume(pm_message_t state)
660 */ 600 */
661static void device_complete(struct device *dev, pm_message_t state) 601static void device_complete(struct device *dev, pm_message_t state)
662{ 602{
603 void (*callback)(struct device *) = NULL;
604 char *info = NULL;
605
663 device_lock(dev); 606 device_lock(dev);
664 607
665 if (dev->pm_domain) { 608 if (dev->pm_domain) {
666 pm_dev_dbg(dev, state, "completing power domain "); 609 info = "completing power domain ";
667 if (dev->pm_domain->ops.complete) 610 callback = dev->pm_domain->ops.complete;
668 dev->pm_domain->ops.complete(dev);
669 } else if (dev->type && dev->type->pm) { 611 } else if (dev->type && dev->type->pm) {
670 pm_dev_dbg(dev, state, "completing type "); 612 info = "completing type ";
671 if (dev->type->pm->complete) 613 callback = dev->type->pm->complete;
672 dev->type->pm->complete(dev);
673 } else if (dev->class && dev->class->pm) { 614 } else if (dev->class && dev->class->pm) {
674 pm_dev_dbg(dev, state, "completing class "); 615 info = "completing class ";
675 if (dev->class->pm->complete) 616 callback = dev->class->pm->complete;
676 dev->class->pm->complete(dev);
677 } else if (dev->bus && dev->bus->pm) { 617 } else if (dev->bus && dev->bus->pm) {
678 pm_dev_dbg(dev, state, "completing "); 618 info = "completing bus ";
679 if (dev->bus->pm->complete) 619 callback = dev->bus->pm->complete;
680 dev->bus->pm->complete(dev); 620 }
621
622 if (!callback && dev->driver && dev->driver->pm) {
623 info = "completing driver ";
624 callback = dev->driver->pm->complete;
625 }
626
627 if (callback) {
628 pm_dev_dbg(dev, state, info);
629 callback(dev);
681 } 630 }
682 631
683 device_unlock(dev); 632 device_unlock(dev);
@@ -763,31 +712,29 @@ static pm_message_t resume_event(pm_message_t sleep_state)
763 */ 712 */
764static int device_suspend_noirq(struct device *dev, pm_message_t state) 713static int device_suspend_noirq(struct device *dev, pm_message_t state)
765{ 714{
766 int error; 715 pm_callback_t callback = NULL;
716 char *info = NULL;
767 717
768 if (dev->pm_domain) { 718 if (dev->pm_domain) {
769 pm_dev_dbg(dev, state, "LATE power domain "); 719 info = "LATE power domain ";
770 error = pm_noirq_op(dev, &dev->pm_domain->ops, state); 720 callback = pm_noirq_op(&dev->pm_domain->ops, state);
771 if (error)
772 return error;
773 } else if (dev->type && dev->type->pm) { 721 } else if (dev->type && dev->type->pm) {
774 pm_dev_dbg(dev, state, "LATE type "); 722 info = "LATE type ";
775 error = pm_noirq_op(dev, dev->type->pm, state); 723 callback = pm_noirq_op(dev->type->pm, state);
776 if (error)
777 return error;
778 } else if (dev->class && dev->class->pm) { 724 } else if (dev->class && dev->class->pm) {
779 pm_dev_dbg(dev, state, "LATE class "); 725 info = "LATE class ";
780 error = pm_noirq_op(dev, dev->class->pm, state); 726 callback = pm_noirq_op(dev->class->pm, state);
781 if (error)
782 return error;
783 } else if (dev->bus && dev->bus->pm) { 727 } else if (dev->bus && dev->bus->pm) {
784 pm_dev_dbg(dev, state, "LATE "); 728 info = "LATE bus ";
785 error = pm_noirq_op(dev, dev->bus->pm, state); 729 callback = pm_noirq_op(dev->bus->pm, state);
786 if (error)
787 return error;
788 } 730 }
789 731
790 return 0; 732 if (!callback && dev->driver && dev->driver->pm) {
733 info = "LATE driver ";
734 callback = pm_noirq_op(dev->driver->pm, state);
735 }
736
737 return dpm_run_callback(callback, dev, state, info);
791} 738}
792 739
793/** 740/**
@@ -864,6 +811,8 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
864 */ 811 */
865static int __device_suspend(struct device *dev, pm_message_t state, bool async) 812static int __device_suspend(struct device *dev, pm_message_t state, bool async)
866{ 813{
814 pm_callback_t callback = NULL;
815 char *info = NULL;
867 int error = 0; 816 int error = 0;
868 817
869 dpm_wait_for_children(dev, async); 818 dpm_wait_for_children(dev, async);
@@ -884,22 +833,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
884 device_lock(dev); 833 device_lock(dev);
885 834
886 if (dev->pm_domain) { 835 if (dev->pm_domain) {
887 pm_dev_dbg(dev, state, "power domain "); 836 info = "power domain ";
888 error = pm_op(dev, &dev->pm_domain->ops, state); 837 callback = pm_op(&dev->pm_domain->ops, state);
889 goto End; 838 goto Run;
890 } 839 }
891 840
892 if (dev->type && dev->type->pm) { 841 if (dev->type && dev->type->pm) {
893 pm_dev_dbg(dev, state, "type "); 842 info = "type ";
894 error = pm_op(dev, dev->type->pm, state); 843 callback = pm_op(dev->type->pm, state);
895 goto End; 844 goto Run;
896 } 845 }
897 846
898 if (dev->class) { 847 if (dev->class) {
899 if (dev->class->pm) { 848 if (dev->class->pm) {
900 pm_dev_dbg(dev, state, "class "); 849 info = "class ";
901 error = pm_op(dev, dev->class->pm, state); 850 callback = pm_op(dev->class->pm, state);
902 goto End; 851 goto Run;
903 } else if (dev->class->suspend) { 852 } else if (dev->class->suspend) {
904 pm_dev_dbg(dev, state, "legacy class "); 853 pm_dev_dbg(dev, state, "legacy class ");
905 error = legacy_suspend(dev, state, dev->class->suspend); 854 error = legacy_suspend(dev, state, dev->class->suspend);
@@ -909,14 +858,23 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
909 858
910 if (dev->bus) { 859 if (dev->bus) {
911 if (dev->bus->pm) { 860 if (dev->bus->pm) {
912 pm_dev_dbg(dev, state, ""); 861 info = "bus ";
913 error = pm_op(dev, dev->bus->pm, state); 862 callback = pm_op(dev->bus->pm, state);
914 } else if (dev->bus->suspend) { 863 } else if (dev->bus->suspend) {
915 pm_dev_dbg(dev, state, "legacy "); 864 pm_dev_dbg(dev, state, "legacy bus ");
916 error = legacy_suspend(dev, state, dev->bus->suspend); 865 error = legacy_suspend(dev, state, dev->bus->suspend);
866 goto End;
917 } 867 }
918 } 868 }
919 869
870 Run:
871 if (!callback && dev->driver && dev->driver->pm) {
872 info = "driver ";
873 callback = pm_op(dev->driver->pm, state);
874 }
875
876 error = dpm_run_callback(callback, dev, state, info);
877
920 End: 878 End:
921 if (!error) { 879 if (!error) {
922 dev->power.is_suspended = true; 880 dev->power.is_suspended = true;
@@ -1022,6 +980,8 @@ int dpm_suspend(pm_message_t state)
1022 */ 980 */
1023static int device_prepare(struct device *dev, pm_message_t state) 981static int device_prepare(struct device *dev, pm_message_t state)
1024{ 982{
983 int (*callback)(struct device *) = NULL;
984 char *info = NULL;
1025 int error = 0; 985 int error = 0;
1026 986
1027 device_lock(dev); 987 device_lock(dev);
@@ -1029,34 +989,29 @@ static int device_prepare(struct device *dev, pm_message_t state)
1029 dev->power.wakeup_path = device_may_wakeup(dev); 989 dev->power.wakeup_path = device_may_wakeup(dev);
1030 990
1031 if (dev->pm_domain) { 991 if (dev->pm_domain) {
1032 pm_dev_dbg(dev, state, "preparing power domain "); 992 info = "preparing power domain ";
1033 if (dev->pm_domain->ops.prepare) 993 callback = dev->pm_domain->ops.prepare;
1034 error = dev->pm_domain->ops.prepare(dev);
1035 suspend_report_result(dev->pm_domain->ops.prepare, error);
1036 if (error)
1037 goto End;
1038 } else if (dev->type && dev->type->pm) { 994 } else if (dev->type && dev->type->pm) {
1039 pm_dev_dbg(dev, state, "preparing type "); 995 info = "preparing type ";
1040 if (dev->type->pm->prepare) 996 callback = dev->type->pm->prepare;
1041 error = dev->type->pm->prepare(dev);
1042 suspend_report_result(dev->type->pm->prepare, error);
1043 if (error)
1044 goto End;
1045 } else if (dev->class && dev->class->pm) { 997 } else if (dev->class && dev->class->pm) {
1046 pm_dev_dbg(dev, state, "preparing class "); 998 info = "preparing class ";
1047 if (dev->class->pm->prepare) 999 callback = dev->class->pm->prepare;
1048 error = dev->class->pm->prepare(dev);
1049 suspend_report_result(dev->class->pm->prepare, error);
1050 if (error)
1051 goto End;
1052 } else if (dev->bus && dev->bus->pm) { 1000 } else if (dev->bus && dev->bus->pm) {
1053 pm_dev_dbg(dev, state, "preparing "); 1001 info = "preparing bus ";
1054 if (dev->bus->pm->prepare) 1002 callback = dev->bus->pm->prepare;
1055 error = dev->bus->pm->prepare(dev); 1003 }
1056 suspend_report_result(dev->bus->pm->prepare, error); 1004
1005 if (!callback && dev->driver && dev->driver->pm) {
1006 info = "preparing driver ";
1007 callback = dev->driver->pm->prepare;
1008 }
1009
1010 if (callback) {
1011 error = callback(dev);
1012 suspend_report_result(callback, error);
1057 } 1013 }
1058 1014
1059 End:
1060 device_unlock(dev); 1015 device_unlock(dev);
1061 1016
1062 return error; 1017 return error;