diff options
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r-- | drivers/base/platform.c | 176 |
1 files changed, 58 insertions, 118 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index c6c933f58102..6040717b62bb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -147,7 +147,9 @@ static void platform_device_release(struct device *dev) | |||
147 | struct platform_object *pa = container_of(dev, struct platform_object, | 147 | struct platform_object *pa = container_of(dev, struct platform_object, |
148 | pdev.dev); | 148 | pdev.dev); |
149 | 149 | ||
150 | of_device_node_put(&pa->pdev.dev); | ||
150 | kfree(pa->pdev.dev.platform_data); | 151 | kfree(pa->pdev.dev.platform_data); |
152 | kfree(pa->pdev.mfd_cell); | ||
151 | kfree(pa->pdev.resource); | 153 | kfree(pa->pdev.resource); |
152 | kfree(pa); | 154 | kfree(pa); |
153 | } | 155 | } |
@@ -190,15 +192,18 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); | |||
190 | int platform_device_add_resources(struct platform_device *pdev, | 192 | int platform_device_add_resources(struct platform_device *pdev, |
191 | const struct resource *res, unsigned int num) | 193 | const struct resource *res, unsigned int num) |
192 | { | 194 | { |
193 | struct resource *r; | 195 | struct resource *r = NULL; |
194 | 196 | ||
195 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); | 197 | if (res) { |
196 | if (r) { | 198 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); |
197 | pdev->resource = r; | 199 | if (!r) |
198 | pdev->num_resources = num; | 200 | return -ENOMEM; |
199 | return 0; | ||
200 | } | 201 | } |
201 | return -ENOMEM; | 202 | |
203 | kfree(pdev->resource); | ||
204 | pdev->resource = r; | ||
205 | pdev->num_resources = num; | ||
206 | return 0; | ||
202 | } | 207 | } |
203 | EXPORT_SYMBOL_GPL(platform_device_add_resources); | 208 | EXPORT_SYMBOL_GPL(platform_device_add_resources); |
204 | 209 | ||
@@ -215,13 +220,17 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources); | |||
215 | 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, |
216 | size_t size) | 221 | size_t size) |
217 | { | 222 | { |
218 | void *d = kmemdup(data, size, GFP_KERNEL); | 223 | void *d = NULL; |
219 | 224 | ||
220 | if (d) { | 225 | if (data) { |
221 | pdev->dev.platform_data = d; | 226 | d = kmemdup(data, size, GFP_KERNEL); |
222 | return 0; | 227 | if (!d) |
228 | return -ENOMEM; | ||
223 | } | 229 | } |
224 | return -ENOMEM; | 230 | |
231 | kfree(pdev->dev.platform_data); | ||
232 | pdev->dev.platform_data = d; | ||
233 | return 0; | ||
225 | } | 234 | } |
226 | EXPORT_SYMBOL_GPL(platform_device_add_data); | 235 | EXPORT_SYMBOL_GPL(platform_device_add_data); |
227 | 236 | ||
@@ -358,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); | |||
358 | * | 367 | * |
359 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | 368 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. |
360 | */ | 369 | */ |
361 | struct platform_device *__init_or_module platform_device_register_resndata( | 370 | struct platform_device *platform_device_register_resndata( |
362 | struct device *parent, | 371 | struct device *parent, |
363 | const char *name, int id, | 372 | const char *name, int id, |
364 | const struct resource *res, unsigned int num, | 373 | const struct resource *res, unsigned int num, |
@@ -373,17 +382,13 @@ struct platform_device *__init_or_module platform_device_register_resndata( | |||
373 | 382 | ||
374 | pdev->dev.parent = parent; | 383 | pdev->dev.parent = parent; |
375 | 384 | ||
376 | if (res) { | 385 | ret = platform_device_add_resources(pdev, res, num); |
377 | ret = platform_device_add_resources(pdev, res, num); | 386 | if (ret) |
378 | if (ret) | 387 | goto err; |
379 | goto err; | ||
380 | } | ||
381 | 388 | ||
382 | if (data) { | 389 | ret = platform_device_add_data(pdev, data, size); |
383 | ret = platform_device_add_data(pdev, data, size); | 390 | if (ret) |
384 | if (ret) | 391 | goto err; |
385 | goto err; | ||
386 | } | ||
387 | 392 | ||
388 | ret = platform_device_add(pdev); | 393 | ret = platform_device_add(pdev); |
389 | if (ret) { | 394 | if (ret) { |
@@ -488,12 +493,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, | |||
488 | * if the probe was successful, and make sure any forced probes of | 493 | * if the probe was successful, and make sure any forced probes of |
489 | * new devices fail. | 494 | * new devices fail. |
490 | */ | 495 | */ |
491 | spin_lock(&platform_bus_type.p->klist_drivers.k_lock); | 496 | spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); |
492 | drv->probe = NULL; | 497 | drv->probe = NULL; |
493 | if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) | 498 | if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) |
494 | retval = -ENODEV; | 499 | retval = -ENODEV; |
495 | drv->driver.probe = platform_drv_probe_fail; | 500 | drv->driver.probe = platform_drv_probe_fail; |
496 | spin_unlock(&platform_bus_type.p->klist_drivers.k_lock); | 501 | spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); |
497 | 502 | ||
498 | if (code != retval) | 503 | if (code != retval) |
499 | platform_driver_unregister(drv); | 504 | platform_driver_unregister(drv); |
@@ -530,17 +535,13 @@ struct platform_device * __init_or_module platform_create_bundle( | |||
530 | goto err_out; | 535 | goto err_out; |
531 | } | 536 | } |
532 | 537 | ||
533 | if (res) { | 538 | error = platform_device_add_resources(pdev, res, n_res); |
534 | error = platform_device_add_resources(pdev, res, n_res); | 539 | if (error) |
535 | if (error) | 540 | goto err_pdev_put; |
536 | goto err_pdev_put; | ||
537 | } | ||
538 | 541 | ||
539 | if (data) { | 542 | error = platform_device_add_data(pdev, data, size); |
540 | error = platform_device_add_data(pdev, data, size); | 543 | if (error) |
541 | if (error) | 544 | goto err_pdev_put; |
542 | goto err_pdev_put; | ||
543 | } | ||
544 | 545 | ||
545 | error = platform_device_add(pdev); | 546 | error = platform_device_add(pdev); |
546 | if (error) | 547 | if (error) |
@@ -666,7 +667,7 @@ static int platform_legacy_resume(struct device *dev) | |||
666 | return ret; | 667 | return ret; |
667 | } | 668 | } |
668 | 669 | ||
669 | static int platform_pm_prepare(struct device *dev) | 670 | int platform_pm_prepare(struct device *dev) |
670 | { | 671 | { |
671 | struct device_driver *drv = dev->driver; | 672 | struct device_driver *drv = dev->driver; |
672 | int ret = 0; | 673 | int ret = 0; |
@@ -677,7 +678,7 @@ static int platform_pm_prepare(struct device *dev) | |||
677 | return ret; | 678 | return ret; |
678 | } | 679 | } |
679 | 680 | ||
680 | static void platform_pm_complete(struct device *dev) | 681 | void platform_pm_complete(struct device *dev) |
681 | { | 682 | { |
682 | struct device_driver *drv = dev->driver; | 683 | struct device_driver *drv = dev->driver; |
683 | 684 | ||
@@ -685,16 +686,11 @@ static void platform_pm_complete(struct device *dev) | |||
685 | drv->pm->complete(dev); | 686 | drv->pm->complete(dev); |
686 | } | 687 | } |
687 | 688 | ||
688 | #else /* !CONFIG_PM_SLEEP */ | 689 | #endif /* CONFIG_PM_SLEEP */ |
689 | |||
690 | #define platform_pm_prepare NULL | ||
691 | #define platform_pm_complete NULL | ||
692 | |||
693 | #endif /* !CONFIG_PM_SLEEP */ | ||
694 | 690 | ||
695 | #ifdef CONFIG_SUSPEND | 691 | #ifdef CONFIG_SUSPEND |
696 | 692 | ||
697 | int __weak platform_pm_suspend(struct device *dev) | 693 | int platform_pm_suspend(struct device *dev) |
698 | { | 694 | { |
699 | struct device_driver *drv = dev->driver; | 695 | struct device_driver *drv = dev->driver; |
700 | int ret = 0; | 696 | int ret = 0; |
@@ -712,7 +708,7 @@ int __weak platform_pm_suspend(struct device *dev) | |||
712 | return ret; | 708 | return ret; |
713 | } | 709 | } |
714 | 710 | ||
715 | int __weak platform_pm_suspend_noirq(struct device *dev) | 711 | int platform_pm_suspend_noirq(struct device *dev) |
716 | { | 712 | { |
717 | struct device_driver *drv = dev->driver; | 713 | struct device_driver *drv = dev->driver; |
718 | int ret = 0; | 714 | int ret = 0; |
@@ -728,7 +724,7 @@ int __weak platform_pm_suspend_noirq(struct device *dev) | |||
728 | return ret; | 724 | return ret; |
729 | } | 725 | } |
730 | 726 | ||
731 | int __weak platform_pm_resume(struct device *dev) | 727 | int platform_pm_resume(struct device *dev) |
732 | { | 728 | { |
733 | struct device_driver *drv = dev->driver; | 729 | struct device_driver *drv = dev->driver; |
734 | int ret = 0; | 730 | int ret = 0; |
@@ -746,7 +742,7 @@ int __weak platform_pm_resume(struct device *dev) | |||
746 | return ret; | 742 | return ret; |
747 | } | 743 | } |
748 | 744 | ||
749 | int __weak platform_pm_resume_noirq(struct device *dev) | 745 | int platform_pm_resume_noirq(struct device *dev) |
750 | { | 746 | { |
751 | struct device_driver *drv = dev->driver; | 747 | struct device_driver *drv = dev->driver; |
752 | int ret = 0; | 748 | int ret = 0; |
@@ -762,18 +758,11 @@ int __weak platform_pm_resume_noirq(struct device *dev) | |||
762 | return ret; | 758 | return ret; |
763 | } | 759 | } |
764 | 760 | ||
765 | #else /* !CONFIG_SUSPEND */ | 761 | #endif /* CONFIG_SUSPEND */ |
766 | |||
767 | #define platform_pm_suspend NULL | ||
768 | #define platform_pm_resume NULL | ||
769 | #define platform_pm_suspend_noirq NULL | ||
770 | #define platform_pm_resume_noirq NULL | ||
771 | |||
772 | #endif /* !CONFIG_SUSPEND */ | ||
773 | 762 | ||
774 | #ifdef CONFIG_HIBERNATION | 763 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
775 | 764 | ||
776 | static int platform_pm_freeze(struct device *dev) | 765 | int platform_pm_freeze(struct device *dev) |
777 | { | 766 | { |
778 | struct device_driver *drv = dev->driver; | 767 | struct device_driver *drv = dev->driver; |
779 | int ret = 0; | 768 | int ret = 0; |
@@ -791,7 +780,7 @@ static int platform_pm_freeze(struct device *dev) | |||
791 | return ret; | 780 | return ret; |
792 | } | 781 | } |
793 | 782 | ||
794 | static int platform_pm_freeze_noirq(struct device *dev) | 783 | int platform_pm_freeze_noirq(struct device *dev) |
795 | { | 784 | { |
796 | struct device_driver *drv = dev->driver; | 785 | struct device_driver *drv = dev->driver; |
797 | int ret = 0; | 786 | int ret = 0; |
@@ -807,7 +796,7 @@ static int platform_pm_freeze_noirq(struct device *dev) | |||
807 | return ret; | 796 | return ret; |
808 | } | 797 | } |
809 | 798 | ||
810 | static int platform_pm_thaw(struct device *dev) | 799 | int platform_pm_thaw(struct device *dev) |
811 | { | 800 | { |
812 | struct device_driver *drv = dev->driver; | 801 | struct device_driver *drv = dev->driver; |
813 | int ret = 0; | 802 | int ret = 0; |
@@ -825,7 +814,7 @@ static int platform_pm_thaw(struct device *dev) | |||
825 | return ret; | 814 | return ret; |
826 | } | 815 | } |
827 | 816 | ||
828 | static int platform_pm_thaw_noirq(struct device *dev) | 817 | int platform_pm_thaw_noirq(struct device *dev) |
829 | { | 818 | { |
830 | struct device_driver *drv = dev->driver; | 819 | struct device_driver *drv = dev->driver; |
831 | int ret = 0; | 820 | int ret = 0; |
@@ -841,7 +830,7 @@ static int platform_pm_thaw_noirq(struct device *dev) | |||
841 | return ret; | 830 | return ret; |
842 | } | 831 | } |
843 | 832 | ||
844 | static int platform_pm_poweroff(struct device *dev) | 833 | int platform_pm_poweroff(struct device *dev) |
845 | { | 834 | { |
846 | struct device_driver *drv = dev->driver; | 835 | struct device_driver *drv = dev->driver; |
847 | int ret = 0; | 836 | int ret = 0; |
@@ -859,7 +848,7 @@ static int platform_pm_poweroff(struct device *dev) | |||
859 | return ret; | 848 | return ret; |
860 | } | 849 | } |
861 | 850 | ||
862 | static int platform_pm_poweroff_noirq(struct device *dev) | 851 | int platform_pm_poweroff_noirq(struct device *dev) |
863 | { | 852 | { |
864 | struct device_driver *drv = dev->driver; | 853 | struct device_driver *drv = dev->driver; |
865 | int ret = 0; | 854 | int ret = 0; |
@@ -875,7 +864,7 @@ static int platform_pm_poweroff_noirq(struct device *dev) | |||
875 | return ret; | 864 | return ret; |
876 | } | 865 | } |
877 | 866 | ||
878 | static int platform_pm_restore(struct device *dev) | 867 | int platform_pm_restore(struct device *dev) |
879 | { | 868 | { |
880 | struct device_driver *drv = dev->driver; | 869 | struct device_driver *drv = dev->driver; |
881 | int ret = 0; | 870 | int ret = 0; |
@@ -893,7 +882,7 @@ static int platform_pm_restore(struct device *dev) | |||
893 | return ret; | 882 | return ret; |
894 | } | 883 | } |
895 | 884 | ||
896 | static int platform_pm_restore_noirq(struct device *dev) | 885 | int platform_pm_restore_noirq(struct device *dev) |
897 | { | 886 | { |
898 | struct device_driver *drv = dev->driver; | 887 | struct device_driver *drv = dev->driver; |
899 | int ret = 0; | 888 | int ret = 0; |
@@ -909,62 +898,13 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
909 | return ret; | 898 | return ret; |
910 | } | 899 | } |
911 | 900 | ||
912 | #else /* !CONFIG_HIBERNATION */ | 901 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
913 | |||
914 | #define platform_pm_freeze NULL | ||
915 | #define platform_pm_thaw NULL | ||
916 | #define platform_pm_poweroff NULL | ||
917 | #define platform_pm_restore NULL | ||
918 | #define platform_pm_freeze_noirq NULL | ||
919 | #define platform_pm_thaw_noirq NULL | ||
920 | #define platform_pm_poweroff_noirq NULL | ||
921 | #define platform_pm_restore_noirq NULL | ||
922 | |||
923 | #endif /* !CONFIG_HIBERNATION */ | ||
924 | |||
925 | #ifdef CONFIG_PM_RUNTIME | ||
926 | |||
927 | int __weak platform_pm_runtime_suspend(struct device *dev) | ||
928 | { | ||
929 | return pm_generic_runtime_suspend(dev); | ||
930 | }; | ||
931 | |||
932 | int __weak platform_pm_runtime_resume(struct device *dev) | ||
933 | { | ||
934 | return pm_generic_runtime_resume(dev); | ||
935 | }; | ||
936 | |||
937 | int __weak platform_pm_runtime_idle(struct device *dev) | ||
938 | { | ||
939 | return pm_generic_runtime_idle(dev); | ||
940 | }; | ||
941 | |||
942 | #else /* !CONFIG_PM_RUNTIME */ | ||
943 | |||
944 | #define platform_pm_runtime_suspend NULL | ||
945 | #define platform_pm_runtime_resume NULL | ||
946 | #define platform_pm_runtime_idle NULL | ||
947 | |||
948 | #endif /* !CONFIG_PM_RUNTIME */ | ||
949 | 902 | ||
950 | static const struct dev_pm_ops platform_dev_pm_ops = { | 903 | static const struct dev_pm_ops platform_dev_pm_ops = { |
951 | .prepare = platform_pm_prepare, | 904 | .runtime_suspend = pm_generic_runtime_suspend, |
952 | .complete = platform_pm_complete, | 905 | .runtime_resume = pm_generic_runtime_resume, |
953 | .suspend = platform_pm_suspend, | 906 | .runtime_idle = pm_generic_runtime_idle, |
954 | .resume = platform_pm_resume, | 907 | USE_PLATFORM_PM_SLEEP_OPS |
955 | .freeze = platform_pm_freeze, | ||
956 | .thaw = platform_pm_thaw, | ||
957 | .poweroff = platform_pm_poweroff, | ||
958 | .restore = platform_pm_restore, | ||
959 | .suspend_noirq = platform_pm_suspend_noirq, | ||
960 | .resume_noirq = platform_pm_resume_noirq, | ||
961 | .freeze_noirq = platform_pm_freeze_noirq, | ||
962 | .thaw_noirq = platform_pm_thaw_noirq, | ||
963 | .poweroff_noirq = platform_pm_poweroff_noirq, | ||
964 | .restore_noirq = platform_pm_restore_noirq, | ||
965 | .runtime_suspend = platform_pm_runtime_suspend, | ||
966 | .runtime_resume = platform_pm_runtime_resume, | ||
967 | .runtime_idle = platform_pm_runtime_idle, | ||
968 | }; | 908 | }; |
969 | 909 | ||
970 | struct bus_type platform_bus_type = { | 910 | struct bus_type platform_bus_type = { |