diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/power/main.c | 37 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 19 |
2 files changed, 54 insertions, 2 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f7a755923751..05b989139b54 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -423,6 +423,11 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
423 | TRACE_DEVICE(dev); | 423 | TRACE_DEVICE(dev); |
424 | TRACE_RESUME(0); | 424 | TRACE_RESUME(0); |
425 | 425 | ||
426 | if (dev->pwr_domain) { | ||
427 | pm_dev_dbg(dev, state, "EARLY power domain "); | ||
428 | pm_noirq_op(dev, &dev->pwr_domain->ops, state); | ||
429 | } | ||
430 | |||
426 | if (dev->bus && dev->bus->pm) { | 431 | if (dev->bus && dev->bus->pm) { |
427 | pm_dev_dbg(dev, state, "EARLY "); | 432 | pm_dev_dbg(dev, state, "EARLY "); |
428 | error = pm_noirq_op(dev, dev->bus->pm, state); | 433 | error = pm_noirq_op(dev, dev->bus->pm, state); |
@@ -518,6 +523,11 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
518 | 523 | ||
519 | dev->power.in_suspend = false; | 524 | dev->power.in_suspend = false; |
520 | 525 | ||
526 | if (dev->pwr_domain) { | ||
527 | pm_dev_dbg(dev, state, "power domain "); | ||
528 | pm_op(dev, &dev->pwr_domain->ops, state); | ||
529 | } | ||
530 | |||
521 | if (dev->bus) { | 531 | if (dev->bus) { |
522 | if (dev->bus->pm) { | 532 | if (dev->bus->pm) { |
523 | pm_dev_dbg(dev, state, ""); | 533 | pm_dev_dbg(dev, state, ""); |
@@ -629,6 +639,11 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
629 | { | 639 | { |
630 | device_lock(dev); | 640 | device_lock(dev); |
631 | 641 | ||
642 | if (dev->pwr_domain && dev->pwr_domain->ops.complete) { | ||
643 | pm_dev_dbg(dev, state, "completing power domain "); | ||
644 | dev->pwr_domain->ops.complete(dev); | ||
645 | } | ||
646 | |||
632 | if (dev->class && dev->class->pm && dev->class->pm->complete) { | 647 | if (dev->class && dev->class->pm && dev->class->pm->complete) { |
633 | pm_dev_dbg(dev, state, "completing class "); | 648 | pm_dev_dbg(dev, state, "completing class "); |
634 | dev->class->pm->complete(dev); | 649 | dev->class->pm->complete(dev); |
@@ -745,6 +760,13 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) | |||
745 | if (dev->bus && dev->bus->pm) { | 760 | if (dev->bus && dev->bus->pm) { |
746 | pm_dev_dbg(dev, state, "LATE "); | 761 | pm_dev_dbg(dev, state, "LATE "); |
747 | error = pm_noirq_op(dev, dev->bus->pm, state); | 762 | error = pm_noirq_op(dev, dev->bus->pm, state); |
763 | if (error) | ||
764 | goto End; | ||
765 | } | ||
766 | |||
767 | if (dev->pwr_domain) { | ||
768 | pm_dev_dbg(dev, state, "LATE power domain "); | ||
769 | pm_noirq_op(dev, &dev->pwr_domain->ops, state); | ||
748 | } | 770 | } |
749 | 771 | ||
750 | End: | 772 | End: |
@@ -864,6 +886,13 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
864 | pm_dev_dbg(dev, state, "legacy "); | 886 | pm_dev_dbg(dev, state, "legacy "); |
865 | error = legacy_suspend(dev, state, dev->bus->suspend); | 887 | error = legacy_suspend(dev, state, dev->bus->suspend); |
866 | } | 888 | } |
889 | if (error) | ||
890 | goto End; | ||
891 | } | ||
892 | |||
893 | if (dev->pwr_domain) { | ||
894 | pm_dev_dbg(dev, state, "power domain "); | ||
895 | pm_op(dev, &dev->pwr_domain->ops, state); | ||
867 | } | 896 | } |
868 | 897 | ||
869 | End: | 898 | End: |
@@ -976,7 +1005,15 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
976 | pm_dev_dbg(dev, state, "preparing class "); | 1005 | pm_dev_dbg(dev, state, "preparing class "); |
977 | error = dev->class->pm->prepare(dev); | 1006 | error = dev->class->pm->prepare(dev); |
978 | suspend_report_result(dev->class->pm->prepare, error); | 1007 | suspend_report_result(dev->class->pm->prepare, error); |
1008 | if (error) | ||
1009 | goto End; | ||
1010 | } | ||
1011 | |||
1012 | if (dev->pwr_domain && dev->pwr_domain->ops.prepare) { | ||
1013 | pm_dev_dbg(dev, state, "preparing power domain "); | ||
1014 | dev->pwr_domain->ops.prepare(dev); | ||
979 | } | 1015 | } |
1016 | |||
980 | End: | 1017 | End: |
981 | device_unlock(dev); | 1018 | device_unlock(dev); |
982 | 1019 | ||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 42615b419dfb..25edc9a3a489 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -168,6 +168,7 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
168 | static int rpm_idle(struct device *dev, int rpmflags) | 168 | static int rpm_idle(struct device *dev, int rpmflags) |
169 | { | 169 | { |
170 | int (*callback)(struct device *); | 170 | int (*callback)(struct device *); |
171 | int (*domain_callback)(struct device *); | ||
171 | int retval; | 172 | int retval; |
172 | 173 | ||
173 | retval = rpm_check_suspend_allowed(dev); | 174 | retval = rpm_check_suspend_allowed(dev); |
@@ -222,10 +223,19 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
222 | else | 223 | else |
223 | callback = NULL; | 224 | callback = NULL; |
224 | 225 | ||
225 | if (callback) { | 226 | if (dev->pwr_domain) |
227 | domain_callback = dev->pwr_domain->ops.runtime_idle; | ||
228 | else | ||
229 | domain_callback = NULL; | ||
230 | |||
231 | if (callback || domain_callback) { | ||
226 | spin_unlock_irq(&dev->power.lock); | 232 | spin_unlock_irq(&dev->power.lock); |
227 | 233 | ||
228 | callback(dev); | 234 | if (domain_callback) |
235 | retval = domain_callback(dev); | ||
236 | |||
237 | if (!retval && callback) | ||
238 | callback(dev); | ||
229 | 239 | ||
230 | spin_lock_irq(&dev->power.lock); | 240 | spin_lock_irq(&dev->power.lock); |
231 | } | 241 | } |
@@ -390,6 +400,8 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
390 | else | 400 | else |
391 | pm_runtime_cancel_pending(dev); | 401 | pm_runtime_cancel_pending(dev); |
392 | } else { | 402 | } else { |
403 | if (dev->pwr_domain) | ||
404 | rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev); | ||
393 | no_callback: | 405 | no_callback: |
394 | __update_runtime_status(dev, RPM_SUSPENDED); | 406 | __update_runtime_status(dev, RPM_SUSPENDED); |
395 | pm_runtime_deactivate_timer(dev); | 407 | pm_runtime_deactivate_timer(dev); |
@@ -569,6 +581,9 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
569 | 581 | ||
570 | __update_runtime_status(dev, RPM_RESUMING); | 582 | __update_runtime_status(dev, RPM_RESUMING); |
571 | 583 | ||
584 | if (dev->pwr_domain) | ||
585 | rpm_callback(dev->pwr_domain->ops.runtime_resume, dev); | ||
586 | |||
572 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) | 587 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) |
573 | callback = dev->bus->pm->runtime_resume; | 588 | callback = dev->bus->pm->runtime_resume; |
574 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume) | 589 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume) |