From patchwork Fri Nov 18 23:20:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benoit Parrot X-Patchwork-Id: 9437577 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 20B1660238 for ; Fri, 18 Nov 2016 23:23:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0FBBE271E0 for ; Fri, 18 Nov 2016 23:23:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0321A28585; Fri, 18 Nov 2016 23:23:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A591271E0 for ; Fri, 18 Nov 2016 23:23:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753852AbcKRXXr (ORCPT ); Fri, 18 Nov 2016 18:23:47 -0500 Received: from lelnx194.ext.ti.com ([198.47.27.80]:14834 "EHLO lelnx194.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753677AbcKRXVX (ORCPT ); Fri, 18 Nov 2016 18:21:23 -0500 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by lelnx194.ext.ti.com (8.15.1/8.15.1) with ESMTP id uAINLMOv020209; Fri, 18 Nov 2016 17:21:22 -0600 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id uAINLMq7029009; Fri, 18 Nov 2016 17:21:22 -0600 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.294.0; Fri, 18 Nov 2016 17:21:21 -0600 Received: from uda0869644a.am.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id uAINKqW8001882; Fri, 18 Nov 2016 17:21:22 -0600 From: Benoit Parrot To: , Hans Verkuil CC: , Tomi Valkeinen , Jyri Sarha , Peter Ujfalusi , Benoit Parrot Subject: [Patch v2 31/35] media: ti-vpe: vpe: Make sure frame size dont exceed scaler capacity Date: Fri, 18 Nov 2016 17:20:41 -0600 Message-ID: <20161118232045.24665-32-bparrot@ti.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20161118232045.24665-1-bparrot@ti.com> References: <20161118232045.24665-1-bparrot@ti.com> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When scaler is to be used we need to make sure that the input and output frame size do not exceed the maximum frame sizes that the scaler h/w can handle otherwise streaming stall as the scaler cannot proceed. The scaler buffer is limited to 2047 pixels (i.e. 11 bits) when attempting anything larger (2048 for example) the scaler stalls. Realistically in an mem2mem device we can only check for this type of issue when start_streaming is called. We can't do it during the try_fmt/s_fmt because we do not have all of the info needed at that point. So instead when start_streaming is called we need to check that the input and output frames size do not exceed the scaler's capability. The only time larger frame size are allowed is when the input frame szie is the same as the output frame size. Now in the case where we need to fail, start_streaming must return all previously queued buffer back otherwise the vb2 framework will issue kernel WARN messages. In this case we also give an error message. Signed-off-by: Benoit Parrot Acked-by: Hans Verkuil --- drivers/media/platform/ti-vpe/sc.h | 6 ++++ drivers/media/platform/ti-vpe/vpe.c | 71 ++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/ti-vpe/sc.h b/drivers/media/platform/ti-vpe/sc.h index d0aab5ef0eca..f1fe80b38c9f 100644 --- a/drivers/media/platform/ti-vpe/sc.h +++ b/drivers/media/platform/ti-vpe/sc.h @@ -173,6 +173,12 @@ /* number of taps expected by the scaler in it's coefficient memory */ #define SC_NUM_TAPS_MEM_ALIGN 8 +/* Maximum frame width the scaler can handle (in pixels) */ +#define SC_MAX_PIXEL_WIDTH 2047 + +/* Maximum frame height the scaler can handle (in lines) */ +#define SC_MAX_PIXEL_HEIGHT 2047 + /* * coefficient memory size in bytes: * num phases x num sets(luma and chroma) x num taps(aligned) x coeff size diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index ebde4f4586e6..32489d6369ca 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -2025,28 +2025,33 @@ static void vpe_buf_queue(struct vb2_buffer *vb) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } -static int vpe_start_streaming(struct vb2_queue *q, unsigned int count) +static int check_srcdst_sizes(struct vpe_ctx *ctx) { - struct vpe_ctx *ctx = vb2_get_drv_priv(q); + struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC]; + struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST]; + unsigned int src_w = s_q_data->c_rect.width; + unsigned int src_h = s_q_data->c_rect.height; + unsigned int dst_w = d_q_data->c_rect.width; + unsigned int dst_h = d_q_data->c_rect.height; - if (ctx->deinterlacing) - config_edi_input_mode(ctx, 0x0); + if (src_w == dst_w && src_h == dst_h) + return 0; - if (ctx->sequence != 0) - set_srcdst_params(ctx); + if (src_h <= SC_MAX_PIXEL_HEIGHT && + src_w <= SC_MAX_PIXEL_WIDTH && + dst_h <= SC_MAX_PIXEL_HEIGHT && + dst_w <= SC_MAX_PIXEL_WIDTH) + return 0; - return 0; + return -1; } -static void vpe_stop_streaming(struct vb2_queue *q) +static void vpe_return_all_buffers(struct vpe_ctx *ctx, struct vb2_queue *q, + enum vb2_buffer_state state) { - struct vpe_ctx *ctx = vb2_get_drv_priv(q); struct vb2_v4l2_buffer *vb; unsigned long flags; - vpe_dump_regs(ctx->dev); - vpdma_dump_regs(ctx->dev->vpdma); - for (;;) { if (V4L2_TYPE_IS_OUTPUT(q->type)) vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); @@ -2055,7 +2060,7 @@ static void vpe_stop_streaming(struct vb2_queue *q) if (!vb) break; spin_lock_irqsave(&ctx->dev->lock, flags); - v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(vb, state); spin_unlock_irqrestore(&ctx->dev->lock, flags); } @@ -2068,15 +2073,15 @@ static void vpe_stop_streaming(struct vb2_queue *q) spin_lock_irqsave(&ctx->dev->lock, flags); if (ctx->src_vbs[2]) - v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(ctx->src_vbs[2], state); if (ctx->src_vbs[1] && (ctx->src_vbs[1] != ctx->src_vbs[2])) - v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(ctx->src_vbs[1], state); if (ctx->src_vbs[0] && (ctx->src_vbs[0] != ctx->src_vbs[1]) && (ctx->src_vbs[0] != ctx->src_vbs[2])) - v4l2_m2m_buf_done(ctx->src_vbs[0], VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(ctx->src_vbs[0], state); ctx->src_vbs[2] = NULL; ctx->src_vbs[1] = NULL; @@ -2087,13 +2092,45 @@ static void vpe_stop_streaming(struct vb2_queue *q) if (ctx->dst_vb) { spin_lock_irqsave(&ctx->dev->lock, flags); - v4l2_m2m_buf_done(ctx->dst_vb, VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(ctx->dst_vb, state); ctx->dst_vb = NULL; spin_unlock_irqrestore(&ctx->dev->lock, flags); } } } +static int vpe_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct vpe_ctx *ctx = vb2_get_drv_priv(q); + + /* Check any of the size exceed maximum scaling sizes */ + if (check_srcdst_sizes(ctx)) { + vpe_err(ctx->dev, + "Conversion setup failed, check source and destination parameters\n" + ); + vpe_return_all_buffers(ctx, q, VB2_BUF_STATE_QUEUED); + return -EINVAL; + } + + if (ctx->deinterlacing) + config_edi_input_mode(ctx, 0x0); + + if (ctx->sequence != 0) + set_srcdst_params(ctx); + + return 0; +} + +static void vpe_stop_streaming(struct vb2_queue *q) +{ + struct vpe_ctx *ctx = vb2_get_drv_priv(q); + + vpe_dump_regs(ctx->dev); + vpdma_dump_regs(ctx->dev->vpdma); + + vpe_return_all_buffers(ctx, q, VB2_BUF_STATE_ERROR); +} + static const struct vb2_ops vpe_qops = { .queue_setup = vpe_queue_setup, .buf_prepare = vpe_buf_prepare,