Skip to content

Commit

Permalink
platform: Add support for automatic device IDs
Browse files Browse the repository at this point in the history
Right now we have support for explicit platform device IDs, as well as
ID-less platform devices when a given device type can only have one
instance. However there are cases where multiple instances of a device
type can exist, and their IDs aren't (and can't be) known in advance
and do not matter. In that case we need automatic device IDs to avoid
device name collisions.

I am using magic ID value -2 (PLATFORM_DEVID_AUTO) for this, similar
to -1 for ID-less devices. The automatically allocated device IDs are
global (to avoid an additional per-driver cost.) We keep note that the
ID was automatically allocated so that it can be freed later.

Note that we also restore the ID to PLATFORM_DEVID_AUTO on error and
device deletion, to avoid avoid unexpected behavior on retry. I don't
really expect retries on platform device addition, but better safe
than sorry.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jean Delvare authored and Greg Kroah-Hartman committed Aug 16, 2012
1 parent a525a3d commit 689ae23
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
38 changes: 35 additions & 3 deletions drivers/base/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/idr.h>

#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))

Expand Down Expand Up @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions include/linux/platform_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>

#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;
Expand Down

0 comments on commit 689ae23

Please sign in to comment.