diff options
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index eeed14468a17..01670567641a 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -29,6 +29,7 @@ #include <media/v4l2-device.h> #include <media/videobuf2-v4l2.h> #include <media/v4l2-mc.h> +#include <media/v4l2-mem2mem.h> #include <trace/events/v4l2.h> @@ -2670,11 +2671,62 @@ static bool v4l2_is_known_ioctl(unsigned int cmd) return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; } +#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) +static bool v4l2_ioctl_m2m_queue_is_output(unsigned int cmd, void *arg) +{ + switch (cmd) { + case VIDIOC_CREATE_BUFS: { + struct v4l2_create_buffers *cbufs = arg; + + return V4L2_TYPE_IS_OUTPUT(cbufs->format.type); + } + case VIDIOC_REQBUFS: { + struct v4l2_requestbuffers *rbufs = arg; + + return V4L2_TYPE_IS_OUTPUT(rbufs->type); + } + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + case VIDIOC_QUERYBUF: + case VIDIOC_PREPARE_BUF: { + struct v4l2_buffer *buf = arg; + + return V4L2_TYPE_IS_OUTPUT(buf->type); + } + case VIDIOC_EXPBUF: { + struct v4l2_exportbuffer *expbuf = arg; + + return V4L2_TYPE_IS_OUTPUT(expbuf->type); + } + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { + int *type = arg; + + return V4L2_TYPE_IS_OUTPUT(*type); + } + default: + return false; + } +} +#endif + static struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, - unsigned int cmd) + struct v4l2_fh *vfh, unsigned int cmd, + void *arg) { if (_IOC_NR(cmd) >= V4L2_IOCTLS) return vdev->lock; +#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) + if (vfh && vfh->m2m_ctx && + (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) { + bool is_output = v4l2_ioctl_m2m_queue_is_output(cmd, arg); + struct v4l2_m2m_queue_ctx *ctx = is_output ? + &vfh->m2m_ctx->out_q_ctx : &vfh->m2m_ctx->cap_q_ctx; + + if (ctx->q.lock) + return ctx->q.lock; + } +#endif if (vdev->queue && vdev->queue->lock && (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) return vdev->queue->lock; @@ -2741,7 +2793,7 @@ 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); + lock = v4l2_ioctl_get_lock(vfd, vfh, cmd, arg); if (lock && mutex_lock_interruptible(lock)) return -ERESTARTSYS; |