Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: imx-jpeg: Add a timeout mechanism for each frame

Add a timeout mechanism for each frame.
If the frame can't be decoded or encoded,
driver can cancel it to avoid hang.

Fixes: 2db16c6ed72ce ("media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG Encoder/Decoder")
Signed-off-by: Ming Qian <ming.qian@nxp.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>

authored by

Ming Qian and committed by
Hans Verkuil
cfed9632 2bcc3b48

+49 -7
+48 -7
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
··· 330 330 module_param(debug, int, 0644); 331 331 MODULE_PARM_DESC(debug, "Debug level (0-3)"); 332 332 333 + static unsigned int hw_timeout = 2000; 334 + module_param(hw_timeout, int, 0644); 335 + MODULE_PARM_DESC(hw_timeout, "MXC JPEG hw timeout, the number of milliseconds"); 336 + 333 337 static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision); 334 338 static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q); 335 339 ··· 573 569 } 574 570 } 575 571 572 + static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state state, bool reset) 573 + { 574 + struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; 575 + void __iomem *reg = jpeg->base_reg; 576 + struct vb2_v4l2_buffer *src_buf, *dst_buf; 577 + 578 + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); 579 + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 580 + mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf); 581 + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 582 + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 583 + v4l2_m2m_buf_done(src_buf, state); 584 + v4l2_m2m_buf_done(dst_buf, state); 585 + 586 + mxc_jpeg_disable_irq(reg, ctx->slot); 587 + ctx->mxc_jpeg->slot_data[ctx->slot].used = false; 588 + if (reset) 589 + mxc_jpeg_sw_reset(reg); 590 + } 591 + 576 592 static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) 577 593 { 578 594 struct mxc_jpeg_dev *jpeg = priv; ··· 624 600 slot, ctx->slot); 625 601 goto job_unlock; 626 602 } 603 + 604 + if (!jpeg->slot_data[slot].used) 605 + goto job_unlock; 627 606 628 607 dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); 629 608 writel(dec_ret, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */ ··· 692 665 buf_state = VB2_BUF_STATE_DONE; 693 666 694 667 buffers_done: 695 - mxc_jpeg_disable_irq(reg, ctx->slot); 696 - jpeg->slot_data[slot].used = false; /* unused, but don't free */ 697 - mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf); 698 - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 699 - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 700 - v4l2_m2m_buf_done(src_buf, buf_state); 701 - v4l2_m2m_buf_done(dst_buf, buf_state); 668 + mxc_jpeg_job_finish(ctx, buf_state, false); 702 669 spin_unlock(&jpeg->hw_lock); 670 + cancel_delayed_work(&ctx->task_timer); 703 671 v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); 704 672 return IRQ_HANDLED; 705 673 job_unlock: ··· 1025 1003 return ctx->source_change ? 0 : 1; 1026 1004 } 1027 1005 1006 + static void mxc_jpeg_device_run_timeout(struct work_struct *work) 1007 + { 1008 + struct delayed_work *dwork = to_delayed_work(work); 1009 + struct mxc_jpeg_ctx *ctx = container_of(dwork, struct mxc_jpeg_ctx, task_timer); 1010 + struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; 1011 + unsigned long flags; 1012 + 1013 + spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags); 1014 + if (ctx->slot < MXC_MAX_SLOTS && ctx->mxc_jpeg->slot_data[ctx->slot].used) { 1015 + dev_warn(jpeg->dev, "%s timeout, cancel it\n", 1016 + ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? "decode" : "encode"); 1017 + mxc_jpeg_job_finish(ctx, VB2_BUF_STATE_ERROR, true); 1018 + v4l2_m2m_job_finish(ctx->mxc_jpeg->m2m_dev, ctx->fh.m2m_ctx); 1019 + } 1020 + spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags); 1021 + } 1022 + 1028 1023 static void mxc_jpeg_device_run(void *priv) 1029 1024 { 1030 1025 struct mxc_jpeg_ctx *ctx = priv; ··· 1127 1088 &src_buf->vb2_buf, &dst_buf->vb2_buf); 1128 1089 mxc_jpeg_dec_mode_go(dev, reg); 1129 1090 } 1091 + schedule_delayed_work(&ctx->task_timer, msecs_to_jiffies(hw_timeout)); 1130 1092 end: 1131 1093 spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags); 1132 1094 } ··· 1711 1671 ctx->fh.ctrl_handler = &ctx->ctrl_handler; 1712 1672 mxc_jpeg_set_default_params(ctx); 1713 1673 ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */ 1674 + INIT_DELAYED_WORK(&ctx->task_timer, mxc_jpeg_device_run_timeout); 1714 1675 1715 1676 if (mxc_jpeg->mode == MXC_JPEG_DECODE) 1716 1677 dev_dbg(dev, "Opened JPEG decoder instance %p\n", ctx);
+1
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
··· 97 97 bool header_parsed; 98 98 struct v4l2_ctrl_handler ctrl_handler; 99 99 u8 jpeg_quality; 100 + struct delayed_work task_timer; 100 101 }; 101 102 102 103 struct mxc_jpeg_slot_data {