diff options
Diffstat (limited to 'drivers/media/rc/lirc_dev.c')
| -rw-r--r-- | drivers/media/rc/lirc_dev.c | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 91f9bb87ce68..1688893a65bb 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -13,17 +13,13 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> #include <linux/kernel.h> -#include <linux/sched.h> +#include <linux/sched/signal.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/fs.h> @@ -150,9 +146,6 @@ static const struct file_operations lirc_dev_fops = { .write = lirc_dev_fop_write, .poll = lirc_dev_fop_poll, .unlocked_ioctl = lirc_dev_fop_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = lirc_dev_fop_ioctl, -#endif .open = lirc_dev_fop_open, .release = lirc_dev_fop_close, .llseek = noop_llseek, @@ -160,19 +153,19 @@ static const struct file_operations lirc_dev_fops = { static int lirc_cdev_add(struct irctl *ir) { - int retval = -ENOMEM; struct lirc_driver *d = &ir->d; struct cdev *cdev; + int retval; - cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + cdev = cdev_alloc(); if (!cdev) - goto err_out; + return -ENOMEM; if (d->fops) { - cdev_init(cdev, d->fops); + cdev->ops = d->fops; cdev->owner = d->owner; } else { - cdev_init(cdev, &lirc_dev_fops); + cdev->ops = &lirc_dev_fops; cdev->owner = THIS_MODULE; } retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); @@ -180,17 +173,15 @@ static int lirc_cdev_add(struct irctl *ir) goto err_out; retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); - if (retval) { - kobject_put(&cdev->kobj); + if (retval) goto err_out; - } ir->cdev = cdev; return 0; err_out: - kfree(cdev); + cdev_del(cdev); return retval; } @@ -420,7 +411,6 @@ int lirc_unregister_driver(int minor) } else { lirc_irctl_cleanup(ir); cdev_del(cdev); - kfree(cdev); kfree(ir); irctls[minor] = NULL; } @@ -446,6 +436,8 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) return -ERESTARTSYS; ir = irctls[iminor(inode)]; + mutex_unlock(&lirc_dev_lock); + if (!ir) { retval = -ENODEV; goto error; @@ -478,7 +470,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) if (retval) { module_put(cdev->owner); ir->open--; - } else { + } else if (ir->buf) { lirc_buffer_clear(ir->buf); } if (ir->task) @@ -486,8 +478,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) } error: - mutex_unlock(&lirc_dev_lock); - nonseekable_open(inode, file); return retval; @@ -521,7 +511,6 @@ 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); } @@ -589,7 +578,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) result = put_user(ir->d.features, (__u32 __user *)arg); break; case LIRC_GET_REC_MODE: - if (LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(ir->d.features)) { result = -ENOTTY; break; } @@ -599,7 +588,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (__u32 __user *)arg); break; case LIRC_SET_REC_MODE: - if (LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(ir->d.features)) { result = -ENOTTY; break; } @@ -658,6 +647,9 @@ ssize_t lirc_dev_fop_read(struct file *file, return -ENODEV; } + if (!LIRC_CAN_REC(ir->d.features)) + return -EINVAL; + dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); buf = kzalloc(ir->chunk_size, GFP_KERNEL); @@ -684,7 +676,6 @@ ssize_t lirc_dev_fop_read(struct file *file, * between while condition checking and scheduling) */ add_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_INTERRUPTIBLE); /* * while we didn't provide 'length' bytes, device is opened in blocking @@ -709,19 +700,19 @@ ssize_t lirc_dev_fop_read(struct file *file, } mutex_unlock(&ir->irctl_lock); - schedule(); set_current_state(TASK_INTERRUPTIBLE); + schedule(); + set_current_state(TASK_RUNNING); if (mutex_lock_interruptible(&ir->irctl_lock)) { ret = -ERESTARTSYS; remove_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_RUNNING); goto out_unlocked; } if (!ir->attached) { ret = -ENODEV; - break; + goto out_locked; } } else { lirc_buffer_read(ir->buf, buf); @@ -735,7 +726,6 @@ ssize_t lirc_dev_fop_read(struct file *file, } remove_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_RUNNING); out_locked: mutex_unlock(&ir->irctl_lock); |
