@@ -352,14 +352,8 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
int ret = -ENODEV;
if (vdev->fops->unlocked_ioctl) {
- struct mutex *lock = v4l2_ioctl_get_lock(vdev, cmd);
-
- if (lock && mutex_lock_interruptible(lock))
- return -ERESTARTSYS;
if (video_is_registered(vdev))
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
- if (lock)
- mutex_unlock(lock);
} else
ret = -ENOTTY;
@@ -2634,14 +2634,14 @@ 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 cmd)
{
if (_IOC_NR(cmd) >= V4L2_IOCTLS)
return vdev->lock;
@@ -2692,6 +2692,7 @@ static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
+ struct mutex *lock = v4l2_ioctl_get_lock(vfd, cmd);
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
bool write_only = false;
struct v4l2_ioctl_info default_info;
@@ -2710,6 +2711,14 @@ static long __video_do_ioctl(struct file *file,
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data;
+ 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)];
@@ -2765,6 +2774,9 @@ static long __video_do_ioctl(struct file *file,
}
}
+unlock:
+ if (lock)
+ mutex_unlock(lock);
return ret;
}
@@ -2954,7 +2966,6 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
kvfree(mbuf);
return err;
}
-EXPORT_SYMBOL(video_usercopy);
long video_ioctl2(struct file *file,
unsigned int cmd, unsigned long arg)
@@ -502,10 +502,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
+static long subdev_do_ioctl_lock(struct file *file, unsigned int cmd, void *arg)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct mutex *lock = vdev->lock;
+ long ret = -ENODEV;
+
+ if (lock && mutex_lock_interruptible(lock))
+ return -ERESTARTSYS;
+ if (video_is_registered(vdev))
+ ret = subdev_do_ioctl(file, cmd, arg);
+ if (lock)
+ mutex_unlock(lock);
+ return ret;
+}
+
static long subdev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- return video_usercopy(file, cmd, arg, subdev_do_ioctl);
+ return video_usercopy(file, cmd, arg, subdev_do_ioctl_lock);
}
#ifdef CONFIG_COMPAT
@@ -434,15 +434,6 @@ void video_device_release(struct video_device *vdev);
*/
void video_device_release_empty(struct video_device *vdev);
-/**
- * v4l2_is_known_ioctl - Checks if a given cmd is a known V4L ioctl
- *
- * @cmd: ioctl command
- *
- * returns true if cmd is a known V4L2 ioctl
- */
-bool v4l2_is_known_ioctl(unsigned int cmd);
-
/**
* v4l2_disable_ioctl- mark that a given command isn't implemented.
* shouldn't use core locking
@@ -658,18 +658,6 @@ void v4l_printk_ioctl(const char *prefix, unsigned int cmd);
struct video_device;
-
-/**
- * v4l2_ioctl_get_lock - get the mutex (if any) that it is need to lock for
- * a given command.
- *
- * @vdev: Pointer to struct &video_device.
- * @cmd: Ioctl name.
- *
- * .. note:: Internal use only. Should not be used outside V4L2 core.
- */
-struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned int cmd);
-
/* names for fancy debug output */
extern const char *v4l2_field_names[];
extern const char *v4l2_type_names[];