diff options
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r-- | drivers/base/platform.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index c6c933f58102..3966e62ad019 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -192,6 +192,9 @@ int platform_device_add_resources(struct platform_device *pdev, | |||
192 | { | 192 | { |
193 | struct resource *r; | 193 | struct resource *r; |
194 | 194 | ||
195 | if (!res) | ||
196 | return 0; | ||
197 | |||
195 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); | 198 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); |
196 | if (r) { | 199 | if (r) { |
197 | pdev->resource = r; | 200 | pdev->resource = r; |
@@ -215,8 +218,12 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources); | |||
215 | int platform_device_add_data(struct platform_device *pdev, const void *data, | 218 | int platform_device_add_data(struct platform_device *pdev, const void *data, |
216 | size_t size) | 219 | size_t size) |
217 | { | 220 | { |
218 | void *d = kmemdup(data, size, GFP_KERNEL); | 221 | void *d; |
222 | |||
223 | if (!data) | ||
224 | return 0; | ||
219 | 225 | ||
226 | d = kmemdup(data, size, GFP_KERNEL); | ||
220 | if (d) { | 227 | if (d) { |
221 | pdev->dev.platform_data = d; | 228 | pdev->dev.platform_data = d; |
222 | return 0; | 229 | return 0; |
@@ -373,17 +380,13 @@ struct platform_device *__init_or_module platform_device_register_resndata( | |||
373 | 380 | ||
374 | pdev->dev.parent = parent; | 381 | pdev->dev.parent = parent; |
375 | 382 | ||
376 | if (res) { | 383 | ret = platform_device_add_resources(pdev, res, num); |
377 | ret = platform_device_add_resources(pdev, res, num); | 384 | if (ret) |
378 | if (ret) | 385 | goto err; |
379 | goto err; | ||
380 | } | ||
381 | 386 | ||
382 | if (data) { | 387 | ret = platform_device_add_data(pdev, data, size); |
383 | ret = platform_device_add_data(pdev, data, size); | 388 | if (ret) |
384 | if (ret) | 389 | goto err; |
385 | goto err; | ||
386 | } | ||
387 | 390 | ||
388 | ret = platform_device_add(pdev); | 391 | ret = platform_device_add(pdev); |
389 | if (ret) { | 392 | if (ret) { |
@@ -488,12 +491,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 | 491 | * if the probe was successful, and make sure any forced probes of |
489 | * new devices fail. | 492 | * new devices fail. |
490 | */ | 493 | */ |
491 | spin_lock(&platform_bus_type.p->klist_drivers.k_lock); | 494 | spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); |
492 | drv->probe = NULL; | 495 | drv->probe = NULL; |
493 | if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) | 496 | if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) |
494 | retval = -ENODEV; | 497 | retval = -ENODEV; |
495 | drv->driver.probe = platform_drv_probe_fail; | 498 | drv->driver.probe = platform_drv_probe_fail; |
496 | spin_unlock(&platform_bus_type.p->klist_drivers.k_lock); | 499 | spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); |
497 | 500 | ||
498 | if (code != retval) | 501 | if (code != retval) |
499 | platform_driver_unregister(drv); | 502 | platform_driver_unregister(drv); |
@@ -530,17 +533,13 @@ struct platform_device * __init_or_module platform_create_bundle( | |||
530 | goto err_out; | 533 | goto err_out; |
531 | } | 534 | } |
532 | 535 | ||
533 | if (res) { | 536 | error = platform_device_add_resources(pdev, res, n_res); |
534 | error = platform_device_add_resources(pdev, res, n_res); | 537 | if (error) |
535 | if (error) | 538 | goto err_pdev_put; |
536 | goto err_pdev_put; | ||
537 | } | ||
538 | 539 | ||
539 | if (data) { | 540 | error = platform_device_add_data(pdev, data, size); |
540 | error = platform_device_add_data(pdev, data, size); | 541 | if (error) |
541 | if (error) | 542 | goto err_pdev_put; |
542 | goto err_pdev_put; | ||
543 | } | ||
544 | 543 | ||
545 | error = platform_device_add(pdev); | 544 | error = platform_device_add(pdev); |
546 | if (error) | 545 | if (error) |
@@ -976,6 +975,41 @@ struct bus_type platform_bus_type = { | |||
976 | }; | 975 | }; |
977 | EXPORT_SYMBOL_GPL(platform_bus_type); | 976 | EXPORT_SYMBOL_GPL(platform_bus_type); |
978 | 977 | ||
978 | /** | ||
979 | * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops | ||
980 | * | ||
981 | * This function can be used by platform code to get the current | ||
982 | * set of dev_pm_ops functions used by the platform_bus_type. | ||
983 | */ | ||
984 | const struct dev_pm_ops * __init platform_bus_get_pm_ops(void) | ||
985 | { | ||
986 | return platform_bus_type.pm; | ||
987 | } | ||
988 | |||
989 | /** | ||
990 | * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type | ||
991 | * | ||
992 | * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type | ||
993 | * | ||
994 | * Platform code can override the dev_pm_ops methods of | ||
995 | * platform_bus_type by using this function. It is expected that | ||
996 | * platform code will first do a platform_bus_get_pm_ops(), then | ||
997 | * kmemdup it, then customize selected methods and pass a pointer to | ||
998 | * the new struct dev_pm_ops to this function. | ||
999 | * | ||
1000 | * Since platform-specific code is customizing methods for *all* | ||
1001 | * devices (not just platform-specific devices) it is expected that | ||
1002 | * any custom overrides of these functions will keep existing behavior | ||
1003 | * and simply extend it. For example, any customization of the | ||
1004 | * runtime PM methods should continue to call the pm_generic_* | ||
1005 | * functions as the default ones do in addition to the | ||
1006 | * platform-specific behavior. | ||
1007 | */ | ||
1008 | void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm) | ||
1009 | { | ||
1010 | platform_bus_type.pm = pm; | ||
1011 | } | ||
1012 | |||
979 | int __init platform_bus_init(void) | 1013 | int __init platform_bus_init(void) |
980 | { | 1014 | { |
981 | int error; | 1015 | int error; |