diff options
author | Len Brown <len.brown@intel.com> | 2010-08-15 01:06:31 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-08-15 01:06:31 -0400 |
commit | 95ee46aa8698f2000647dfb362400fadbb5807cf (patch) | |
tree | e5a05c7297f997e191c73091934e42e3195c0e40 /drivers/base/platform.c | |
parent | cfa806f059801dbe7e435745eb2e187c8bfe1e7f (diff) | |
parent | 92fa5bd9a946b6e7aab6764e7312e4e3d9bed295 (diff) |
Merge branch 'linus' into release
Conflicts:
drivers/acpi/debug.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r-- | drivers/base/platform.c | 123 |
1 files changed, 41 insertions, 82 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4d99c8bdfedc..c6c933f58102 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/of_device.h> | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
@@ -191,13 +192,13 @@ int platform_device_add_resources(struct platform_device *pdev, | |||
191 | { | 192 | { |
192 | struct resource *r; | 193 | struct resource *r; |
193 | 194 | ||
194 | r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); | 195 | r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); |
195 | if (r) { | 196 | if (r) { |
196 | memcpy(r, res, sizeof(struct resource) * num); | ||
197 | pdev->resource = r; | 197 | pdev->resource = r; |
198 | pdev->num_resources = num; | 198 | pdev->num_resources = num; |
199 | return 0; | ||
199 | } | 200 | } |
200 | return r ? 0 : -ENOMEM; | 201 | return -ENOMEM; |
201 | } | 202 | } |
202 | EXPORT_SYMBOL_GPL(platform_device_add_resources); | 203 | EXPORT_SYMBOL_GPL(platform_device_add_resources); |
203 | 204 | ||
@@ -344,108 +345,56 @@ void platform_device_unregister(struct platform_device *pdev) | |||
344 | EXPORT_SYMBOL_GPL(platform_device_unregister); | 345 | EXPORT_SYMBOL_GPL(platform_device_unregister); |
345 | 346 | ||
346 | /** | 347 | /** |
347 | * platform_device_register_simple - add a platform-level device and its resources | 348 | * platform_device_register_resndata - add a platform-level device with |
348 | * @name: base name of the device we're adding | 349 | * resources and platform-specific data |
349 | * @id: instance id | ||
350 | * @res: set of resources that needs to be allocated for the device | ||
351 | * @num: number of resources | ||
352 | * | 350 | * |
353 | * This function creates a simple platform device that requires minimal | ||
354 | * resource and memory management. Canned release function freeing memory | ||
355 | * allocated for the device allows drivers using such devices to be | ||
356 | * unloaded without waiting for the last reference to the device to be | ||
357 | * dropped. | ||
358 | * | ||
359 | * This interface is primarily intended for use with legacy drivers which | ||
360 | * probe hardware directly. Because such drivers create sysfs device nodes | ||
361 | * themselves, rather than letting system infrastructure handle such device | ||
362 | * enumeration tasks, they don't fully conform to the Linux driver model. | ||
363 | * In particular, when such drivers are built as modules, they can't be | ||
364 | * "hotplugged". | ||
365 | * | ||
366 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | ||
367 | */ | ||
368 | struct platform_device *platform_device_register_simple(const char *name, | ||
369 | int id, | ||
370 | const struct resource *res, | ||
371 | unsigned int num) | ||
372 | { | ||
373 | struct platform_device *pdev; | ||
374 | int retval; | ||
375 | |||
376 | pdev = platform_device_alloc(name, id); | ||
377 | if (!pdev) { | ||
378 | retval = -ENOMEM; | ||
379 | goto error; | ||
380 | } | ||
381 | |||
382 | if (num) { | ||
383 | retval = platform_device_add_resources(pdev, res, num); | ||
384 | if (retval) | ||
385 | goto error; | ||
386 | } | ||
387 | |||
388 | retval = platform_device_add(pdev); | ||
389 | if (retval) | ||
390 | goto error; | ||
391 | |||
392 | return pdev; | ||
393 | |||
394 | error: | ||
395 | platform_device_put(pdev); | ||
396 | return ERR_PTR(retval); | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(platform_device_register_simple); | ||
399 | |||
400 | /** | ||
401 | * platform_device_register_data - add a platform-level device with platform-specific data | ||
402 | * @parent: parent device for the device we're adding | 351 | * @parent: parent device for the device we're adding |
403 | * @name: base name of the device we're adding | 352 | * @name: base name of the device we're adding |
404 | * @id: instance id | 353 | * @id: instance id |
354 | * @res: set of resources that needs to be allocated for the device | ||
355 | * @num: number of resources | ||
405 | * @data: platform specific data for this platform device | 356 | * @data: platform specific data for this platform device |
406 | * @size: size of platform specific data | 357 | * @size: size of platform specific data |
407 | * | 358 | * |
408 | * This function creates a simple platform device that requires minimal | ||
409 | * resource and memory management. Canned release function freeing memory | ||
410 | * allocated for the device allows drivers using such devices to be | ||
411 | * unloaded without waiting for the last reference to the device to be | ||
412 | * dropped. | ||
413 | * | ||
414 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | 359 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. |
415 | */ | 360 | */ |
416 | struct platform_device *platform_device_register_data( | 361 | struct platform_device *__init_or_module platform_device_register_resndata( |
417 | struct device *parent, | 362 | struct device *parent, |
418 | const char *name, int id, | 363 | const char *name, int id, |
364 | const struct resource *res, unsigned int num, | ||
419 | const void *data, size_t size) | 365 | const void *data, size_t size) |
420 | { | 366 | { |
367 | int ret = -ENOMEM; | ||
421 | struct platform_device *pdev; | 368 | struct platform_device *pdev; |
422 | int retval; | ||
423 | 369 | ||
424 | pdev = platform_device_alloc(name, id); | 370 | pdev = platform_device_alloc(name, id); |
425 | if (!pdev) { | 371 | if (!pdev) |
426 | retval = -ENOMEM; | 372 | goto err; |
427 | goto error; | ||
428 | } | ||
429 | 373 | ||
430 | pdev->dev.parent = parent; | 374 | pdev->dev.parent = parent; |
431 | 375 | ||
432 | if (size) { | 376 | if (res) { |
433 | retval = platform_device_add_data(pdev, data, size); | 377 | ret = platform_device_add_resources(pdev, res, num); |
434 | if (retval) | 378 | if (ret) |
435 | goto error; | 379 | goto err; |
436 | } | 380 | } |
437 | 381 | ||
438 | retval = platform_device_add(pdev); | 382 | if (data) { |
439 | if (retval) | 383 | ret = platform_device_add_data(pdev, data, size); |
440 | goto error; | 384 | if (ret) |
385 | goto err; | ||
386 | } | ||
441 | 387 | ||
442 | return pdev; | 388 | ret = platform_device_add(pdev); |
389 | if (ret) { | ||
390 | err: | ||
391 | platform_device_put(pdev); | ||
392 | return ERR_PTR(ret); | ||
393 | } | ||
443 | 394 | ||
444 | error: | 395 | return pdev; |
445 | platform_device_put(pdev); | ||
446 | return ERR_PTR(retval); | ||
447 | } | 396 | } |
448 | EXPORT_SYMBOL_GPL(platform_device_register_data); | 397 | EXPORT_SYMBOL_GPL(platform_device_register_resndata); |
449 | 398 | ||
450 | static int platform_drv_probe(struct device *_dev) | 399 | static int platform_drv_probe(struct device *_dev) |
451 | { | 400 | { |
@@ -635,6 +584,12 @@ static struct device_attribute platform_dev_attrs[] = { | |||
635 | static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) | 584 | static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) |
636 | { | 585 | { |
637 | struct platform_device *pdev = to_platform_device(dev); | 586 | struct platform_device *pdev = to_platform_device(dev); |
587 | int rc; | ||
588 | |||
589 | /* Some devices have extra OF data and an OF-style MODALIAS */ | ||
590 | rc = of_device_uevent(dev,env); | ||
591 | if (rc != -ENODEV) | ||
592 | return rc; | ||
638 | 593 | ||
639 | add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, | 594 | add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, |
640 | (pdev->id_entry) ? pdev->id_entry->name : pdev->name); | 595 | (pdev->id_entry) ? pdev->id_entry->name : pdev->name); |
@@ -673,7 +628,11 @@ static int platform_match(struct device *dev, struct device_driver *drv) | |||
673 | struct platform_device *pdev = to_platform_device(dev); | 628 | struct platform_device *pdev = to_platform_device(dev); |
674 | struct platform_driver *pdrv = to_platform_driver(drv); | 629 | struct platform_driver *pdrv = to_platform_driver(drv); |
675 | 630 | ||
676 | /* match against the id table first */ | 631 | /* Attempt an OF style match first */ |
632 | if (of_driver_match_device(dev, drv)) | ||
633 | return 1; | ||
634 | |||
635 | /* Then try to match against the id table */ | ||
677 | if (pdrv->id_table) | 636 | if (pdrv->id_table) |
678 | return platform_match_id(pdrv->id_table, pdev) != NULL; | 637 | return platform_match_id(pdrv->id_table, pdev) != NULL; |
679 | 638 | ||