summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMing Qian <ming.qian@nxp.com>2022-08-12 15:22:09 +0800
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2022-09-30 16:43:53 +0200
commitdf71c6e4d5e54a79a772c3f8a3676ab6bf169c46 (patch)
tree820220ae5b9d82b9b2bee2a6927c4c8d4238b4c8
parentccc9f1db9c6b06205f35d4dcbd19a9cb16a25d03 (diff)
downloadlinux-df71c6e4d5e54a79a772c3f8a3676ab6bf169c46.tar.bz2
media: imx-jpeg: Lock on ioctl encoder/decoder stop cmd
the ioctl encoder/decoder cmd is under queue lock, and buf_done is in the irq, it can't be locked with the mutex, they are not synchronized. when v4l2_update_last_buf_state is called to handle the encoder/decoder stop cmd, the last src buffer may be done at the same time. so it's possible that last_src_buf is set, but the output rdy_queue is empty, then driver won't mark it stopped, as v4l2_m2m_is_last_draining_src_buf() will always return false and v4l2_m2m_dst_buf_is_last() return false too. In this case, the drain will be blocked. add the hw lock around the ioctl encoder/decoder cmd, to synchronize with the buf_done. Fixes: 4911c5acf935 ("media: imx-jpeg: Implement drain using v4l2-mem2mem helpers") Signed-off-by: Ming Qian <ming.qian@nxp.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index d262a563844f..bb2bc28b55ed 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1224,6 +1224,7 @@ static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
{
struct v4l2_fh *fh = file->private_data;
struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
+ unsigned long flags;
int ret;
ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
@@ -1233,7 +1234,9 @@ static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
if (!vb2_is_streaming(v4l2_m2m_get_src_vq(fh->m2m_ctx)))
return 0;
+ spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
ret = v4l2_m2m_ioctl_decoder_cmd(file, priv, cmd);
+ spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
if (ret < 0)
return ret;
@@ -1254,6 +1257,7 @@ static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,
{
struct v4l2_fh *fh = file->private_data;
struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
+ unsigned long flags;
int ret;
ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);
@@ -1264,7 +1268,9 @@ static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,
!vb2_is_streaming(v4l2_m2m_get_dst_vq(fh->m2m_ctx)))
return 0;
+ spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, cmd);
+ spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
if (ret < 0)
return 0;