diff --git a/kernel/daedalus_v4l2_main.c b/kernel/daedalus_v4l2_main.c index b493a4b..6eb021a 100644 --- a/kernel/daedalus_v4l2_main.c +++ b/kernel/daedalus_v4l2_main.c @@ -149,6 +149,17 @@ struct daedalus_ctx { struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_ctrl_handler hdl; + /* + * Per-context vb2 queue lock. Was originally pointed at the + * device-wide dev->m2m_lock, which serialised vb2 ioctls across + * every concurrent client — Firefox spawns multiple content/RDD + * processes that each open /dev/video0, and a device-wide lock + * made S_FMT / REQBUFS / QBUF on one client block (and sometimes + * EBUSY-fail) against another client mid-stream. cedrus / rkvdec + * / hantro all use per-ctx vb mutexes for exactly this reason. + */ + struct mutex vb_mutex; + struct v4l2_pix_format_mplane src_fmt; struct v4l2_pix_format_mplane dst_fmt; }; @@ -523,7 +534,9 @@ static int daedalus_queue_init(void *priv, struct vb2_queue *src_vq, */ src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = &ctx->dev->m2m_lock; + /* Per-ctx lock so concurrent clients don't serialise on a + * device-wide mutex. See struct daedalus_ctx.vb_mutex comment. */ + src_vq->lock = &ctx->vb_mutex; src_vq->dev = &ctx->dev->pdev->dev; src_vq->allow_cache_hints = 1; @@ -538,7 +551,7 @@ static int daedalus_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->ops = &daedalus_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - dst_vq->lock = &ctx->dev->m2m_lock; + dst_vq->lock = &ctx->vb_mutex; dst_vq->dev = &ctx->dev->pdev->dev; dst_vq->allow_cache_hints = 1; @@ -1112,6 +1125,7 @@ static int daedalus_open(struct file *file) if (!ctx) return -ENOMEM; ctx->dev = dev; + mutex_init(&ctx->vb_mutex); v4l2_fh_init(&ctx->fh, &dev->vdev); file->private_data = &ctx->fh; @@ -1159,6 +1173,7 @@ static int daedalus_open(struct file *file) err_ctrl: v4l2_ctrl_handler_free(&ctx->hdl); v4l2_fh_exit(&ctx->fh); + mutex_destroy(&ctx->vb_mutex); kfree(ctx); return ret; } @@ -1175,6 +1190,7 @@ static int daedalus_release(struct file *file) v4l2_m2m_ctx_release(ctx->m2m_ctx); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_fh_exit(&ctx->fh); + mutex_destroy(&ctx->vb_mutex); kfree(ctx); return 0; }