From 0ebf2f1556d59fd88aa5d78f37b9155431e9967e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 27 Jul 2012 22:14:59 +0200 Subject: [PATCH] --- yaml --- r: 324359 b: refs/heads/master c: 689ae231afbac8979f96100b372a5a73458baaa9 h: refs/heads/master i: 324357: 2057cefc77a88741a1a0a09925816c4d63f56b7e 324355: 3aad788db1ae572b8dd702a31ccf9c7b0cbcb80b 324351: 1bcfbc7da019ee6f787e158b3b6b0ffcb0d4906a v: v3 --- [refs] | 2 +- trunk/drivers/base/platform.c | 38 ++++++++++++++++++++++++--- trunk/include/linux/platform_device.h | 4 +++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 53b88d2aacf6..ed4169eff465 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a525a3ddeaca69f405d98442ab3c0746e53168dc +refs/heads/master: 689ae231afbac8979f96100b372a5a73458baaa9 diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index a1a722502587..3f8077ce585c 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -20,9 +20,13 @@ #include #include #include +#include #include "base.h" +/* For automatically allocated device IDs */ +static DEFINE_IDA(platform_devid_ida); + #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ driver)) @@ -263,7 +267,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data); */ int platform_device_add(struct platform_device *pdev) { - int i, ret = 0; + int i, ret; if (!pdev) return -EINVAL; @@ -273,10 +277,27 @@ int platform_device_add(struct platform_device *pdev) pdev->dev.bus = &platform_bus_type; - if (pdev->id != -1) + switch (pdev->id) { + default: dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - else + break; + case PLATFORM_DEVID_NONE: dev_set_name(&pdev->dev, "%s", pdev->name); + break; + case PLATFORM_DEVID_AUTO: + /* + * Automatically allocated device ID. We mark it as such so + * that we remember it must be freed, and we append a suffix + * to avoid namespace collision with explicit IDs. + */ + ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); + if (ret < 0) + goto err_out; + pdev->id = ret; + pdev->id_auto = true; + dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id); + break; + } for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; @@ -309,6 +330,11 @@ int platform_device_add(struct platform_device *pdev) return ret; failed: + if (pdev->id_auto) { + ida_simple_remove(&platform_devid_ida, pdev->id); + pdev->id = PLATFORM_DEVID_AUTO; + } + while (--i >= 0) { struct resource *r = &pdev->resource[i]; unsigned long type = resource_type(r); @@ -317,6 +343,7 @@ int platform_device_add(struct platform_device *pdev) release_resource(r); } + err_out: return ret; } EXPORT_SYMBOL_GPL(platform_device_add); @@ -336,6 +363,11 @@ void platform_device_del(struct platform_device *pdev) if (pdev) { device_del(&pdev->dev); + if (pdev->id_auto) { + ida_simple_remove(&platform_devid_ida, pdev->id); + pdev->id = PLATFORM_DEVID_AUTO; + } + for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; unsigned long type = resource_type(r); diff --git a/trunk/include/linux/platform_device.h b/trunk/include/linux/platform_device.h index 60e9994ef405..5711e9525a2a 100644 --- a/trunk/include/linux/platform_device.h +++ b/trunk/include/linux/platform_device.h @@ -14,11 +14,15 @@ #include #include +#define PLATFORM_DEVID_NONE (-1) +#define PLATFORM_DEVID_AUTO (-2) + struct mfd_cell; struct platform_device { const char * name; int id; + bool id_auto; struct device dev; u32 num_resources; struct resource * resource;