aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-12-17 18:34:13 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2011-12-21 16:01:05 -0500
commit35cd133c6130c1eb52806808abee9d62e6854a27 (patch)
tree2f06e7f0288b9d4a3785a202f6480928113d8d5c /drivers/base
parent9cf519d1c15fa05a538c2b3963c5f3903daf765a (diff)
PM: Run the driver callback directly if the subsystem one is not there
Make the PM core execute driver PM callbacks directly if the corresponding subsystem callbacks are not present. There are three reasons for doing that. First, it reflects the behavior of drivers/base/dd.c:really_probe() that runs the driver's .probe() callback directly if the bus type's one is not defined, so this change will remove one arbitrary difference between the PM core and the remaining parts of the driver core. Second, it will allow some subsystems, whose PM callbacks don't do anything except for executing driver callbacks, to be simplified quite a bit by removing those "forward-only" callbacks. Finally, it will allow us to remove one level of indirection in the system suspend and resume code paths where it is not necessary, which is going to lead to less debug noise with initcall_debug passed in the kernel command line (messages won't be printed for driverless devices whose subsystems don't provide PM callbacks among other things). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c109
-rw-r--r--drivers/base/power/runtime.c9
2 files changed, 81 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 */
589static void device_complete(struct device *dev, pm_message_t state) 601static 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 */
950static int device_prepare(struct device *dev, pm_message_t state) 981static 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);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 8c78443bca8f..c56efd756531 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -250,6 +250,9 @@ static int rpm_idle(struct device *dev, int rpmflags)
250 else 250 else
251 callback = NULL; 251 callback = NULL;
252 252
253 if (!callback && dev->driver && dev->driver->pm)
254 callback = dev->driver->pm->runtime_idle;
255
253 if (callback) 256 if (callback)
254 __rpm_callback(callback, dev); 257 __rpm_callback(callback, dev);
255 258
@@ -413,6 +416,9 @@ static int rpm_suspend(struct device *dev, int rpmflags)
413 else 416 else
414 callback = NULL; 417 callback = NULL;
415 418
419 if (!callback && dev->driver && dev->driver->pm)
420 callback = dev->driver->pm->runtime_suspend;
421
416 retval = rpm_callback(callback, dev); 422 retval = rpm_callback(callback, dev);
417 if (retval) { 423 if (retval) {
418 __update_runtime_status(dev, RPM_ACTIVE); 424 __update_runtime_status(dev, RPM_ACTIVE);
@@ -633,6 +639,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
633 else 639 else
634 callback = NULL; 640 callback = NULL;
635 641
642 if (!callback && dev->driver && dev->driver->pm)
643 callback = dev->driver->pm->runtime_resume;
644
636 retval = rpm_callback(callback, dev); 645 retval = rpm_callback(callback, dev);
637 if (retval) { 646 if (retval) {
638 __update_runtime_status(dev, RPM_SUSPENDED); 647 __update_runtime_status(dev, RPM_SUSPENDED);