diff options
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r-- | drivers/base/platform.c | 176 |
1 files changed, 40 insertions, 136 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9e0e4fc24c46..1c291af637b3 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -192,18 +192,18 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); | |||
192 | int platform_device_add_resources(struct platform_device *pdev, | 192 | int platform_device_add_resources(struct platform_device *pdev, |
193 | const struct resource *res, unsigned int num) | 193 | const struct resource *res, unsigned int num) |
194 | { | 194 | { |
195 | struct resource *r; | 195 | struct resource *r = NULL; |
196 | 196 | ||
197 | if (!res) | 197 | if (res) { |
198 | return 0; | 198 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); |
199 | 199 | if (!r) | |
200 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); | 200 | return -ENOMEM; |
201 | if (r) { | ||
202 | pdev->resource = r; | ||
203 | pdev->num_resources = num; | ||
204 | return 0; | ||
205 | } | 201 | } |
206 | return -ENOMEM; | 202 | |
203 | kfree(pdev->resource); | ||
204 | pdev->resource = r; | ||
205 | pdev->num_resources = num; | ||
206 | return 0; | ||
207 | } | 207 | } |
208 | EXPORT_SYMBOL_GPL(platform_device_add_resources); | 208 | EXPORT_SYMBOL_GPL(platform_device_add_resources); |
209 | 209 | ||
@@ -220,17 +220,17 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources); | |||
220 | int platform_device_add_data(struct platform_device *pdev, const void *data, | 220 | int platform_device_add_data(struct platform_device *pdev, const void *data, |
221 | size_t size) | 221 | size_t size) |
222 | { | 222 | { |
223 | void *d; | 223 | void *d = NULL; |
224 | 224 | ||
225 | if (!data) | 225 | if (data) { |
226 | return 0; | 226 | d = kmemdup(data, size, GFP_KERNEL); |
227 | 227 | if (!d) | |
228 | d = kmemdup(data, size, GFP_KERNEL); | 228 | return -ENOMEM; |
229 | if (d) { | ||
230 | pdev->dev.platform_data = d; | ||
231 | return 0; | ||
232 | } | 229 | } |
233 | return -ENOMEM; | 230 | |
231 | kfree(pdev->dev.platform_data); | ||
232 | pdev->dev.platform_data = d; | ||
233 | return 0; | ||
234 | } | 234 | } |
235 | EXPORT_SYMBOL_GPL(platform_device_add_data); | 235 | EXPORT_SYMBOL_GPL(platform_device_add_data); |
236 | 236 | ||
@@ -667,7 +667,7 @@ static int platform_legacy_resume(struct device *dev) | |||
667 | return ret; | 667 | return ret; |
668 | } | 668 | } |
669 | 669 | ||
670 | static int platform_pm_prepare(struct device *dev) | 670 | int platform_pm_prepare(struct device *dev) |
671 | { | 671 | { |
672 | struct device_driver *drv = dev->driver; | 672 | struct device_driver *drv = dev->driver; |
673 | int ret = 0; | 673 | int ret = 0; |
@@ -678,7 +678,7 @@ static int platform_pm_prepare(struct device *dev) | |||
678 | return ret; | 678 | return ret; |
679 | } | 679 | } |
680 | 680 | ||
681 | static void platform_pm_complete(struct device *dev) | 681 | void platform_pm_complete(struct device *dev) |
682 | { | 682 | { |
683 | struct device_driver *drv = dev->driver; | 683 | struct device_driver *drv = dev->driver; |
684 | 684 | ||
@@ -686,16 +686,11 @@ static void platform_pm_complete(struct device *dev) | |||
686 | drv->pm->complete(dev); | 686 | drv->pm->complete(dev); |
687 | } | 687 | } |
688 | 688 | ||
689 | #else /* !CONFIG_PM_SLEEP */ | 689 | #endif /* CONFIG_PM_SLEEP */ |
690 | |||
691 | #define platform_pm_prepare NULL | ||
692 | #define platform_pm_complete NULL | ||
693 | |||
694 | #endif /* !CONFIG_PM_SLEEP */ | ||
695 | 690 | ||
696 | #ifdef CONFIG_SUSPEND | 691 | #ifdef CONFIG_SUSPEND |
697 | 692 | ||
698 | int __weak platform_pm_suspend(struct device *dev) | 693 | int platform_pm_suspend(struct device *dev) |
699 | { | 694 | { |
700 | struct device_driver *drv = dev->driver; | 695 | struct device_driver *drv = dev->driver; |
701 | int ret = 0; | 696 | int ret = 0; |
@@ -713,7 +708,7 @@ int __weak platform_pm_suspend(struct device *dev) | |||
713 | return ret; | 708 | return ret; |
714 | } | 709 | } |
715 | 710 | ||
716 | int __weak platform_pm_suspend_noirq(struct device *dev) | 711 | int platform_pm_suspend_noirq(struct device *dev) |
717 | { | 712 | { |
718 | struct device_driver *drv = dev->driver; | 713 | struct device_driver *drv = dev->driver; |
719 | int ret = 0; | 714 | int ret = 0; |
@@ -729,7 +724,7 @@ int __weak platform_pm_suspend_noirq(struct device *dev) | |||
729 | return ret; | 724 | return ret; |
730 | } | 725 | } |
731 | 726 | ||
732 | int __weak platform_pm_resume(struct device *dev) | 727 | int platform_pm_resume(struct device *dev) |
733 | { | 728 | { |
734 | struct device_driver *drv = dev->driver; | 729 | struct device_driver *drv = dev->driver; |
735 | int ret = 0; | 730 | int ret = 0; |
@@ -747,7 +742,7 @@ int __weak platform_pm_resume(struct device *dev) | |||
747 | return ret; | 742 | return ret; |
748 | } | 743 | } |
749 | 744 | ||
750 | int __weak platform_pm_resume_noirq(struct device *dev) | 745 | int platform_pm_resume_noirq(struct device *dev) |
751 | { | 746 | { |
752 | struct device_driver *drv = dev->driver; | 747 | struct device_driver *drv = dev->driver; |
753 | int ret = 0; | 748 | int ret = 0; |
@@ -763,18 +758,11 @@ int __weak platform_pm_resume_noirq(struct device *dev) | |||
763 | return ret; | 758 | return ret; |
764 | } | 759 | } |
765 | 760 | ||
766 | #else /* !CONFIG_SUSPEND */ | 761 | #endif /* CONFIG_SUSPEND */ |
767 | |||
768 | #define platform_pm_suspend NULL | ||
769 | #define platform_pm_resume NULL | ||
770 | #define platform_pm_suspend_noirq NULL | ||
771 | #define platform_pm_resume_noirq NULL | ||
772 | |||
773 | #endif /* !CONFIG_SUSPEND */ | ||
774 | 762 | ||
775 | #ifdef CONFIG_HIBERNATE_CALLBACKS | 763 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
776 | 764 | ||
777 | static int platform_pm_freeze(struct device *dev) | 765 | int platform_pm_freeze(struct device *dev) |
778 | { | 766 | { |
779 | struct device_driver *drv = dev->driver; | 767 | struct device_driver *drv = dev->driver; |
780 | int ret = 0; | 768 | int ret = 0; |
@@ -792,7 +780,7 @@ static int platform_pm_freeze(struct device *dev) | |||
792 | return ret; | 780 | return ret; |
793 | } | 781 | } |
794 | 782 | ||
795 | static int platform_pm_freeze_noirq(struct device *dev) | 783 | int platform_pm_freeze_noirq(struct device *dev) |
796 | { | 784 | { |
797 | struct device_driver *drv = dev->driver; | 785 | struct device_driver *drv = dev->driver; |
798 | int ret = 0; | 786 | int ret = 0; |
@@ -808,7 +796,7 @@ static int platform_pm_freeze_noirq(struct device *dev) | |||
808 | return ret; | 796 | return ret; |
809 | } | 797 | } |
810 | 798 | ||
811 | static int platform_pm_thaw(struct device *dev) | 799 | int platform_pm_thaw(struct device *dev) |
812 | { | 800 | { |
813 | struct device_driver *drv = dev->driver; | 801 | struct device_driver *drv = dev->driver; |
814 | int ret = 0; | 802 | int ret = 0; |
@@ -826,7 +814,7 @@ static int platform_pm_thaw(struct device *dev) | |||
826 | return ret; | 814 | return ret; |
827 | } | 815 | } |
828 | 816 | ||
829 | static int platform_pm_thaw_noirq(struct device *dev) | 817 | int platform_pm_thaw_noirq(struct device *dev) |
830 | { | 818 | { |
831 | struct device_driver *drv = dev->driver; | 819 | struct device_driver *drv = dev->driver; |
832 | int ret = 0; | 820 | int ret = 0; |
@@ -842,7 +830,7 @@ static int platform_pm_thaw_noirq(struct device *dev) | |||
842 | return ret; | 830 | return ret; |
843 | } | 831 | } |
844 | 832 | ||
845 | static int platform_pm_poweroff(struct device *dev) | 833 | int platform_pm_poweroff(struct device *dev) |
846 | { | 834 | { |
847 | struct device_driver *drv = dev->driver; | 835 | struct device_driver *drv = dev->driver; |
848 | int ret = 0; | 836 | int ret = 0; |
@@ -860,7 +848,7 @@ static int platform_pm_poweroff(struct device *dev) | |||
860 | return ret; | 848 | return ret; |
861 | } | 849 | } |
862 | 850 | ||
863 | static int platform_pm_poweroff_noirq(struct device *dev) | 851 | int platform_pm_poweroff_noirq(struct device *dev) |
864 | { | 852 | { |
865 | struct device_driver *drv = dev->driver; | 853 | struct device_driver *drv = dev->driver; |
866 | int ret = 0; | 854 | int ret = 0; |
@@ -876,7 +864,7 @@ static int platform_pm_poweroff_noirq(struct device *dev) | |||
876 | return ret; | 864 | return ret; |
877 | } | 865 | } |
878 | 866 | ||
879 | static int platform_pm_restore(struct device *dev) | 867 | int platform_pm_restore(struct device *dev) |
880 | { | 868 | { |
881 | struct device_driver *drv = dev->driver; | 869 | struct device_driver *drv = dev->driver; |
882 | int ret = 0; | 870 | int ret = 0; |
@@ -894,7 +882,7 @@ static int platform_pm_restore(struct device *dev) | |||
894 | return ret; | 882 | return ret; |
895 | } | 883 | } |
896 | 884 | ||
897 | static int platform_pm_restore_noirq(struct device *dev) | 885 | int platform_pm_restore_noirq(struct device *dev) |
898 | { | 886 | { |
899 | struct device_driver *drv = dev->driver; | 887 | struct device_driver *drv = dev->driver; |
900 | int ret = 0; | 888 | int ret = 0; |
@@ -910,62 +898,13 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
910 | return ret; | 898 | return ret; |
911 | } | 899 | } |
912 | 900 | ||
913 | #else /* !CONFIG_HIBERNATE_CALLBACKS */ | 901 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
914 | |||
915 | #define platform_pm_freeze NULL | ||
916 | #define platform_pm_thaw NULL | ||
917 | #define platform_pm_poweroff NULL | ||
918 | #define platform_pm_restore NULL | ||
919 | #define platform_pm_freeze_noirq NULL | ||
920 | #define platform_pm_thaw_noirq NULL | ||
921 | #define platform_pm_poweroff_noirq NULL | ||
922 | #define platform_pm_restore_noirq NULL | ||
923 | |||
924 | #endif /* !CONFIG_HIBERNATE_CALLBACKS */ | ||
925 | |||
926 | #ifdef CONFIG_PM_RUNTIME | ||
927 | |||
928 | int __weak platform_pm_runtime_suspend(struct device *dev) | ||
929 | { | ||
930 | return pm_generic_runtime_suspend(dev); | ||
931 | }; | ||
932 | |||
933 | int __weak platform_pm_runtime_resume(struct device *dev) | ||
934 | { | ||
935 | return pm_generic_runtime_resume(dev); | ||
936 | }; | ||
937 | |||
938 | int __weak platform_pm_runtime_idle(struct device *dev) | ||
939 | { | ||
940 | return pm_generic_runtime_idle(dev); | ||
941 | }; | ||
942 | |||
943 | #else /* !CONFIG_PM_RUNTIME */ | ||
944 | |||
945 | #define platform_pm_runtime_suspend NULL | ||
946 | #define platform_pm_runtime_resume NULL | ||
947 | #define platform_pm_runtime_idle NULL | ||
948 | |||
949 | #endif /* !CONFIG_PM_RUNTIME */ | ||
950 | 902 | ||
951 | static const struct dev_pm_ops platform_dev_pm_ops = { | 903 | static const struct dev_pm_ops platform_dev_pm_ops = { |
952 | .prepare = platform_pm_prepare, | 904 | .runtime_suspend = pm_generic_runtime_suspend, |
953 | .complete = platform_pm_complete, | 905 | .runtime_resume = pm_generic_runtime_resume, |
954 | .suspend = platform_pm_suspend, | 906 | .runtime_idle = pm_generic_runtime_idle, |
955 | .resume = platform_pm_resume, | 907 | USE_PLATFORM_PM_SLEEP_OPS |
956 | .freeze = platform_pm_freeze, | ||
957 | .thaw = platform_pm_thaw, | ||
958 | .poweroff = platform_pm_poweroff, | ||
959 | .restore = platform_pm_restore, | ||
960 | .suspend_noirq = platform_pm_suspend_noirq, | ||
961 | .resume_noirq = platform_pm_resume_noirq, | ||
962 | .freeze_noirq = platform_pm_freeze_noirq, | ||
963 | .thaw_noirq = platform_pm_thaw_noirq, | ||
964 | .poweroff_noirq = platform_pm_poweroff_noirq, | ||
965 | .restore_noirq = platform_pm_restore_noirq, | ||
966 | .runtime_suspend = platform_pm_runtime_suspend, | ||
967 | .runtime_resume = platform_pm_runtime_resume, | ||
968 | .runtime_idle = platform_pm_runtime_idle, | ||
969 | }; | 908 | }; |
970 | 909 | ||
971 | struct bus_type platform_bus_type = { | 910 | struct bus_type platform_bus_type = { |
@@ -977,41 +916,6 @@ struct bus_type platform_bus_type = { | |||
977 | }; | 916 | }; |
978 | EXPORT_SYMBOL_GPL(platform_bus_type); | 917 | EXPORT_SYMBOL_GPL(platform_bus_type); |
979 | 918 | ||
980 | /** | ||
981 | * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops | ||
982 | * | ||
983 | * This function can be used by platform code to get the current | ||
984 | * set of dev_pm_ops functions used by the platform_bus_type. | ||
985 | */ | ||
986 | const struct dev_pm_ops * __init platform_bus_get_pm_ops(void) | ||
987 | { | ||
988 | return platform_bus_type.pm; | ||
989 | } | ||
990 | |||
991 | /** | ||
992 | * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type | ||
993 | * | ||
994 | * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type | ||
995 | * | ||
996 | * Platform code can override the dev_pm_ops methods of | ||
997 | * platform_bus_type by using this function. It is expected that | ||
998 | * platform code will first do a platform_bus_get_pm_ops(), then | ||
999 | * kmemdup it, then customize selected methods and pass a pointer to | ||
1000 | * the new struct dev_pm_ops to this function. | ||
1001 | * | ||
1002 | * Since platform-specific code is customizing methods for *all* | ||
1003 | * devices (not just platform-specific devices) it is expected that | ||
1004 | * any custom overrides of these functions will keep existing behavior | ||
1005 | * and simply extend it. For example, any customization of the | ||
1006 | * runtime PM methods should continue to call the pm_generic_* | ||
1007 | * functions as the default ones do in addition to the | ||
1008 | * platform-specific behavior. | ||
1009 | */ | ||
1010 | void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm) | ||
1011 | { | ||
1012 | platform_bus_type.pm = pm; | ||
1013 | } | ||
1014 | |||
1015 | int __init platform_bus_init(void) | 919 | int __init platform_bus_init(void) |
1016 | { | 920 | { |
1017 | int error; | 921 | int error; |