[PATCH 2/2] als: add unique device-ids to the als device class

From: Amit Kucheria
Date: Thu Nov 26 2009 - 07:06:36 EST


Other devices classes such as hwmon and input class handle assignment of
unique device-ids inside the core functions instead of pushing it out to
individual drivers. This reduces code duplication and resulting bugs.

Signed-off-by: Amit Kucheria <amit.kucheria@xxxxxxxxxxxxx>
Cc: Zhang Rui <rui.zhang@xxxxxxxxx>
Cc: Jonathan Cameron <jic23@xxxxxxxxx>

---
drivers/als/als_sys.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/als/als_sys.c b/drivers/als/als_sys.c
index e1d6395..aa15ad8 100644
--- a/drivers/als/als_sys.c
+++ b/drivers/als/als_sys.c
@@ -26,22 +26,55 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kdev_t.h>
+#include <linux/idr.h>

MODULE_AUTHOR("Zhang Rui <rui.zhang@xxxxxxxxx>");
MODULE_DESCRIPTION("Ambient Light Sensor sysfs/class support");
MODULE_LICENSE("GPL");

+#define ALS_ID_PREFIX "als"
+#define ALS_ID_FORMAT ALS_ID_PREFIX "%d"
+
static struct class *als_class;

+static DEFINE_IDR(als_idr);
+static DEFINE_SPINLOCK(idr_lock);
+
/**
* als_device_register - register a new Ambient Light Sensor class device
* @parent: the device to register.
*
* Returns the pointer to the new device
*/
-struct device *als_device_register(struct device *dev, char *name)
+struct device *als_device_register(struct device *dev)
{
- return device_create(als_class, dev, MKDEV(0, 0), NULL, name);
+ int id, err;
+ struct device *alsdev;
+
+again:
+ if (unlikely(idr_pre_get(&als_idr, GFP_KERNEL) == 0))
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock(&idr_lock);
+ err = idr_get_new(&als_idr, NULL, &id);
+ spin_unlock(&idr_lock);
+
+ if (unlikely(err == -EAGAIN))
+ goto again;
+ else if (unlikely(err))
+ return ERR_PTR(err);
+
+ id = id & MAX_ID_MASK;
+ alsdev = device_create(als_class, dev, MKDEV(0, 0), NULL,
+ ALS_ID_FORMAT, id);
+
+ if (IS_ERR(alsdev)) {
+ spin_lock(&idr_lock);
+ idr_remove(&als_idr, id);
+ spin_unlock(&idr_lock);
+ }
+
+ return alsdev;
}
EXPORT_SYMBOL(als_device_register);

@@ -51,7 +84,16 @@ EXPORT_SYMBOL(als_device_register);
*/
void als_device_unregister(struct device *dev)
{
- device_unregister(dev);
+ int id;
+
+ if (likely(sscanf(dev_name(dev), ALS_ID_FORMAT, &id) == 1)) {
+ device_unregister(dev);
+ spin_lock(&idr_lock);
+ idr_remove(&als_idr, id);
+ spin_unlock(&idr_lock);
+ } else
+ dev_dbg(dev->parent,
+ "als_device_unregister() failed: bad class ID!\n");
}
EXPORT_SYMBOL(als_device_unregister);

--
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/