Commit 8de111e2 authored by Jarod Wilson's avatar Jarod Wilson Committed by Mauro Carvalho Chehab

[media] lirc_dev: store cdev in irctl, up maxdevs

Store the cdev pointer in struct irctl, allocated dynamically as needed,
rather than having a static array. At the same time, recycle some of the
saved memory to nudge the maximum number of lirc devices supported up a
ways -- its not that uncommon these days, now that we have the rc-core
lirc bridge driver, to see a system with at least 4 raw IR receivers.
(consider a mythtv backend with several video capture devices and the
possible need for IR transmit hardware).
Signed-off-by: default avatarJarod Wilson <jarod@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 04f561ff
...@@ -55,6 +55,8 @@ struct irctl { ...@@ -55,6 +55,8 @@ struct irctl {
struct lirc_buffer *buf; struct lirc_buffer *buf;
unsigned int chunk_size; unsigned int chunk_size;
struct cdev *cdev;
struct task_struct *task; struct task_struct *task;
long jiffies_to_wait; long jiffies_to_wait;
}; };
...@@ -62,7 +64,6 @@ struct irctl { ...@@ -62,7 +64,6 @@ struct irctl {
static DEFINE_MUTEX(lirc_dev_lock); static DEFINE_MUTEX(lirc_dev_lock);
static struct irctl *irctls[MAX_IRCTL_DEVICES]; static struct irctl *irctls[MAX_IRCTL_DEVICES];
static struct cdev cdevs[MAX_IRCTL_DEVICES];
/* Only used for sysfs but defined to void otherwise */ /* Only used for sysfs but defined to void otherwise */
static struct class *lirc_class; static struct class *lirc_class;
...@@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = { ...@@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = {
static int lirc_cdev_add(struct irctl *ir) static int lirc_cdev_add(struct irctl *ir)
{ {
int retval; int retval = -ENOMEM;
struct lirc_driver *d = &ir->d; struct lirc_driver *d = &ir->d;
struct cdev *cdev = &cdevs[d->minor]; struct cdev *cdev;
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
goto err_out;
if (d->fops) { if (d->fops) {
cdev_init(cdev, d->fops); cdev_init(cdev, d->fops);
...@@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir) ...@@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir)
} }
retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
if (retval) if (retval)
return retval; goto err_out;
retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
if (retval) if (retval) {
kobject_put(&cdev->kobj); kobject_put(&cdev->kobj);
goto err_out;
}
ir->cdev = cdev;
return 0;
err_out:
kfree(cdev);
return retval; return retval;
} }
...@@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d) ...@@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d)
if (MAX_IRCTL_DEVICES <= d->minor) { if (MAX_IRCTL_DEVICES <= d->minor) {
dev_err(d->dev, "lirc_dev: lirc_register_driver: " dev_err(d->dev, "lirc_dev: lirc_register_driver: "
"\"minor\" must be between 0 and %d (%d)!\n", "\"minor\" must be between 0 and %d (%d)!\n",
MAX_IRCTL_DEVICES-1, d->minor); MAX_IRCTL_DEVICES - 1, d->minor);
err = -EBADRQC; err = -EBADRQC;
goto out; goto out;
} }
...@@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor) ...@@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor)
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
"0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1);
return -EBADRQC; return -EBADRQC;
} }
...@@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor) ...@@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor)
return -ENOENT; return -ENOENT;
} }
cdev = &cdevs[minor]; cdev = ir->cdev;
mutex_lock(&lirc_dev_lock); mutex_lock(&lirc_dev_lock);
...@@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor) ...@@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor)
} else { } else {
lirc_irctl_cleanup(ir); lirc_irctl_cleanup(ir);
cdev_del(cdev); cdev_del(cdev);
kfree(cdev);
kfree(ir); kfree(ir);
irctls[minor] = NULL; irctls[minor] = NULL;
} }
...@@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ...@@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
goto error; goto error;
} }
cdev = &cdevs[iminor(inode)]; cdev = ir->cdev;
if (try_module_get(cdev->owner)) { if (try_module_get(cdev->owner)) {
ir->open++; ir->open++;
retval = ir->d.set_use_inc(ir->d.data); retval = ir->d.set_use_inc(ir->d.data);
...@@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open); ...@@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
int lirc_dev_fop_close(struct inode *inode, struct file *file) int lirc_dev_fop_close(struct inode *inode, struct file *file)
{ {
struct irctl *ir = irctls[iminor(inode)]; struct irctl *ir = irctls[iminor(inode)];
struct cdev *cdev = &cdevs[iminor(inode)]; struct cdev *cdev;
if (!ir) { if (!ir) {
printk(KERN_ERR "%s: called with invalid irctl\n", __func__); printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
return -EINVAL; return -EINVAL;
} }
cdev = ir->cdev;
dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
WARN_ON(mutex_lock_killable(&lirc_dev_lock)); WARN_ON(mutex_lock_killable(&lirc_dev_lock));
...@@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) ...@@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
lirc_irctl_cleanup(ir); lirc_irctl_cleanup(ir);
cdev_del(cdev); cdev_del(cdev);
irctls[ir->d.minor] = NULL; irctls[ir->d.minor] = NULL;
kfree(cdev);
kfree(ir); kfree(ir);
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#ifndef _LINUX_LIRC_DEV_H #ifndef _LINUX_LIRC_DEV_H
#define _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H
#define MAX_IRCTL_DEVICES 4 #define MAX_IRCTL_DEVICES 8
#define BUFLEN 16 #define BUFLEN 16
#define mod(n, div) ((n) % (div)) #define mod(n, div) ((n) % (div))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment