|
@@ -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;
|