diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 109 |
1 files changed, 72 insertions, 37 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index b5cef7e7de23..e2cc3d2e0ecc 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -383,10 +383,15 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
383 | info = "EARLY class "; | 383 | info = "EARLY class "; |
384 | callback = pm_noirq_op(dev->class->pm, state); | 384 | callback = pm_noirq_op(dev->class->pm, state); |
385 | } else if (dev->bus && dev->bus->pm) { | 385 | } else if (dev->bus && dev->bus->pm) { |
386 | info = "EARLY "; | 386 | info = "EARLY bus "; |
387 | callback = pm_noirq_op(dev->bus->pm, state); | 387 | callback = pm_noirq_op(dev->bus->pm, state); |
388 | } | 388 | } |
389 | 389 | ||
390 | if (!callback && dev->driver && dev->driver->pm) { | ||
391 | info = "EARLY driver "; | ||
392 | callback = pm_noirq_op(dev->driver->pm, state); | ||
393 | } | ||
394 | |||
390 | error = dpm_run_callback(callback, dev, state, info); | 395 | error = dpm_run_callback(callback, dev, state, info); |
391 | 396 | ||
392 | TRACE_RESUME(error); | 397 | TRACE_RESUME(error); |
@@ -464,20 +469,20 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
464 | if (dev->pm_domain) { | 469 | if (dev->pm_domain) { |
465 | info = "power domain "; | 470 | info = "power domain "; |
466 | callback = pm_op(&dev->pm_domain->ops, state); | 471 | callback = pm_op(&dev->pm_domain->ops, state); |
467 | goto End; | 472 | goto Driver; |
468 | } | 473 | } |
469 | 474 | ||
470 | if (dev->type && dev->type->pm) { | 475 | if (dev->type && dev->type->pm) { |
471 | info = "type "; | 476 | info = "type "; |
472 | callback = pm_op(dev->type->pm, state); | 477 | callback = pm_op(dev->type->pm, state); |
473 | goto End; | 478 | goto Driver; |
474 | } | 479 | } |
475 | 480 | ||
476 | if (dev->class) { | 481 | if (dev->class) { |
477 | if (dev->class->pm) { | 482 | if (dev->class->pm) { |
478 | info = "class "; | 483 | info = "class "; |
479 | callback = pm_op(dev->class->pm, state); | 484 | callback = pm_op(dev->class->pm, state); |
480 | goto End; | 485 | goto Driver; |
481 | } else if (dev->class->resume) { | 486 | } else if (dev->class->resume) { |
482 | info = "legacy class "; | 487 | info = "legacy class "; |
483 | callback = dev->class->resume; | 488 | callback = dev->class->resume; |
@@ -487,14 +492,21 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
487 | 492 | ||
488 | if (dev->bus) { | 493 | if (dev->bus) { |
489 | if (dev->bus->pm) { | 494 | if (dev->bus->pm) { |
490 | info = ""; | 495 | info = "bus "; |
491 | callback = pm_op(dev->bus->pm, state); | 496 | callback = pm_op(dev->bus->pm, state); |
492 | } else if (dev->bus->resume) { | 497 | } else if (dev->bus->resume) { |
493 | info = "legacy "; | 498 | info = "legacy bus "; |
494 | callback = dev->bus->resume; | 499 | callback = dev->bus->resume; |
500 | goto End; | ||
495 | } | 501 | } |
496 | } | 502 | } |
497 | 503 | ||
504 | Driver: | ||
505 | if (!callback && dev->driver && dev->driver->pm) { | ||
506 | info = "driver "; | ||
507 | callback = pm_op(dev->driver->pm, state); | ||
508 | } | ||
509 | |||
498 | End: | 510 | End: |
499 | error = dpm_run_callback(callback, dev, state, info); | 511 | error = dpm_run_callback(callback, dev, state, info); |
500 | dev->power.is_suspended = false; | 512 | dev->power.is_suspended = false; |
@@ -588,24 +600,33 @@ void dpm_resume(pm_message_t state) | |||
588 | */ | 600 | */ |
589 | static void device_complete(struct device *dev, pm_message_t state) | 601 | static void device_complete(struct device *dev, pm_message_t state) |
590 | { | 602 | { |
603 | void (*callback)(struct device *) = NULL; | ||
604 | char *info = NULL; | ||
605 | |||
591 | device_lock(dev); | 606 | device_lock(dev); |
592 | 607 | ||
593 | if (dev->pm_domain) { | 608 | if (dev->pm_domain) { |
594 | pm_dev_dbg(dev, state, "completing power domain "); | 609 | info = "completing power domain "; |
595 | if (dev->pm_domain->ops.complete) | 610 | callback = dev->pm_domain->ops.complete; |
596 | dev->pm_domain->ops.complete(dev); | ||
597 | } else if (dev->type && dev->type->pm) { | 611 | } else if (dev->type && dev->type->pm) { |
598 | pm_dev_dbg(dev, state, "completing type "); | 612 | info = "completing type "; |
599 | if (dev->type->pm->complete) | 613 | callback = dev->type->pm->complete; |
600 | dev->type->pm->complete(dev); | ||
601 | } else if (dev->class && dev->class->pm) { | 614 | } else if (dev->class && dev->class->pm) { |
602 | pm_dev_dbg(dev, state, "completing class "); | 615 | info = "completing class "; |
603 | if (dev->class->pm->complete) | 616 | callback = dev->class->pm->complete; |
604 | dev->class->pm->complete(dev); | ||
605 | } else if (dev->bus && dev->bus->pm) { | 617 | } else if (dev->bus && dev->bus->pm) { |
606 | pm_dev_dbg(dev, state, "completing "); | 618 | info = "completing bus "; |
607 | if (dev->bus->pm->complete) | 619 | callback = dev->bus->pm->complete; |
608 | 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); | ||
609 | } | 630 | } |
610 | 631 | ||
611 | device_unlock(dev); | 632 | device_unlock(dev); |
@@ -704,10 +725,15 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) | |||
704 | info = "LATE class "; | 725 | info = "LATE class "; |
705 | callback = pm_noirq_op(dev->class->pm, state); | 726 | callback = pm_noirq_op(dev->class->pm, state); |
706 | } else if (dev->bus && dev->bus->pm) { | 727 | } else if (dev->bus && dev->bus->pm) { |
707 | info = "LATE "; | 728 | info = "LATE bus "; |
708 | callback = pm_noirq_op(dev->bus->pm, state); | 729 | callback = pm_noirq_op(dev->bus->pm, state); |
709 | } | 730 | } |
710 | 731 | ||
732 | if (!callback && dev->driver && dev->driver->pm) { | ||
733 | info = "LATE driver "; | ||
734 | callback = pm_noirq_op(dev->driver->pm, state); | ||
735 | } | ||
736 | |||
711 | return dpm_run_callback(callback, dev, state, info); | 737 | return dpm_run_callback(callback, dev, state, info); |
712 | } | 738 | } |
713 | 739 | ||
@@ -832,16 +858,21 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
832 | 858 | ||
833 | if (dev->bus) { | 859 | if (dev->bus) { |
834 | if (dev->bus->pm) { | 860 | if (dev->bus->pm) { |
835 | info = ""; | 861 | info = "bus "; |
836 | callback = pm_op(dev->bus->pm, state); | 862 | callback = pm_op(dev->bus->pm, state); |
837 | } else if (dev->bus->suspend) { | 863 | } else if (dev->bus->suspend) { |
838 | pm_dev_dbg(dev, state, "legacy "); | 864 | pm_dev_dbg(dev, state, "legacy bus "); |
839 | error = legacy_suspend(dev, state, dev->bus->suspend); | 865 | error = legacy_suspend(dev, state, dev->bus->suspend); |
840 | goto End; | 866 | goto End; |
841 | } | 867 | } |
842 | } | 868 | } |
843 | 869 | ||
844 | Run: | 870 | Run: |
871 | if (!callback && dev->driver && dev->driver->pm) { | ||
872 | info = "driver "; | ||
873 | callback = pm_op(dev->driver->pm, state); | ||
874 | } | ||
875 | |||
845 | error = dpm_run_callback(callback, dev, state, info); | 876 | error = dpm_run_callback(callback, dev, state, info); |
846 | 877 | ||
847 | End: | 878 | End: |
@@ -949,6 +980,8 @@ int dpm_suspend(pm_message_t state) | |||
949 | */ | 980 | */ |
950 | static int device_prepare(struct device *dev, pm_message_t state) | 981 | static int device_prepare(struct device *dev, pm_message_t state) |
951 | { | 982 | { |
983 | int (*callback)(struct device *) = NULL; | ||
984 | char *info = NULL; | ||
952 | int error = 0; | 985 | int error = 0; |
953 | 986 | ||
954 | device_lock(dev); | 987 | device_lock(dev); |
@@ -956,25 +989,27 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
956 | dev->power.wakeup_path = device_may_wakeup(dev); | 989 | dev->power.wakeup_path = device_may_wakeup(dev); |
957 | 990 | ||
958 | if (dev->pm_domain) { | 991 | if (dev->pm_domain) { |
959 | pm_dev_dbg(dev, state, "preparing power domain "); | 992 | info = "preparing power domain "; |
960 | if (dev->pm_domain->ops.prepare) | 993 | callback = dev->pm_domain->ops.prepare; |
961 | error = dev->pm_domain->ops.prepare(dev); | ||
962 | suspend_report_result(dev->pm_domain->ops.prepare, error); | ||
963 | } else if (dev->type && dev->type->pm) { | 994 | } else if (dev->type && dev->type->pm) { |
964 | pm_dev_dbg(dev, state, "preparing type "); | 995 | info = "preparing type "; |
965 | if (dev->type->pm->prepare) | 996 | callback = dev->type->pm->prepare; |
966 | error = dev->type->pm->prepare(dev); | ||
967 | suspend_report_result(dev->type->pm->prepare, error); | ||
968 | } else if (dev->class && dev->class->pm) { | 997 | } else if (dev->class && dev->class->pm) { |
969 | pm_dev_dbg(dev, state, "preparing class "); | 998 | info = "preparing class "; |
970 | if (dev->class->pm->prepare) | 999 | callback = dev->class->pm->prepare; |
971 | error = dev->class->pm->prepare(dev); | ||
972 | suspend_report_result(dev->class->pm->prepare, error); | ||
973 | } else if (dev->bus && dev->bus->pm) { | 1000 | } else if (dev->bus && dev->bus->pm) { |
974 | pm_dev_dbg(dev, state, "preparing "); | 1001 | info = "preparing bus "; |
975 | if (dev->bus->pm->prepare) | 1002 | callback = dev->bus->pm->prepare; |
976 | error = dev->bus->pm->prepare(dev); | 1003 | } |
977 | 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); | ||
978 | } | 1013 | } |
979 | 1014 | ||
980 | device_unlock(dev); | 1015 | device_unlock(dev); |