Commit d862bc08 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: v4l2-ioctl.c: use correct vb2_queue lock for m2m devices

For m2m devices the vdev->queue lock was always taken instead of the
lock for the specific capture or output queue. Now that we pushed
the locking down into __video_do_ioctl() we can pick the correct
lock and potentially improve the performance of m2m devices.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 19d38b23
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/videobuf2-v4l2.h> #include <media/videobuf2-v4l2.h>
#include <media/v4l2-mc.h> #include <media/v4l2-mc.h>
#include <media/v4l2-mem2mem.h>
#include <trace/events/v4l2.h> #include <trace/events/v4l2.h>
...@@ -2670,11 +2671,62 @@ static bool v4l2_is_known_ioctl(unsigned int cmd) ...@@ -2670,11 +2671,62 @@ static bool v4l2_is_known_ioctl(unsigned int cmd)
return v4l2_ioctls[_IOC_NR(cmd)].ioctl == 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, 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) if (_IOC_NR(cmd) >= V4L2_IOCTLS)
return vdev->lock; 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 && if (vdev->queue && vdev->queue->lock &&
(v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE))
return vdev->queue->lock; return vdev->queue->lock;
...@@ -2741,7 +2793,7 @@ static long __video_do_ioctl(struct file *file, ...@@ -2741,7 +2793,7 @@ static long __video_do_ioctl(struct file *file,
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data; 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)) if (lock && mutex_lock_interruptible(lock))
return -ERESTARTSYS; return -ERESTARTSYS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment