From patchwork Fri Nov 18 23:20:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benoit Parrot X-Patchwork-Id: 9437597 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 E0BBC60238 for ; Fri, 18 Nov 2016 23:25:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D0CB429A51 for ; Fri, 18 Nov 2016 23:25:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C52BB29A56; Fri, 18 Nov 2016 23:25:18 +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=unavailable 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 4EAD229A51 for ; Fri, 18 Nov 2016 23:25:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753613AbcKRXVU (ORCPT ); Fri, 18 Nov 2016 18:21:20 -0500 Received: from lelnx194.ext.ti.com ([198.47.27.80]:14816 "EHLO lelnx194.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753495AbcKRXVN (ORCPT ); Fri, 18 Nov 2016 18:21:13 -0500 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by lelnx194.ext.ti.com (8.15.1/8.15.1) with ESMTP id uAINL7cd020175; Fri, 18 Nov 2016 17:21:07 -0600 Received: from DLEE70.ent.ti.com (dlee70.ent.ti.com [157.170.170.113]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id uAINL7eP030184; Fri, 18 Nov 2016 17:21:07 -0600 Received: from dlep33.itg.ti.com (157.170.170.75) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.294.0; Fri, 18 Nov 2016 17:21:06 -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 uAINKqVn001882; Fri, 18 Nov 2016 17:21:06 -0600 From: Benoit Parrot To: , Hans Verkuil CC: , Tomi Valkeinen , Jyri Sarha , Peter Ujfalusi , Benoit Parrot Subject: [Patch v2 12/35] media: ti-vpe: vpdma: Add abort channel desc and cleanup APIs Date: Fri, 18 Nov 2016 17:20:22 -0600 Message-ID: <20161118232045.24665-13-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 From: Nikhil Devshatwar Whenever VPDMA processes a data descriptor of a list, it processes it and sets up the channel for the DMA transaction. List manager holds the descriptor in the list until the DMA is complete. If sync_on_channel descriptor, or another descriptor for the same channel is present in the FIFO, list manager keeps them until the current channel is free. When the capture stream is closed suddenly while there are pending descriptors in the FIFO (streamON failed, application killed), it would keep the VPDMA in a busy state. Any further list post would fail with EBUSY. To avoid this, drivers need to stop the current processing list and cleanup all the resources VPDMA has taken and also clear the internal FSM of list manager. The state machine is cleared by issuing channel specific abort descriptor. Therefore, the vpdma_list_cleanup accepts an array of channels for which abort_channel descriptors should be posted. It is driver's responsibility to post for all the channels or the channels which were used in the last context. Signed-off-by: Nikhil Devshatwar Signed-off-by: Benoit Parrot Acked-by: Hans Verkuil --- drivers/media/platform/ti-vpe/vpdma.c | 75 +++++++++++++++++++++++++++++++++++ drivers/media/platform/ti-vpe/vpdma.h | 6 +++ 2 files changed, 81 insertions(+) diff --git a/drivers/media/platform/ti-vpe/vpdma.c b/drivers/media/platform/ti-vpe/vpdma.c index 1a0152842a17..7808c9c1828b 100644 --- a/drivers/media/platform/ti-vpe/vpdma.c +++ b/drivers/media/platform/ti-vpe/vpdma.c @@ -385,6 +385,56 @@ void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf) EXPORT_SYMBOL(vpdma_unmap_desc_buf); /* + * Cleanup all pending descriptors of a list + * First, stop the current list being processed. + * If the VPDMA was busy, this step makes vpdma to accept post lists. + * To cleanup the internal FSM, post abort list descriptor for all the + * channels from @channels array of size @size. + */ +int vpdma_list_cleanup(struct vpdma_data *vpdma, int list_num, + int *channels, int size) +{ + struct vpdma_desc_list abort_list; + int i, ret, timeout = 500; + + write_reg(vpdma, VPDMA_LIST_ATTR, + (list_num << VPDMA_LIST_NUM_SHFT) | + (1 << VPDMA_LIST_STOP_SHFT)); + + if (size <= 0 || !channels) + return 0; + + ret = vpdma_create_desc_list(&abort_list, + size * sizeof(struct vpdma_dtd), VPDMA_LIST_TYPE_NORMAL); + if (ret) + return ret; + + for (i = 0; i < size; i++) + vpdma_add_abort_channel_ctd(&abort_list, channels[i]); + + ret = vpdma_map_desc_buf(vpdma, &abort_list.buf); + if (ret) + return ret; + ret = vpdma_submit_descs(vpdma, &abort_list, list_num); + if (ret) + return ret; + + while (vpdma_list_busy(vpdma, list_num) && timeout--) + ; + + if (timeout == 0) { + dev_err(&vpdma->pdev->dev, "Timed out cleaning up VPDMA list\n"); + return -EBUSY; + } + + vpdma_unmap_desc_buf(vpdma, &abort_list.buf); + vpdma_free_desc_buf(&abort_list.buf); + + return 0; +} +EXPORT_SYMBOL(vpdma_list_cleanup); + +/* * create a descriptor list, the user of this list will append configuration, * control and data descriptors to this list, this list will be submitted to * VPDMA. VPDMA's list parser will go through each descriptor and perform the @@ -629,6 +679,31 @@ void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, } EXPORT_SYMBOL(vpdma_add_sync_on_channel_ctd); +/* + * append an 'abort_channel' type control descriptor to the given descriptor + * list, this descriptor aborts any DMA transaction happening using the + * specified channel + */ +void vpdma_add_abort_channel_ctd(struct vpdma_desc_list *list, + int chan_num) +{ + struct vpdma_ctd *ctd; + + ctd = list->next; + WARN_ON((void *)(ctd + 1) > (list->buf.addr + list->buf.size)); + + ctd->w0 = 0; + ctd->w1 = 0; + ctd->w2 = 0; + ctd->type_source_ctl = ctd_type_source_ctl(chan_num, + CTD_TYPE_ABORT_CHANNEL); + + list->next = ctd + 1; + + dump_ctd(ctd); +} +EXPORT_SYMBOL(vpdma_add_abort_channel_ctd); + static void dump_dtd(struct vpdma_dtd *dtd) { int dir, chan; diff --git a/drivers/media/platform/ti-vpe/vpdma.h b/drivers/media/platform/ti-vpe/vpdma.h index 32b9ed5191c5..4dafc1bcf116 100644 --- a/drivers/media/platform/ti-vpe/vpdma.h +++ b/drivers/media/platform/ti-vpe/vpdma.h @@ -163,6 +163,8 @@ enum vpdma_channel { #define VIP_CHAN_YUV_PORTB_OFFSET 2 #define VIP_CHAN_RGB_PORTB_OFFSET 1 +#define VPDMA_MAX_CHANNELS 256 + /* flags for VPDMA data descriptors */ #define VPDMA_DATA_ODD_LINE_SKIP (1 << 0) #define VPDMA_DATA_EVEN_LINE_SKIP (1 << 1) @@ -219,6 +221,8 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, struct vpdma_buf *adb); void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, enum vpdma_channel chan); +void vpdma_add_abort_channel_ctd(struct vpdma_desc_list *list, + int chan_num); void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, const struct v4l2_rect *c_rect, const struct vpdma_data_format *fmt, dma_addr_t dma_addr, @@ -233,6 +237,8 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width, const struct vpdma_data_format *fmt, dma_addr_t dma_addr, enum vpdma_channel chan, int field, u32 flags, int frame_width, int frame_height, int start_h, int start_v); +int vpdma_list_cleanup(struct vpdma_data *vpdma, int list_num, + int *channels, int size); /* vpdma list interrupt management */ void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int irq_num,