[PATCH] media: imx-jpeg: Fix JPEG encoder ready race condition

Ming Qian(OSS) ming.qian at oss.nxp.com
Thu Aug 21 00:06:28 PDT 2025


Hi Marek,

On 8/21/2025 12:29 AM, Marek Vasut wrote:
> [You don't often get email from marek.vasut at mailbox.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> 
> 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.
> 

The jpeg encoder and jpeg decoder are 2 different devices, so they won't
compete with each other.

For encoder, we always want mxc_jpeg_job_ready() to return true.

And v4l2_m2m has ensured that there will be no race condition between
mxc_jpeg_dec_irq() and mxc_jpeg_start_streaming().

After v4l2_m2m_job_finish() is called in the mxc_jpeg_dec_irq(),
then it is possible to start encoding the next frame.

So I don't think it's necessary to add a new state MXC_JPEG_ENC_DONE,
as It is almost equivalent to the completion status of the v4l2 m2m job.

Regards,
Ming

> 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