summaryrefslogtreecommitdiff
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2017-06-25 09:32:05 -0300
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2017-10-04 14:03:21 -0300
commit46c8f4771154eb0dc21f5f2bc2640a33e8fe1d02 (patch)
treeceb3f9342ccff3441735eddd94bdb54a891b2508 /drivers/media/rc
parent3381b779a736f4908a64b603ce339ab067e01de7 (diff)
[media] media: lirc_dev: use an IDA instead of an array to keep track of registered devices
Using the kernel-provided IDA simplifies the code and makes it possible to remove the lirc_dev_lock mutex. Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/lirc_dev.c36
1 files changed, 12 insertions, 24 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index c83fffec0681..a2c5ed0181c1 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -24,6 +24,7 @@
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/cdev.h>
+#include <linux/idr.h>
#include <media/rc-core.h>
#include <media/lirc.h>
@@ -46,10 +47,9 @@ struct irctl {
struct cdev cdev;
};
-/* This mutex protects the irctls array */
-static DEFINE_MUTEX(lirc_dev_lock);
-
-static struct irctl *irctls[MAX_IRCTL_DEVICES];
+/* Used to keep track of allocated lirc devices */
+#define LIRC_MAX_DEVICES 256
+static DEFINE_IDA(lirc_ida);
/* Only used for sysfs but defined to void otherwise */
static struct class *lirc_class;
@@ -69,9 +69,6 @@ static void lirc_release(struct device *ld)
{
struct irctl *ir = container_of(ld, struct irctl, dev);
- mutex_lock(&lirc_dev_lock);
- irctls[ir->d.minor] = NULL;
- mutex_unlock(&lirc_dev_lock);
lirc_free_buffer(ir);
kfree(ir);
}
@@ -109,7 +106,7 @@ out:
int lirc_register_driver(struct lirc_driver *d)
{
struct irctl *ir;
- unsigned int minor;
+ int minor;
int err;
if (!d) {
@@ -171,28 +168,17 @@ int lirc_register_driver(struct lirc_driver *d)
d->rbuf = ir->buf;
}
- mutex_lock(&lirc_dev_lock);
-
- /* find first free slot for driver */
- for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
- if (!irctls[minor])
- break;
-
- if (minor == MAX_IRCTL_DEVICES) {
- dev_err(d->dev, "no free slots for drivers!\n");
- mutex_unlock(&lirc_dev_lock);
+ minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
+ if (minor < 0) {
lirc_free_buffer(ir);
kfree(ir);
- return -ENOMEM;
+ return minor;
}
- irctls[minor] = ir;
d->irctl = ir;
d->minor = minor;
ir->d.minor = minor;
- mutex_unlock(&lirc_dev_lock);
-
device_initialize(&ir->dev);
ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor);
ir->dev.class = lirc_class;
@@ -206,6 +192,7 @@ int lirc_register_driver(struct lirc_driver *d)
err = cdev_device_add(&ir->cdev, &ir->dev);
if (err) {
+ ida_simple_remove(&lirc_ida, minor);
put_device(&ir->dev);
return err;
}
@@ -244,6 +231,7 @@ void lirc_unregister_driver(struct lirc_driver *d)
mutex_unlock(&ir->mutex);
+ ida_simple_remove(&lirc_ida, d->minor);
put_device(&ir->dev);
}
EXPORT_SYMBOL(lirc_unregister_driver);
@@ -540,7 +528,7 @@ static int __init lirc_dev_init(void)
return PTR_ERR(lirc_class);
}
- retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
+ retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES,
"BaseRemoteCtl");
if (retval) {
class_destroy(lirc_class);
@@ -557,7 +545,7 @@ static int __init lirc_dev_init(void)
static void __exit lirc_dev_exit(void)
{
class_destroy(lirc_class);
- unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
+ unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES);
pr_info("module unloaded\n");
}