@@ -3293,6 +3293,9 @@ static const struct v4l2_ctrl_ops adv7842_ctrl_ops = {
static const struct v4l2_subdev_core_ops adv7842_core_ops = {
.log_status = adv7842_log_status,
.ioctl = adv7842_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = adv7842_ioctl,
+#endif
.interrupt_service_routine = adv7842_isr,
.subscribe_event = adv7842_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
@@ -1398,6 +1398,9 @@ static const struct v4l2_ctrl_ops si4713_ctrl_ops = {
static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
.ioctl = si4713_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = si4713_ioctl,
+#endif
};
static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {
@@ -686,13 +686,26 @@ static long subdev_ioctl(struct file *file, unsigned int cmd,
}
#ifdef CONFIG_COMPAT
-static long subdev_compat_ioctl32(struct file *file, unsigned int cmd,
- unsigned long arg)
+static long subdev_do_compat_ioctl32(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+ struct mutex *lock = vdev->lock;
+ long ret = -ENODEV;
- return v4l2_subdev_call(sd, core, compat_ioctl32, cmd, arg);
+ if (lock && mutex_lock_interruptible(lock))
+ return -ERESTARTSYS;
+ if (video_is_registered(vdev))
+ ret = v4l2_subdev_call(sd, core, compat_ioctl32, cmd, arg);
+ if (lock)
+ mutex_unlock(lock);
+ return ret;
+}
+
+static long subdev_compat_ioctl32(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return video_usercopy(file, cmd, arg, subdev_do_compat_ioctl32);
}
#endif
@@ -195,8 +195,7 @@ struct v4l2_subdev_core_ops {
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_COMPAT
- long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
- unsigned long arg);
+ long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#endif
#ifdef CONFIG_VIDEO_ADV_DEBUG
int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);