diff options
author | David Härdeman <david@hardeman.nu> | 2017-06-25 08:32:05 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2017-10-04 13:03:21 -0400 |
commit | 46c8f4771154eb0dc21f5f2bc2640a33e8fe1d02 (patch) | |
tree | ceb3f9342ccff3441735eddd94bdb54a891b2508 /drivers/media/rc/lirc_dev.c | |
parent | 3381b779a736f4908a64b603ce339ab067e01de7 (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/lirc_dev.c')
-rw-r--r-- | drivers/media/rc/lirc_dev.c | 36 |
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 @@ | |||
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/cdev.h> | 26 | #include <linux/cdev.h> |
27 | #include <linux/idr.h> | ||
27 | 28 | ||
28 | #include <media/rc-core.h> | 29 | #include <media/rc-core.h> |
29 | #include <media/lirc.h> | 30 | #include <media/lirc.h> |
@@ -46,10 +47,9 @@ struct irctl { | |||
46 | struct cdev cdev; | 47 | struct cdev cdev; |
47 | }; | 48 | }; |
48 | 49 | ||
49 | /* This mutex protects the irctls array */ | 50 | /* Used to keep track of allocated lirc devices */ |
50 | static DEFINE_MUTEX(lirc_dev_lock); | 51 | #define LIRC_MAX_DEVICES 256 |
51 | 52 | static DEFINE_IDA(lirc_ida); | |
52 | static struct irctl *irctls[MAX_IRCTL_DEVICES]; | ||
53 | 53 | ||
54 | /* Only used for sysfs but defined to void otherwise */ | 54 | /* Only used for sysfs but defined to void otherwise */ |
55 | static struct class *lirc_class; | 55 | static struct class *lirc_class; |
@@ -69,9 +69,6 @@ static void lirc_release(struct device *ld) | |||
69 | { | 69 | { |
70 | struct irctl *ir = container_of(ld, struct irctl, dev); | 70 | struct irctl *ir = container_of(ld, struct irctl, dev); |
71 | 71 | ||
72 | mutex_lock(&lirc_dev_lock); | ||
73 | irctls[ir->d.minor] = NULL; | ||
74 | mutex_unlock(&lirc_dev_lock); | ||
75 | lirc_free_buffer(ir); | 72 | lirc_free_buffer(ir); |
76 | kfree(ir); | 73 | kfree(ir); |
77 | } | 74 | } |
@@ -109,7 +106,7 @@ out: | |||
109 | int lirc_register_driver(struct lirc_driver *d) | 106 | int lirc_register_driver(struct lirc_driver *d) |
110 | { | 107 | { |
111 | struct irctl *ir; | 108 | struct irctl *ir; |
112 | unsigned int minor; | 109 | int minor; |
113 | int err; | 110 | int err; |
114 | 111 | ||
115 | if (!d) { | 112 | if (!d) { |
@@ -171,28 +168,17 @@ int lirc_register_driver(struct lirc_driver *d) | |||
171 | d->rbuf = ir->buf; | 168 | d->rbuf = ir->buf; |
172 | } | 169 | } |
173 | 170 | ||
174 | mutex_lock(&lirc_dev_lock); | 171 | minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL); |
175 | 172 | if (minor < 0) { | |
176 | /* find first free slot for driver */ | ||
177 | for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) | ||
178 | if (!irctls[minor]) | ||
179 | break; | ||
180 | |||
181 | if (minor == MAX_IRCTL_DEVICES) { | ||
182 | dev_err(d->dev, "no free slots for drivers!\n"); | ||
183 | mutex_unlock(&lirc_dev_lock); | ||
184 | lirc_free_buffer(ir); | 173 | lirc_free_buffer(ir); |
185 | kfree(ir); | 174 | kfree(ir); |
186 | return -ENOMEM; | 175 | return minor; |
187 | } | 176 | } |
188 | 177 | ||
189 | irctls[minor] = ir; | ||
190 | d->irctl = ir; | 178 | d->irctl = ir; |
191 | d->minor = minor; | 179 | d->minor = minor; |
192 | ir->d.minor = minor; | 180 | ir->d.minor = minor; |
193 | 181 | ||
194 | mutex_unlock(&lirc_dev_lock); | ||
195 | |||
196 | device_initialize(&ir->dev); | 182 | device_initialize(&ir->dev); |
197 | ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); | 183 | ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); |
198 | ir->dev.class = lirc_class; | 184 | ir->dev.class = lirc_class; |
@@ -206,6 +192,7 @@ int lirc_register_driver(struct lirc_driver *d) | |||
206 | 192 | ||
207 | err = cdev_device_add(&ir->cdev, &ir->dev); | 193 | err = cdev_device_add(&ir->cdev, &ir->dev); |
208 | if (err) { | 194 | if (err) { |
195 | ida_simple_remove(&lirc_ida, minor); | ||
209 | put_device(&ir->dev); | 196 | put_device(&ir->dev); |
210 | return err; | 197 | return err; |
211 | } | 198 | } |
@@ -244,6 +231,7 @@ void lirc_unregister_driver(struct lirc_driver *d) | |||
244 | 231 | ||
245 | mutex_unlock(&ir->mutex); | 232 | mutex_unlock(&ir->mutex); |
246 | 233 | ||
234 | ida_simple_remove(&lirc_ida, d->minor); | ||
247 | put_device(&ir->dev); | 235 | put_device(&ir->dev); |
248 | } | 236 | } |
249 | EXPORT_SYMBOL(lirc_unregister_driver); | 237 | EXPORT_SYMBOL(lirc_unregister_driver); |
@@ -540,7 +528,7 @@ static int __init lirc_dev_init(void) | |||
540 | return PTR_ERR(lirc_class); | 528 | return PTR_ERR(lirc_class); |
541 | } | 529 | } |
542 | 530 | ||
543 | retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, | 531 | retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES, |
544 | "BaseRemoteCtl"); | 532 | "BaseRemoteCtl"); |
545 | if (retval) { | 533 | if (retval) { |
546 | class_destroy(lirc_class); | 534 | class_destroy(lirc_class); |
@@ -557,7 +545,7 @@ static int __init lirc_dev_init(void) | |||
557 | static void __exit lirc_dev_exit(void) | 545 | static void __exit lirc_dev_exit(void) |
558 | { | 546 | { |
559 | class_destroy(lirc_class); | 547 | class_destroy(lirc_class); |
560 | unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); | 548 | unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES); |
561 | pr_info("module unloaded\n"); | 549 | pr_info("module unloaded\n"); |
562 | } | 550 | } |
563 | 551 | ||