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 | |
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>
-rw-r--r-- | drivers/base/platform.c | 115 | ||||
-rw-r--r-- | drivers/base/power/main.c | 19 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 46 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 4 | ||||
-rw-r--r-- | include/linux/device.h | 8 | ||||
-rw-r--r-- | include/linux/pci.h | 1 | ||||
-rw-r--r-- | include/linux/platform_device.h | 1 | ||||
-rw-r--r-- | include/linux/pm.h | 76 |
8 files changed, 119 insertions, 151 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index dfcbfe504867..6c743b6008d9 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 692c20ba5144..a8e4dcbcaf7a 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 | } |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b4cdd690ae71..4042d211c3e5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -433,8 +433,7 @@ static int pci_pm_suspend(struct device *dev) | |||
433 | 433 | ||
434 | static int pci_pm_suspend_noirq(struct device *dev) | 434 | static int pci_pm_suspend_noirq(struct device *dev) |
435 | { | 435 | { |
436 | struct pci_dev *pci_dev = to_pci_dev(dev); | 436 | struct device_driver *drv = dev->driver; |
437 | struct pci_driver *drv = pci_dev->driver; | ||
438 | int error = 0; | 437 | int error = 0; |
439 | 438 | ||
440 | if (drv && drv->pm) { | 439 | if (drv && drv->pm) { |
@@ -469,11 +468,10 @@ static int pci_pm_resume(struct device *dev) | |||
469 | 468 | ||
470 | static int pci_pm_resume_noirq(struct device *dev) | 469 | static int pci_pm_resume_noirq(struct device *dev) |
471 | { | 470 | { |
472 | struct pci_dev *pci_dev = to_pci_dev(dev); | 471 | struct device_driver *drv = dev->driver; |
473 | struct pci_driver *drv = pci_dev->driver; | ||
474 | int error = 0; | 472 | int error = 0; |
475 | 473 | ||
476 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 474 | pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev)); |
477 | 475 | ||
478 | if (drv && drv->pm) { | 476 | if (drv && drv->pm) { |
479 | if (drv->pm->resume_noirq) | 477 | if (drv->pm->resume_noirq) |
@@ -519,8 +517,7 @@ static int pci_pm_freeze(struct device *dev) | |||
519 | 517 | ||
520 | static int pci_pm_freeze_noirq(struct device *dev) | 518 | static int pci_pm_freeze_noirq(struct device *dev) |
521 | { | 519 | { |
522 | struct pci_dev *pci_dev = to_pci_dev(dev); | 520 | struct device_driver *drv = dev->driver; |
523 | struct pci_driver *drv = pci_dev->driver; | ||
524 | int error = 0; | 521 | int error = 0; |
525 | 522 | ||
526 | if (drv && drv->pm) { | 523 | if (drv && drv->pm) { |
@@ -553,15 +550,14 @@ static int pci_pm_thaw(struct device *dev) | |||
553 | 550 | ||
554 | static int pci_pm_thaw_noirq(struct device *dev) | 551 | static int pci_pm_thaw_noirq(struct device *dev) |
555 | { | 552 | { |
556 | struct pci_dev *pci_dev = to_pci_dev(dev); | 553 | struct device_driver *drv = dev->driver; |
557 | struct pci_driver *drv = pci_dev->driver; | ||
558 | int error = 0; | 554 | int error = 0; |
559 | 555 | ||
560 | if (drv && drv->pm) { | 556 | if (drv && drv->pm) { |
561 | if (drv->pm->thaw_noirq) | 557 | if (drv->pm->thaw_noirq) |
562 | error = drv->pm->thaw_noirq(dev); | 558 | error = drv->pm->thaw_noirq(dev); |
563 | } else { | 559 | } else { |
564 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 560 | pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev)); |
565 | error = pci_legacy_resume_early(dev); | 561 | error = pci_legacy_resume_early(dev); |
566 | } | 562 | } |
567 | 563 | ||
@@ -589,8 +585,7 @@ static int pci_pm_poweroff(struct device *dev) | |||
589 | 585 | ||
590 | static int pci_pm_poweroff_noirq(struct device *dev) | 586 | static int pci_pm_poweroff_noirq(struct device *dev) |
591 | { | 587 | { |
592 | struct pci_dev *pci_dev = to_pci_dev(dev); | 588 | struct device_driver *drv = dev->driver; |
593 | struct pci_driver *drv = pci_dev->driver; | ||
594 | int error = 0; | 589 | int error = 0; |
595 | 590 | ||
596 | if (drv && drv->pm) { | 591 | if (drv && drv->pm) { |
@@ -625,7 +620,7 @@ static int pci_pm_restore(struct device *dev) | |||
625 | static int pci_pm_restore_noirq(struct device *dev) | 620 | static int pci_pm_restore_noirq(struct device *dev) |
626 | { | 621 | { |
627 | struct pci_dev *pci_dev = to_pci_dev(dev); | 622 | struct pci_dev *pci_dev = to_pci_dev(dev); |
628 | struct pci_driver *drv = pci_dev->driver; | 623 | struct device_driver *drv = dev->driver; |
629 | int error = 0; | 624 | int error = 0; |
630 | 625 | ||
631 | pci_fixup_device(pci_fixup_resume, pci_dev); | 626 | pci_fixup_device(pci_fixup_resume, pci_dev); |
@@ -654,17 +649,15 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
654 | 649 | ||
655 | #endif /* !CONFIG_HIBERNATION */ | 650 | #endif /* !CONFIG_HIBERNATION */ |
656 | 651 | ||
657 | struct pm_ext_ops pci_pm_ops = { | 652 | struct dev_pm_ops pci_dev_pm_ops = { |
658 | .base = { | 653 | .prepare = pci_pm_prepare, |
659 | .prepare = pci_pm_prepare, | 654 | .complete = pci_pm_complete, |
660 | .complete = pci_pm_complete, | 655 | .suspend = pci_pm_suspend, |
661 | .suspend = pci_pm_suspend, | 656 | .resume = pci_pm_resume, |
662 | .resume = pci_pm_resume, | 657 | .freeze = pci_pm_freeze, |
663 | .freeze = pci_pm_freeze, | 658 | .thaw = pci_pm_thaw, |
664 | .thaw = pci_pm_thaw, | 659 | .poweroff = pci_pm_poweroff, |
665 | .poweroff = pci_pm_poweroff, | 660 | .restore = pci_pm_restore, |
666 | .restore = pci_pm_restore, | ||
667 | }, | ||
668 | .suspend_noirq = pci_pm_suspend_noirq, | 661 | .suspend_noirq = pci_pm_suspend_noirq, |
669 | .resume_noirq = pci_pm_resume_noirq, | 662 | .resume_noirq = pci_pm_resume_noirq, |
670 | .freeze_noirq = pci_pm_freeze_noirq, | 663 | .freeze_noirq = pci_pm_freeze_noirq, |
@@ -673,7 +666,7 @@ struct pm_ext_ops pci_pm_ops = { | |||
673 | .restore_noirq = pci_pm_restore_noirq, | 666 | .restore_noirq = pci_pm_restore_noirq, |
674 | }; | 667 | }; |
675 | 668 | ||
676 | #define PCI_PM_OPS_PTR &pci_pm_ops | 669 | #define PCI_PM_OPS_PTR (&pci_dev_pm_ops) |
677 | 670 | ||
678 | #else /* !CONFIG_PM_SLEEP */ | 671 | #else /* !CONFIG_PM_SLEEP */ |
679 | 672 | ||
@@ -703,9 +696,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
703 | drv->driver.owner = owner; | 696 | drv->driver.owner = owner; |
704 | drv->driver.mod_name = mod_name; | 697 | drv->driver.mod_name = mod_name; |
705 | 698 | ||
706 | if (drv->pm) | ||
707 | drv->driver.pm = &drv->pm->base; | ||
708 | |||
709 | spin_lock_init(&drv->dynids.lock); | 699 | spin_lock_init(&drv->dynids.lock); |
710 | INIT_LIST_HEAD(&drv->dynids.list); | 700 | INIT_LIST_HEAD(&drv->dynids.list); |
711 | 701 | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index be1fa0723f2c..399e15fc5052 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -286,7 +286,7 @@ static int usb_dev_restore(struct device *dev) | |||
286 | return usb_resume(dev); | 286 | return usb_resume(dev); |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct pm_ops usb_device_pm_ops = { | 289 | static struct dev_pm_ops usb_device_pm_ops = { |
290 | .prepare = usb_dev_prepare, | 290 | .prepare = usb_dev_prepare, |
291 | .complete = usb_dev_complete, | 291 | .complete = usb_dev_complete, |
292 | .suspend = usb_dev_suspend, | 292 | .suspend = usb_dev_suspend, |
@@ -301,7 +301,7 @@ static struct pm_ops usb_device_pm_ops = { | |||
301 | 301 | ||
302 | #define ksuspend_usb_init() 0 | 302 | #define ksuspend_usb_init() 0 |
303 | #define ksuspend_usb_cleanup() do {} while (0) | 303 | #define ksuspend_usb_cleanup() do {} while (0) |
304 | #define usb_device_pm_ops (*(struct pm_ops *)0) | 304 | #define usb_device_pm_ops (*(struct dev_pm_ops *)0) |
305 | 305 | ||
306 | #endif /* CONFIG_PM */ | 306 | #endif /* CONFIG_PM */ |
307 | 307 | ||
diff --git a/include/linux/device.h b/include/linux/device.h index 1a3686d15f98..4a520051c315 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -65,7 +65,7 @@ struct bus_type { | |||
65 | int (*resume_early)(struct device *dev); | 65 | int (*resume_early)(struct device *dev); |
66 | int (*resume)(struct device *dev); | 66 | int (*resume)(struct device *dev); |
67 | 67 | ||
68 | struct pm_ext_ops *pm; | 68 | struct dev_pm_ops *pm; |
69 | 69 | ||
70 | struct bus_type_private *p; | 70 | struct bus_type_private *p; |
71 | }; | 71 | }; |
@@ -133,7 +133,7 @@ struct device_driver { | |||
133 | int (*resume) (struct device *dev); | 133 | int (*resume) (struct device *dev); |
134 | struct attribute_group **groups; | 134 | struct attribute_group **groups; |
135 | 135 | ||
136 | struct pm_ops *pm; | 136 | struct dev_pm_ops *pm; |
137 | 137 | ||
138 | struct driver_private *p; | 138 | struct driver_private *p; |
139 | }; | 139 | }; |
@@ -198,7 +198,7 @@ struct class { | |||
198 | int (*suspend)(struct device *dev, pm_message_t state); | 198 | int (*suspend)(struct device *dev, pm_message_t state); |
199 | int (*resume)(struct device *dev); | 199 | int (*resume)(struct device *dev); |
200 | 200 | ||
201 | struct pm_ops *pm; | 201 | struct dev_pm_ops *pm; |
202 | struct class_private *p; | 202 | struct class_private *p; |
203 | }; | 203 | }; |
204 | 204 | ||
@@ -291,7 +291,7 @@ struct device_type { | |||
291 | int (*suspend)(struct device *dev, pm_message_t state); | 291 | int (*suspend)(struct device *dev, pm_message_t state); |
292 | int (*resume)(struct device *dev); | 292 | int (*resume)(struct device *dev); |
293 | 293 | ||
294 | struct pm_ops *pm; | 294 | struct dev_pm_ops *pm; |
295 | }; | 295 | }; |
296 | 296 | ||
297 | /* interface for exporting device attributes */ | 297 | /* interface for exporting device attributes */ |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 03b0b8c3c81b..4bb156ba854a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -421,7 +421,6 @@ struct pci_driver { | |||
421 | int (*resume_early) (struct pci_dev *dev); | 421 | int (*resume_early) (struct pci_dev *dev); |
422 | int (*resume) (struct pci_dev *dev); /* Device woken up */ | 422 | int (*resume) (struct pci_dev *dev); /* Device woken up */ |
423 | void (*shutdown) (struct pci_dev *dev); | 423 | void (*shutdown) (struct pci_dev *dev); |
424 | struct pm_ext_ops *pm; | ||
425 | struct pci_error_handlers *err_handler; | 424 | struct pci_error_handlers *err_handler; |
426 | struct device_driver driver; | 425 | struct device_driver driver; |
427 | struct pci_dynids dynids; | 426 | struct pci_dynids dynids; |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 4b8cc6a32479..9a342699c607 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
@@ -55,7 +55,6 @@ struct platform_driver { | |||
55 | int (*suspend_late)(struct platform_device *, pm_message_t state); | 55 | int (*suspend_late)(struct platform_device *, pm_message_t state); |
56 | int (*resume_early)(struct platform_device *); | 56 | int (*resume_early)(struct platform_device *); |
57 | int (*resume)(struct platform_device *); | 57 | int (*resume)(struct platform_device *); |
58 | struct pm_ext_ops *pm; | ||
59 | struct device_driver driver; | 58 | struct device_driver driver; |
60 | }; | 59 | }; |
61 | 60 | ||
diff --git a/include/linux/pm.h b/include/linux/pm.h index 42de4003c4ee..5785666d0cc4 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -41,7 +41,7 @@ typedef struct pm_message { | |||
41 | } pm_message_t; | 41 | } pm_message_t; |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * struct pm_ops - device PM callbacks | 44 | * struct dev_pm_ops - device PM callbacks |
45 | * | 45 | * |
46 | * Several driver power state transitions are externally visible, affecting | 46 | * Several driver power state transitions are externally visible, affecting |
47 | * the state of pending I/O queues and (for drivers that touch hardware) | 47 | * the state of pending I/O queues and (for drivers that touch hardware) |
@@ -126,46 +126,6 @@ typedef struct pm_message { | |||
126 | * On most platforms, there are no restrictions on availability of | 126 | * On most platforms, there are no restrictions on availability of |
127 | * resources like clocks during @restore(). | 127 | * resources like clocks during @restore(). |
128 | * | 128 | * |
129 | * All of the above callbacks, except for @complete(), return error codes. | ||
130 | * However, the error codes returned by the resume operations, @resume(), | ||
131 | * @thaw(), and @restore(), do not cause the PM core to abort the resume | ||
132 | * transition during which they are returned. The error codes returned in | ||
133 | * that cases are only printed by the PM core to the system logs for debugging | ||
134 | * purposes. Still, it is recommended that drivers only return error codes | ||
135 | * from their resume methods in case of an unrecoverable failure (i.e. when the | ||
136 | * device being handled refuses to resume and becomes unusable) to allow us to | ||
137 | * modify the PM core in the future, so that it can avoid attempting to handle | ||
138 | * devices that failed to resume and their children. | ||
139 | * | ||
140 | * It is allowed to unregister devices while the above callbacks are being | ||
141 | * executed. However, it is not allowed to unregister a device from within any | ||
142 | * of its own callbacks. | ||
143 | */ | ||
144 | |||
145 | struct pm_ops { | ||
146 | int (*prepare)(struct device *dev); | ||
147 | void (*complete)(struct device *dev); | ||
148 | int (*suspend)(struct device *dev); | ||
149 | int (*resume)(struct device *dev); | ||
150 | int (*freeze)(struct device *dev); | ||
151 | int (*thaw)(struct device *dev); | ||
152 | int (*poweroff)(struct device *dev); | ||
153 | int (*restore)(struct device *dev); | ||
154 | }; | ||
155 | |||
156 | /** | ||
157 | * struct pm_ext_ops - extended device PM callbacks | ||
158 | * | ||
159 | * Some devices require certain operations related to suspend and hibernation | ||
160 | * to be carried out with interrupts disabled. Thus, 'struct pm_ext_ops' below | ||
161 | * is defined, adding callbacks to be executed with interrupts disabled to | ||
162 | * 'struct pm_ops'. | ||
163 | * | ||
164 | * The following callbacks included in 'struct pm_ext_ops' are executed with | ||
165 | * the nonboot CPUs switched off and with interrupts disabled on the only | ||
166 | * functional CPU. They also are executed with the PM core list of devices | ||
167 | * locked, so they must NOT unregister any devices. | ||
168 | * | ||
169 | * @suspend_noirq: Complete the operations of ->suspend() by carrying out any | 129 | * @suspend_noirq: Complete the operations of ->suspend() by carrying out any |
170 | * actions required for suspending the device that need interrupts to be | 130 | * actions required for suspending the device that need interrupts to be |
171 | * disabled | 131 | * disabled |
@@ -190,18 +150,32 @@ struct pm_ops { | |||
190 | * actions required for restoring the operations of the device that need | 150 | * actions required for restoring the operations of the device that need |
191 | * interrupts to be disabled | 151 | * interrupts to be disabled |
192 | * | 152 | * |
193 | * All of the above callbacks return error codes, but the error codes returned | 153 | * All of the above callbacks, except for @complete(), return error codes. |
194 | * by the resume operations, @resume_noirq(), @thaw_noirq(), and | 154 | * However, the error codes returned by the resume operations, @resume(), |
195 | * @restore_noirq(), do not cause the PM core to abort the resume transition | 155 | * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq() do |
196 | * during which they are returned. The error codes returned in that cases are | 156 | * not cause the PM core to abort the resume transition during which they are |
197 | * only printed by the PM core to the system logs for debugging purposes. | 157 | * returned. The error codes returned in that cases are only printed by the PM |
198 | * Still, as stated above, it is recommended that drivers only return error | 158 | * core to the system logs for debugging purposes. Still, it is recommended |
199 | * codes from their resume methods if the device being handled fails to resume | 159 | * that drivers only return error codes from their resume methods in case of an |
200 | * and is not usable any more. | 160 | * unrecoverable failure (i.e. when the device being handled refuses to resume |
161 | * and becomes unusable) to allow us to modify the PM core in the future, so | ||
162 | * that it can avoid attempting to handle devices that failed to resume and | ||
163 | * their children. | ||
164 | * | ||
165 | * It is allowed to unregister devices while the above callbacks are being | ||
166 | * executed. However, it is not allowed to unregister a device from within any | ||
167 | * of its own callbacks. | ||
201 | */ | 168 | */ |
202 | 169 | ||
203 | struct pm_ext_ops { | 170 | struct dev_pm_ops { |
204 | struct pm_ops base; | 171 | int (*prepare)(struct device *dev); |
172 | void (*complete)(struct device *dev); | ||
173 | int (*suspend)(struct device *dev); | ||
174 | int (*resume)(struct device *dev); | ||
175 | int (*freeze)(struct device *dev); | ||
176 | int (*thaw)(struct device *dev); | ||
177 | int (*poweroff)(struct device *dev); | ||
178 | int (*restore)(struct device *dev); | ||
205 | int (*suspend_noirq)(struct device *dev); | 179 | int (*suspend_noirq)(struct device *dev); |
206 | int (*resume_noirq)(struct device *dev); | 180 | int (*resume_noirq)(struct device *dev); |
207 | int (*freeze_noirq)(struct device *dev); | 181 | int (*freeze_noirq)(struct device *dev); |