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 #include #include +#include #include #include @@ -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 @@ static int lirc_allocate_buffer(struct irctl *ir) 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"); } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 8e3894e2d2c8..51c15c050e85 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -9,7 +9,6 @@ #ifndef _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H -#define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 #include