diff options
Diffstat (limited to 'drivers/media/rc/lirc_dev.c')
| -rw-r--r-- | drivers/media/rc/lirc_dev.c | 37 | 
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index fd237ab120bb..27997a9ceb0d 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -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);  	}  |