[PATCH 2/2] media: mediatek: vcodec: Complete request on NULL va in stateless decoder
From: Fei Shao
Date: Mon Oct 19 2026 - 02:10:06 EST
If vb2_plane_vaddr() returns NULL for the source buffer because it has
no kernel mapping, mtk_vdec_worker() finishes the m2m job without
returning any buffer or completing the media request, so userspace
waiting on the request never gets a result. The source buffer was only
peeked and stays at the head of the ready list, so
v4l2_m2m_job_finish() also schedules the same job again, which fails
the same way.
Handle it like a decode error, which takes three steps:
- Complete the request controls. The request cannot complete while its
control object is still pending.
- Remove the source buffer from the ready list and return it with an
error, so that the job is not scheduled again.
- Call mtk_vdec_stateless_cap_to_disp(). It returns the capture buffer
and drops the driver's reference to the request, which completes the
request under manual completion.
The media request is now looked up before the address check because
this path needs it, and the error is printed first because the buffer
must not be touched once it is returned.
Fixes: 7b182b8d9c85 ("media: mediatek: vcodec: Refactor get and put capture buffer flow")
Signed-off-by: Fei Shao <fshao@xxxxxxxxxxxx>
---
.../vcodec/decoder/mtk_vcodec_dec_stateless.c | 22 ++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index ab1894fba0d9..c97835f50ca1 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -342,23 +342,29 @@ static void mtk_vdec_worker(struct work_struct *work)
bs_src->va = vb2_plane_vaddr(vb2_src, 0);
bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
bs_src->size = (size_t)vb2_src->planes[0].bytesused;
- if (!bs_src->va) {
+
+ mreq = vb2_src->req_obj.req;
+ if (WARN_ON(!mreq)) {
v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+ mtk_v4l2_vdec_err(ctx, "vb2 buffer media request is NULL");
+ return;
+ }
+
+ if (!bs_src->va) {
mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is NULL", ctx->id,
vb2_src->index);
+ v4l2_ctrl_request_complete(mreq, &ctx->ctrl_hdl);
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_buf_done(vb2_v4l2_src, VB2_BUF_STATE_ERROR);
+ mtk_vdec_stateless_cap_to_disp(ctx, -EFAULT, mreq);
+ v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
return;
}
mtk_v4l2_vdec_dbg(3, ctx, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p",
ctx->id, bs_src->va, &bs_src->dma_addr, bs_src->size, vb2_src);
- /* Apply request controls. */
- mreq = vb2_src->req_obj.req;
- if (WARN_ON(!mreq)) {
- v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
- mtk_v4l2_vdec_err(ctx, "vb2 buffer media request is NULL");
- return;
- }
+ /* Apply request controls. */
v4l2_ctrl_request_setup(mreq, &ctx->ctrl_hdl);
/* Keep a reference so that if the processing completes before this function
--
2.56.0.176.g3575e65682-goog