On Wed Jun 24 00:32:08 2026 +0000, Fan Wu wrote:
> mxc_jpeg_device_run() returns early through a shared "end" label on several
> error paths (no free slot, mxc_jpeg_alloc_slot_data() failure, or missing
> buffers or queue data), and none of them calls v4l2_m2m_job_finish().
> Since the delayed work is queued only after the hardware is started, those
> paths neither finish the job directly nor queue timeout work that could
> finish it later. The job is left with TRANS_RUNNING set, so the
> wait_event() in v4l2_m2m_cancel_job() (reached from v4l2_m2m_ctx_release()
> at close) waits indefinitely and the close hangs.
>
> mxc_jpeg_alloc_slot_data() uses dma_alloc_coherent(), so the failure path
> is reachable under memory pressure.
>
> Return the src/dst buffers with VB2_BUF_STATE_ERROR and call
> v4l2_m2m_job_finish() on those paths: paths that have buffers use a
> "buf_finish" label; the no-buffer path uses "job_finish" directly. This
> mirrors the existing jpeg_parse_error path.
>
> This bug was found by static analysis.
>
> Fixes: 2db16c6ed72c ("media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG
> Encoder/Decoder")
> Cc: [email protected]
> Signed-off-by: Fan Wu <[email protected]>
> Reviewed-by: Ming Qian <[email protected]>
> Signed-off-by: Frank Li <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
---
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index ea2fad5dd646..e17085935435 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1590,15 +1590,15 @@ static void mxc_jpeg_device_run(void *priv)
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
if (!src_buf || !dst_buf) {
dev_err(dev, "Null src or dst buf\n");
- goto end;
+ goto job_finish;
}
q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
if (!q_data_cap)
- goto end;
+ goto buf_finish;
q_data_out = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (!q_data_out)
- goto end;
+ goto buf_finish;
src_buf->sequence = q_data_out->sequence++;
dst_buf->sequence = q_data_cap->sequence++;
@@ -1636,11 +1636,11 @@ static void mxc_jpeg_device_run(void *priv)
ctx->slot = mxc_get_free_slot(&jpeg->slot_data);
if (ctx->slot < 0) {
dev_err(dev, "No more free slots\n");
- goto end;
+ goto buf_finish;
}
if (!mxc_jpeg_alloc_slot_data(jpeg)) {
dev_err(dev, "Cannot allocate slot data\n");
- goto end;
+ goto buf_finish;
}
mxc_jpeg_enable_slot(reg, ctx->slot);
@@ -1660,8 +1660,17 @@ static void mxc_jpeg_device_run(void *priv)
mxc_jpeg_dec_mode_go(dev, reg);
}
schedule_delayed_work(&ctx->task_timer, msecs_to_jiffies(hw_timeout));
-end:
+
spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+ return;
+buf_finish:
+ v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+job_finish:
+ spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
}
static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]