diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2008-10-06 16:46:05 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 13:44:29 -0500 |
commit | adf094931ffb25ef4b381559918f1a34181a5273 (patch) | |
tree | bd343d4c15b21dff6a73359fd2d82ff77e30e0d4 /drivers/base | |
parent | 238c6d54830c624f34ac9cf123ac04aebfca5013 (diff) |
PM: Simplify the new suspend/hibernation framework for devices
PM: Simplify the new suspend/hibernation framework for devices
Following the discussion at the Kernel Summit, simplify the new
device PM framework by merging 'struct pm_ops' and
'struct pm_ext_ops' and removing pointers to 'struct pm_ext_ops'
from 'struct platform_driver' and 'struct pci_driver'.
After this change, the suspend/hibernation callbacks will only
reside in 'struct device_driver' as well as at the bus type/
device class/device type level. Accordingly, PCI and platform
device drivers are now expected to put their suspend/hibernation
callbacks into the 'struct device_driver' embedded in
'struct pci_driver' or 'struct platform_driver', respectively.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@suse.cz>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/platform.c | 115 | ||||
-rw-r--r-- | drivers/base/power/main.c | 19 |
2 files changed, 70 insertions, 64 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index dfcbfe50486..6c743b6008d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -503,8 +503,6 @@ int platform_driver_register(struct platform_driver *drv) | |||
503 | drv->driver.suspend = platform_drv_suspend; | 503 | drv->driver.suspend = platform_drv_suspend; |
504 | if (drv->resume) | 504 | if (drv->resume) |
505 | drv->driver.resume = platform_drv_resume; | 505 | drv->driver.resume = platform_drv_resume; |
506 | if (drv->pm) | ||
507 | drv->driver.pm = &drv->pm->base; | ||
508 | return driver_register(&drv->driver); | 506 | return driver_register(&drv->driver); |
509 | } | 507 | } |
510 | EXPORT_SYMBOL_GPL(platform_driver_register); | 508 | EXPORT_SYMBOL_GPL(platform_driver_register); |
@@ -686,7 +684,10 @@ static int platform_pm_suspend(struct device *dev) | |||
686 | struct device_driver *drv = dev->driver; | 684 | struct device_driver *drv = dev->driver; |
687 | int ret = 0; | 685 | int ret = 0; |
688 | 686 | ||
689 | if (drv && drv->pm) { | 687 | if (!drv) |
688 | return 0; | ||
689 | |||
690 | if (drv->pm) { | ||
690 | if (drv->pm->suspend) | 691 | if (drv->pm->suspend) |
691 | ret = drv->pm->suspend(dev); | 692 | ret = drv->pm->suspend(dev); |
692 | } else { | 693 | } else { |
@@ -698,16 +699,15 @@ static int platform_pm_suspend(struct device *dev) | |||
698 | 699 | ||
699 | static int platform_pm_suspend_noirq(struct device *dev) | 700 | static int platform_pm_suspend_noirq(struct device *dev) |
700 | { | 701 | { |
701 | struct platform_driver *pdrv; | 702 | struct device_driver *drv = dev->driver; |
702 | int ret = 0; | 703 | int ret = 0; |
703 | 704 | ||
704 | if (!dev->driver) | 705 | if (!drv) |
705 | return 0; | 706 | return 0; |
706 | 707 | ||
707 | pdrv = to_platform_driver(dev->driver); | 708 | if (drv->pm) { |
708 | if (pdrv->pm) { | 709 | if (drv->pm->suspend_noirq) |
709 | if (pdrv->pm->suspend_noirq) | 710 | ret = drv->pm->suspend_noirq(dev); |
710 | ret = pdrv->pm->suspend_noirq(dev); | ||
711 | } else { | 711 | } else { |
712 | ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND); | 712 | ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND); |
713 | } | 713 | } |
@@ -720,7 +720,10 @@ static int platform_pm_resume(struct device *dev) | |||
720 | struct device_driver *drv = dev->driver; | 720 | struct device_driver *drv = dev->driver; |
721 | int ret = 0; | 721 | int ret = 0; |
722 | 722 | ||
723 | if (drv && drv->pm) { | 723 | if (!drv) |
724 | return 0; | ||
725 | |||
726 | if (drv->pm) { | ||
724 | if (drv->pm->resume) | 727 | if (drv->pm->resume) |
725 | ret = drv->pm->resume(dev); | 728 | ret = drv->pm->resume(dev); |
726 | } else { | 729 | } else { |
@@ -732,16 +735,15 @@ static int platform_pm_resume(struct device *dev) | |||
732 | 735 | ||
733 | static int platform_pm_resume_noirq(struct device *dev) | 736 | static int platform_pm_resume_noirq(struct device *dev) |
734 | { | 737 | { |
735 | struct platform_driver *pdrv; | 738 | struct device_driver *drv = dev->driver; |
736 | int ret = 0; | 739 | int ret = 0; |
737 | 740 | ||
738 | if (!dev->driver) | 741 | if (!drv) |
739 | return 0; | 742 | return 0; |
740 | 743 | ||
741 | pdrv = to_platform_driver(dev->driver); | 744 | if (drv->pm) { |
742 | if (pdrv->pm) { | 745 | if (drv->pm->resume_noirq) |
743 | if (pdrv->pm->resume_noirq) | 746 | ret = drv->pm->resume_noirq(dev); |
744 | ret = pdrv->pm->resume_noirq(dev); | ||
745 | } else { | 747 | } else { |
746 | ret = platform_legacy_resume_early(dev); | 748 | ret = platform_legacy_resume_early(dev); |
747 | } | 749 | } |
@@ -780,16 +782,15 @@ static int platform_pm_freeze(struct device *dev) | |||
780 | 782 | ||
781 | static int platform_pm_freeze_noirq(struct device *dev) | 783 | static int platform_pm_freeze_noirq(struct device *dev) |
782 | { | 784 | { |
783 | struct platform_driver *pdrv; | 785 | struct device_driver *drv = dev->driver; |
784 | int ret = 0; | 786 | int ret = 0; |
785 | 787 | ||
786 | if (!dev->driver) | 788 | if (!drv) |
787 | return 0; | 789 | return 0; |
788 | 790 | ||
789 | pdrv = to_platform_driver(dev->driver); | 791 | if (drv->pm) { |
790 | if (pdrv->pm) { | 792 | if (drv->pm->freeze_noirq) |
791 | if (pdrv->pm->freeze_noirq) | 793 | ret = drv->pm->freeze_noirq(dev); |
792 | ret = pdrv->pm->freeze_noirq(dev); | ||
793 | } else { | 794 | } else { |
794 | ret = platform_legacy_suspend_late(dev, PMSG_FREEZE); | 795 | ret = platform_legacy_suspend_late(dev, PMSG_FREEZE); |
795 | } | 796 | } |
@@ -802,7 +803,10 @@ static int platform_pm_thaw(struct device *dev) | |||
802 | struct device_driver *drv = dev->driver; | 803 | struct device_driver *drv = dev->driver; |
803 | int ret = 0; | 804 | int ret = 0; |
804 | 805 | ||
805 | if (drv && drv->pm) { | 806 | if (!drv) |
807 | return 0; | ||
808 | |||
809 | if (drv->pm) { | ||
806 | if (drv->pm->thaw) | 810 | if (drv->pm->thaw) |
807 | ret = drv->pm->thaw(dev); | 811 | ret = drv->pm->thaw(dev); |
808 | } else { | 812 | } else { |
@@ -814,16 +818,15 @@ static int platform_pm_thaw(struct device *dev) | |||
814 | 818 | ||
815 | static int platform_pm_thaw_noirq(struct device *dev) | 819 | static int platform_pm_thaw_noirq(struct device *dev) |
816 | { | 820 | { |
817 | struct platform_driver *pdrv; | 821 | struct device_driver *drv = dev->driver; |
818 | int ret = 0; | 822 | int ret = 0; |
819 | 823 | ||
820 | if (!dev->driver) | 824 | if (!drv) |
821 | return 0; | 825 | return 0; |
822 | 826 | ||
823 | pdrv = to_platform_driver(dev->driver); | 827 | if (drv->pm) { |
824 | if (pdrv->pm) { | 828 | if (drv->pm->thaw_noirq) |
825 | if (pdrv->pm->thaw_noirq) | 829 | ret = drv->pm->thaw_noirq(dev); |
826 | ret = pdrv->pm->thaw_noirq(dev); | ||
827 | } else { | 830 | } else { |
828 | ret = platform_legacy_resume_early(dev); | 831 | ret = platform_legacy_resume_early(dev); |
829 | } | 832 | } |
@@ -836,7 +839,10 @@ static int platform_pm_poweroff(struct device *dev) | |||
836 | struct device_driver *drv = dev->driver; | 839 | struct device_driver *drv = dev->driver; |
837 | int ret = 0; | 840 | int ret = 0; |
838 | 841 | ||
839 | if (drv && drv->pm) { | 842 | if (!drv) |
843 | return 0; | ||
844 | |||
845 | if (drv->pm) { | ||
840 | if (drv->pm->poweroff) | 846 | if (drv->pm->poweroff) |
841 | ret = drv->pm->poweroff(dev); | 847 | ret = drv->pm->poweroff(dev); |
842 | } else { | 848 | } else { |
@@ -848,16 +854,15 @@ static int platform_pm_poweroff(struct device *dev) | |||
848 | 854 | ||
849 | static int platform_pm_poweroff_noirq(struct device *dev) | 855 | static int platform_pm_poweroff_noirq(struct device *dev) |
850 | { | 856 | { |
851 | struct platform_driver *pdrv; | 857 | struct device_driver *drv = dev->driver; |
852 | int ret = 0; | 858 | int ret = 0; |
853 | 859 | ||
854 | if (!dev->driver) | 860 | if (!drv) |
855 | return 0; | 861 | return 0; |
856 | 862 | ||
857 | pdrv = to_platform_driver(dev->driver); | 863 | if (drv->pm) { |
858 | if (pdrv->pm) { | 864 | if (drv->pm->poweroff_noirq) |
859 | if (pdrv->pm->poweroff_noirq) | 865 | ret = drv->pm->poweroff_noirq(dev); |
860 | ret = pdrv->pm->poweroff_noirq(dev); | ||
861 | } else { | 866 | } else { |
862 | ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE); | 867 | ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE); |
863 | } | 868 | } |
@@ -870,7 +875,10 @@ static int platform_pm_restore(struct device *dev) | |||
870 | struct device_driver *drv = dev->driver; | 875 | struct device_driver *drv = dev->driver; |
871 | int ret = 0; | 876 | int ret = 0; |
872 | 877 | ||
873 | if (drv && drv->pm) { | 878 | if (!drv) |
879 | return 0; | ||
880 | |||
881 | if (drv->pm) { | ||
874 | if (drv->pm->restore) | 882 | if (drv->pm->restore) |
875 | ret = drv->pm->restore(dev); | 883 | ret = drv->pm->restore(dev); |
876 | } else { | 884 | } else { |
@@ -882,16 +890,15 @@ static int platform_pm_restore(struct device *dev) | |||
882 | 890 | ||
883 | static int platform_pm_restore_noirq(struct device *dev) | 891 | static int platform_pm_restore_noirq(struct device *dev) |
884 | { | 892 | { |
885 | struct platform_driver *pdrv; | 893 | struct device_driver *drv = dev->driver; |
886 | int ret = 0; | 894 | int ret = 0; |
887 | 895 | ||
888 | if (!dev->driver) | 896 | if (!drv) |
889 | return 0; | 897 | return 0; |
890 | 898 | ||
891 | pdrv = to_platform_driver(dev->driver); | 899 | if (drv->pm) { |
892 | if (pdrv->pm) { | 900 | if (drv->pm->restore_noirq) |
893 | if (pdrv->pm->restore_noirq) | 901 | ret = drv->pm->restore_noirq(dev); |
894 | ret = pdrv->pm->restore_noirq(dev); | ||
895 | } else { | 902 | } else { |
896 | ret = platform_legacy_resume_early(dev); | 903 | ret = platform_legacy_resume_early(dev); |
897 | } | 904 | } |
@@ -912,17 +919,15 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
912 | 919 | ||
913 | #endif /* !CONFIG_HIBERNATION */ | 920 | #endif /* !CONFIG_HIBERNATION */ |
914 | 921 | ||
915 | static struct pm_ext_ops platform_pm_ops = { | 922 | static struct dev_pm_ops platform_dev_pm_ops = { |
916 | .base = { | 923 | .prepare = platform_pm_prepare, |
917 | .prepare = platform_pm_prepare, | 924 | .complete = platform_pm_complete, |
918 | .complete = platform_pm_complete, | 925 | .suspend = platform_pm_suspend, |
919 | .suspend = platform_pm_suspend, | 926 | .resume = platform_pm_resume, |
920 | .resume = platform_pm_resume, | 927 | .freeze = platform_pm_freeze, |
921 | .freeze = platform_pm_freeze, | 928 | .thaw = platform_pm_thaw, |
922 | .thaw = platform_pm_thaw, | 929 | .poweroff = platform_pm_poweroff, |
923 | .poweroff = platform_pm_poweroff, | 930 | .restore = platform_pm_restore, |
924 | .restore = platform_pm_restore, | ||
925 | }, | ||
926 | .suspend_noirq = platform_pm_suspend_noirq, | 931 | .suspend_noirq = platform_pm_suspend_noirq, |
927 | .resume_noirq = platform_pm_resume_noirq, | 932 | .resume_noirq = platform_pm_resume_noirq, |
928 | .freeze_noirq = platform_pm_freeze_noirq, | 933 | .freeze_noirq = platform_pm_freeze_noirq, |
@@ -931,7 +936,7 @@ static struct pm_ext_ops platform_pm_ops = { | |||
931 | .restore_noirq = platform_pm_restore_noirq, | 936 | .restore_noirq = platform_pm_restore_noirq, |
932 | }; | 937 | }; |
933 | 938 | ||
934 | #define PLATFORM_PM_OPS_PTR &platform_pm_ops | 939 | #define PLATFORM_PM_OPS_PTR (&platform_dev_pm_ops) |
935 | 940 | ||
936 | #else /* !CONFIG_PM_SLEEP */ | 941 | #else /* !CONFIG_PM_SLEEP */ |
937 | 942 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 692c20ba514..a8e4dcbcaf7 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -112,7 +112,8 @@ void device_pm_remove(struct device *dev) | |||
112 | * @ops: PM operations to choose from. | 112 | * @ops: PM operations to choose from. |
113 | * @state: PM transition of the system being carried out. | 113 | * @state: PM transition of the system being carried out. |
114 | */ | 114 | */ |
115 | static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state) | 115 | static int pm_op(struct device *dev, struct dev_pm_ops *ops, |
116 | pm_message_t state) | ||
116 | { | 117 | { |
117 | int error = 0; | 118 | int error = 0; |
118 | 119 | ||
@@ -174,7 +175,7 @@ static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state) | |||
174 | * The operation is executed with interrupts disabled by the only remaining | 175 | * The operation is executed with interrupts disabled by the only remaining |
175 | * functional CPU in the system. | 176 | * functional CPU in the system. |
176 | */ | 177 | */ |
177 | static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops, | 178 | static int pm_noirq_op(struct device *dev, struct dev_pm_ops *ops, |
178 | pm_message_t state) | 179 | pm_message_t state) |
179 | { | 180 | { |
180 | int error = 0; | 181 | int error = 0; |
@@ -354,7 +355,7 @@ static int resume_device(struct device *dev, pm_message_t state) | |||
354 | if (dev->bus) { | 355 | if (dev->bus) { |
355 | if (dev->bus->pm) { | 356 | if (dev->bus->pm) { |
356 | pm_dev_dbg(dev, state, ""); | 357 | pm_dev_dbg(dev, state, ""); |
357 | error = pm_op(dev, &dev->bus->pm->base, state); | 358 | error = pm_op(dev, dev->bus->pm, state); |
358 | } else if (dev->bus->resume) { | 359 | } else if (dev->bus->resume) { |
359 | pm_dev_dbg(dev, state, "legacy "); | 360 | pm_dev_dbg(dev, state, "legacy "); |
360 | error = dev->bus->resume(dev); | 361 | error = dev->bus->resume(dev); |
@@ -451,9 +452,9 @@ static void complete_device(struct device *dev, pm_message_t state) | |||
451 | dev->type->pm->complete(dev); | 452 | dev->type->pm->complete(dev); |
452 | } | 453 | } |
453 | 454 | ||
454 | if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) { | 455 | if (dev->bus && dev->bus->pm && dev->bus->pm->complete) { |
455 | pm_dev_dbg(dev, state, "completing "); | 456 | pm_dev_dbg(dev, state, "completing "); |
456 | dev->bus->pm->base.complete(dev); | 457 | dev->bus->pm->complete(dev); |
457 | } | 458 | } |
458 | 459 | ||
459 | up(&dev->sem); | 460 | up(&dev->sem); |
@@ -624,7 +625,7 @@ static int suspend_device(struct device *dev, pm_message_t state) | |||
624 | if (dev->bus) { | 625 | if (dev->bus) { |
625 | if (dev->bus->pm) { | 626 | if (dev->bus->pm) { |
626 | pm_dev_dbg(dev, state, ""); | 627 | pm_dev_dbg(dev, state, ""); |
627 | error = pm_op(dev, &dev->bus->pm->base, state); | 628 | error = pm_op(dev, dev->bus->pm, state); |
628 | } else if (dev->bus->suspend) { | 629 | } else if (dev->bus->suspend) { |
629 | pm_dev_dbg(dev, state, "legacy "); | 630 | pm_dev_dbg(dev, state, "legacy "); |
630 | error = dev->bus->suspend(dev, state); | 631 | error = dev->bus->suspend(dev, state); |
@@ -685,10 +686,10 @@ static int prepare_device(struct device *dev, pm_message_t state) | |||
685 | 686 | ||
686 | down(&dev->sem); | 687 | down(&dev->sem); |
687 | 688 | ||
688 | if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) { | 689 | if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { |
689 | pm_dev_dbg(dev, state, "preparing "); | 690 | pm_dev_dbg(dev, state, "preparing "); |
690 | error = dev->bus->pm->base.prepare(dev); | 691 | error = dev->bus->pm->prepare(dev); |
691 | suspend_report_result(dev->bus->pm->base.prepare, error); | 692 | suspend_report_result(dev->bus->pm->prepare, error); |
692 | if (error) | 693 | if (error) |
693 | goto End; | 694 | goto End; |
694 | } | 695 | } |