On Tue May 26 21:22:05 2026 +0900, Younho Choi wrote:
> V4L2_CID_TRANS_NUM_BUFS controls how many buffer pairs a vim2m
> mem2mem job processes before the job is completed. The driver stores
> the value in ctx->translen and device_work() uses it later to decide
> whether the current transaction should continue.
>
> Letting userspace change this control while streaming is active can
> make a queued job observe a different transaction length than the one
> it started with. That leaves the transaction state inconsistent with
> the buffers currently queued for the job.
>
> Grab the transaction buffer count control while either queue is
> streaming, and release it only after both queues have stopped
> streaming. The V4L2 control framework then rejects changes with
> -EBUSY while the value is in use, while still allowing userspace to
> configure the value before streaming starts.
>
> Keep the control handler alive until after v4l2_m2m_ctx_release(),
> since releasing the mem2mem context can call stop_streaming(), which
> now ungrabs the control.
>
> Fixes: 96d8eab5d0a1 ("V4L/DVB: [v5,2/2] v4l: Add a mem-to-mem videobuf
> framework test device")
> Cc: [email protected]
> Signed-off-by: Younho Choi <[email protected]>
> Reviewed-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
drivers/media/test-drivers/vim2m.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
---
diff --git a/drivers/media/test-drivers/vim2m.c
b/drivers/media/test-drivers/vim2m.c
index bb2dd11eef0e..f4a2c4083829 100644
--- a/drivers/media/test-drivers/vim2m.c
+++ b/drivers/media/test-drivers/vim2m.c
@@ -205,6 +205,7 @@ struct vim2m_ctx {
struct vim2m_dev *dev;
struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *trans_num_bufs_ctrl;
/* Processed buffers in this transaction */
u8 num_processed;
@@ -1258,9 +1259,27 @@ static int vim2m_start_streaming(struct vb2_queue *q,
unsigned int count)
ctx->aborting = 0;
q_data->sequence = 0;
+ v4l2_ctrl_grab(ctx->trans_num_bufs_ctrl, true);
+
return 0;
}
+static bool vim2m_other_queue_is_streaming(struct vim2m_ctx *ctx,
+ struct vb2_queue *q)
+{
+ struct vb2_queue *other_vq;
+
+ if (!ctx->fh.m2m_ctx)
+ return false;
+
+ if (V4L2_TYPE_IS_OUTPUT(q->type))
+ other_vq = v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx);
+ else
+ other_vq = v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx);
+
+ return vb2_is_streaming(other_vq);
+}
+
static void vim2m_stop_streaming(struct vb2_queue *q)
{
struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
@@ -1274,11 +1293,14 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
else
vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
if (!vbuf)
- return;
+ break;
v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
&ctx->hdl);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
}
+
+ if (!vim2m_other_queue_is_streaming(ctx, q))
+ v4l2_ctrl_grab(ctx->trans_num_bufs_ctrl, false);
}
static void vim2m_buf_request_complete(struct vb2_buffer *vb)
@@ -1380,7 +1402,8 @@ static int vim2m_open(struct file *file)
vim2m_ctrl_trans_time_msec.def = default_transtime;
v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_time_msec, NULL);
- v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
+ ctx->trans_num_bufs_ctrl =
+ v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
if (hdl->error) {
rc = hdl->error;
v4l2_ctrl_handler_free(hdl);
@@ -1435,10 +1458,10 @@ static int vim2m_release(struct file *file)
v4l2_fh_del(&ctx->fh, file);
v4l2_fh_exit(&ctx->fh);
- v4l2_ctrl_handler_free(&ctx->hdl);
mutex_lock(&dev->dev_mutex);
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
mutex_unlock(&dev->dev_mutex);
+ v4l2_ctrl_handler_free(&ctx->hdl);
kfree(ctx);
atomic_dec(&dev->num_inst);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]