forked from Minki/linux
[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: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
04f561ff87
commit
8de111e276
@ -55,6 +55,8 @@ struct irctl {
|
||||
struct lirc_buffer *buf;
|
||||
unsigned int chunk_size;
|
||||
|
||||
struct cdev *cdev;
|
||||
|
||||
struct task_struct *task;
|
||||
long jiffies_to_wait;
|
||||
};
|
||||
@ -62,7 +64,6 @@ struct irctl {
|
||||
static DEFINE_MUTEX(lirc_dev_lock);
|
||||
|
||||
static struct irctl *irctls[MAX_IRCTL_DEVICES];
|
||||
static struct cdev cdevs[MAX_IRCTL_DEVICES];
|
||||
|
||||
/* Only used for sysfs but defined to void otherwise */
|
||||
static struct class *lirc_class;
|
||||
@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = {
|
||||
|
||||
static int lirc_cdev_add(struct irctl *ir)
|
||||
{
|
||||
int retval;
|
||||
int retval = -ENOMEM;
|
||||
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) {
|
||||
cdev_init(cdev, d->fops);
|
||||
@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir)
|
||||
}
|
||||
retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
|
||||
if (retval)
|
||||
return retval;
|
||||
goto err_out;
|
||||
|
||||
retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
|
||||
if (retval)
|
||||
if (retval) {
|
||||
kobject_put(&cdev->kobj);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ir->cdev = cdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
kfree(cdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d)
|
||||
if (MAX_IRCTL_DEVICES <= d->minor) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"\"minor\" must be between 0 and %d (%d)!\n",
|
||||
MAX_IRCTL_DEVICES-1, d->minor);
|
||||
MAX_IRCTL_DEVICES - 1, d->minor);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor)
|
||||
|
||||
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
cdev = &cdevs[minor];
|
||||
cdev = ir->cdev;
|
||||
|
||||
mutex_lock(&lirc_dev_lock);
|
||||
|
||||
@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor)
|
||||
} else {
|
||||
lirc_irctl_cleanup(ir);
|
||||
cdev_del(cdev);
|
||||
kfree(cdev);
|
||||
kfree(ir);
|
||||
irctls[minor] = NULL;
|
||||
}
|
||||
@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
||||
goto error;
|
||||
}
|
||||
|
||||
cdev = &cdevs[iminor(inode)];
|
||||
cdev = ir->cdev;
|
||||
if (try_module_get(cdev->owner)) {
|
||||
ir->open++;
|
||||
retval = ir->d.set_use_inc(ir->d.data);
|
||||
@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
|
||||
int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(inode)];
|
||||
struct cdev *cdev = &cdevs[iminor(inode)];
|
||||
struct cdev *cdev;
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cdev = ir->cdev;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
WARN_ON(mutex_lock_killable(&lirc_dev_lock));
|
||||
@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
||||
lirc_irctl_cleanup(ir);
|
||||
cdev_del(cdev);
|
||||
irctls[ir->d.minor] = NULL;
|
||||
kfree(cdev);
|
||||
kfree(ir);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef _LINUX_LIRC_DEV_H
|
||||
#define _LINUX_LIRC_DEV_H
|
||||
|
||||
#define MAX_IRCTL_DEVICES 4
|
||||
#define MAX_IRCTL_DEVICES 8
|
||||
#define BUFLEN 16
|
||||
|
||||
#define mod(n, div) ((n) % (div))
|
||||
|
Loading…
Reference in New Issue
Block a user