diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index c23fbfe90a9e..965fd301f617 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2655,14 +2655,15 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) -bool v4l2_is_known_ioctl(unsigned int cmd) +static bool v4l2_is_known_ioctl(unsigned int cmd) { if (_IOC_NR(cmd) >= V4L2_IOCTLS) return false; return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; } -struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd) +static struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, + unsigned int cmd) { if (_IOC_NR(cmd) >= V4L2_IOCTLS) return vdev->lock; @@ -2713,6 +2714,7 @@ static long __video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vfd = video_devdata(file); + struct mutex *lock; /* ioctl serialization mutex */ const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; bool write_only = false; struct v4l2_ioctl_info default_info; @@ -2731,6 +2733,16 @@ static long __video_do_ioctl(struct file *file, if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) vfh = file->private_data; + lock = v4l2_ioctl_get_lock(vfd, cmd); + + if (lock && mutex_lock_interruptible(lock)) + return -ERESTARTSYS; + + if (!video_is_registered(vfd)) { + ret = -ENODEV; + goto unlock; + } + if (v4l2_is_known_ioctl(cmd)) { info = &v4l2_ioctls[_IOC_NR(cmd)]; @@ -2780,6 +2792,9 @@ done: } } +unlock: + if (lock) + mutex_unlock(lock); return ret; } @@ -2969,7 +2984,6 @@ out: kvfree(mbuf); return err; } -EXPORT_SYMBOL(video_usercopy); long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) |