[PATCH] media: imx-jpeg: Fix JPEG encoder ready race condition
Marek Vasut
marek.vasut at mailbox.org
Wed Aug 20 09:29:25 PDT 2025
The current mxc_jpeg_job_ready() implementation works for JPEG decode
side of this IP, it does not work at all for the JPEG encode side. The
JPEG encode side does not change ctx->source_change at all, therefore
the mxc_jpeg_source_change() always returns right away and the encode
side somehow works.
However, this is susceptible to a race condition between mxc_jpeg_dec_irq()
and mxc_jpeg_start_streaming(), where mxc_jpeg_start_streaming() might
start decoding another frame before mxc_jpeg_dec_irq() indicates completion
of encoding of current frame. Add new state, MXC_JPEG_ENC_DONE, which is
set in three locations, first when streaming starts to indicate the encoder
is ready to start processing a frame, second in mxc_jpeg_dec_irq() when the
encoder finishes encoding current frame, and third in mxc_jpeg_dec_irq() in
case of an error so the encoder can proceed with encoding another frame.
Update mxc_jpeg_job_ready() to check whether the encoder is in this new
MXC_JPEG_ENC_DONE state before reporting the encoder is ready to encode
new frame.
Fixes: b4e1fb8643da ("media: imx-jpeg: Support dynamic resolution change")
Signed-off-by: Marek Vasut <marek.vasut at mailbox.org>
---
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Cc: Mauro Carvalho Chehab <mchehab at kernel.org>
Cc: Ming Qian <ming.qian at oss.nxp.com>
Cc: Mirela Rabulea <mirela.rabulea at nxp.com>
Cc: Nicolas Dufresne <nicolas.dufresne at collabora.com>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-media at vger.kernel.org
---
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 18 ++++++++++++++++--
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h | 1 +
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index df3ccdf767baf..aef1d6473eb8d 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1009,6 +1009,7 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
dev_err(dev, "Encoder/decoder error, dec_ret = 0x%08x, status=0x%08x",
dec_ret, ret);
+ ctx->enc_state = MXC_JPEG_ENC_DONE;
mxc_jpeg_clr_desc(reg, slot);
mxc_jpeg_sw_reset(reg);
buf_state = VB2_BUF_STATE_ERROR;
@@ -1062,9 +1063,16 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
buffers_done:
mxc_jpeg_job_finish(ctx, buf_state, false);
- spin_unlock(&jpeg->hw_lock);
cancel_delayed_work(&ctx->task_timer);
+
+ if (jpeg->mode == MXC_JPEG_ENCODE && ctx->enc_state == MXC_JPEG_ENCODING)
+ ctx->enc_state = MXC_JPEG_ENC_DONE;
+
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+
+ spin_unlock(&jpeg->hw_lock);
+
+
return IRQ_HANDLED;
job_unlock:
spin_unlock(&jpeg->hw_lock);
@@ -1488,8 +1496,12 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
static int mxc_jpeg_job_ready(void *priv)
{
struct mxc_jpeg_ctx *ctx = priv;
+ struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
- return ctx->source_change ? 0 : 1;
+ if (jpeg->mode == MXC_JPEG_ENCODE)
+ return ctx->enc_state == MXC_JPEG_ENC_DONE;
+ else
+ return ctx->source_change ? 0 : 1;
}
static void mxc_jpeg_device_run_timeout(struct work_struct *work)
@@ -1713,6 +1725,8 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type))
ctx->source_change = 0;
+ if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
+ ctx->enc_state = MXC_JPEG_ENC_DONE;
dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
q_data->sequence = 0;
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
index 44e46face6d1d..7f0910fc9b47e 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
@@ -35,6 +35,7 @@
enum mxc_jpeg_enc_state {
MXC_JPEG_ENCODING = 0, /* jpeg encode phase */
MXC_JPEG_ENC_CONF = 1, /* jpeg encoder config phase */
+ MXC_JPEG_ENC_DONE = 2, /* jpeg encoder done/ready phase */
};
enum mxc_jpeg_mode {
--
2.50.1
More information about the linux-arm-kernel
mailing list