From: Hans Verkuil <hans.verkuil@xxxxxxxxx> For mem2mem devices we have to make sure that v4l2_m2m_try_schedule() is called whenever a request is queued. We do that by creating a vb2_m2m_request_queue() helper that should be used instead of the 'normal' vb2_request_queue() helper. The m2m helper function will call v4l2_m2m_try_schedule() as needed. In addition we also avoid calling v4l2_m2m_try_schedule() when preparing or queueing a buffer for a request since that is no longer needed. Instead this helper function will do that when the request is actually queued. Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> --- drivers/media/v4l2-core/v4l2-mem2mem.c | 43 +++++++++++++++++++++----- include/media/v4l2-mem2mem.h | 4 +++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 88f95b78e4d0..ec0f8924f5c7 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -304,7 +304,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx) if (m2m_ctx->job_flags & TRANS_RUNNING) { spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); - dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); + dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx); wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags & TRANS_RUNNING)); } else if (m2m_ctx->job_flags & TRANS_QUEUED) { @@ -396,8 +396,14 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, int ret; vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); + if (!V4L2_TYPE_IS_OUTPUT(vq->type) && + (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)) { + dprintk("%s: requests cannot be used with capture buffers\n", + __func__); + return -EINVAL; + } ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf); - if (!ret) + if (!ret && !(buf->flags & V4L2_BUF_FLAG_IN_REQUEST)) v4l2_m2m_try_schedule(m2m_ctx); return ret; @@ -419,14 +425,9 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, { struct video_device *vdev = video_devdata(file); struct vb2_queue *vq; - int ret; vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); - ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf); - if (!ret) - v4l2_m2m_try_schedule(m2m_ctx); - - return ret; + return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf); } EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf); @@ -703,6 +704,32 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, } EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue); +void vb2_m2m_request_queue(struct media_request *req) +{ + struct media_request_object *obj; + + list_for_each_entry(obj, &req->objects, list) { + struct v4l2_m2m_ctx *m2m_ctx; + struct vb2_buffer *vb; + + if (!obj->ops->queue) + continue; + + obj->ops->queue(obj); + if (!vb2_request_object_is_buffer(obj)) + continue; + + vb = container_of(obj, struct vb2_buffer, req_obj); + if (WARN_ON(!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))) + continue; + m2m_ctx = container_of(vb->vb2_queue, + struct v4l2_m2m_ctx, + out_q_ctx.q); + v4l2_m2m_try_schedule(m2m_ctx); + } +} +EXPORT_SYMBOL_GPL(vb2_m2m_request_queue); + /* Videobuf2 ioctl helpers */ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 3d07ba3a8262..f01b3fc13b0e 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -580,6 +580,10 @@ v4l2_m2m_dst_buf_remove_by_idx(struct v4l2_m2m_ctx *m2m_ctx, unsigned int idx) return v4l2_m2m_buf_remove_by_idx(&m2m_ctx->cap_q_ctx, idx); } +/* v4l2 request helper */ + +void vb2_m2m_request_queue(struct media_request *req); + /* v4l2 ioctl helpers */ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, -- 2.17.0