From patchwork Fri Aug 9 11:11:34 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chanho Park X-Patchwork-Id: 2841883 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id CD89CBF546 for ; Fri, 9 Aug 2013 11:11:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9F26920276 for ; Fri, 9 Aug 2013 11:11:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 698B720272 for ; Fri, 9 Aug 2013 11:11:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967570Ab3HILLv (ORCPT ); Fri, 9 Aug 2013 07:11:51 -0400 Received: from mailout3.samsung.com ([203.254.224.33]:59058 "EHLO mailout3.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S967445Ab3HILLu (ORCPT ); Fri, 9 Aug 2013 07:11:50 -0400 Received: from epcpsbgr2.samsung.com (u142.gpu120.samsung.co.kr [203.254.230.142]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MR900KAUGEZLSP0@mailout3.samsung.com> for linux-samsung-soc@vger.kernel.org; Fri, 09 Aug 2013 20:11:47 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.116]) by epcpsbgr2.samsung.com (EPCPMTA) with SMTP id E8.D6.08825.37EC4025; Fri, 09 Aug 2013 20:11:47 +0900 (KST) X-AuditID: cbfee68e-b7f276d000002279-80-5204ce733206 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 52.CB.32250.27EC4025; Fri, 09 Aug 2013 20:11:47 +0900 (KST) Received: from localhost.localdomain ([10.252.81.149]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MR9006CLGFKN680@mmp1.samsung.com>; Fri, 09 Aug 2013 20:11:46 +0900 (KST) From: Chanho Park To: vinod.koul@intel.com, djbw@fb.com Cc: jaswinder.singh@linaro.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kyungmin.park@samsung.com, Chanho Park Subject: [PATCH-RESEND 2/2] dma: pl330: add pl330_prep_dma_sg to transfer from sglist to sglist Date: Fri, 09 Aug 2013 20:11:34 +0900 Message-id: <1376046694-2638-3-git-send-email-chanho61.park@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1376046694-2638-1-git-send-email-chanho61.park@samsung.com> References: <1376046694-2638-1-git-send-email-chanho61.park@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrKLMWRmVeSWpSXmKPExsWyRsSkRLf4HEuQwbdJ3BaX92tbbO5/wGYx edN9RouzTW/YLTY9vsZqMeP8PiaLl337WRzYPSY2v2P3WLznJZPHnWt72Dw2L6n36NuyitHj 8ya5ALYoLpuU1JzMstQifbsEroyNR7+zFlwwruiYMIG9gXG6ZhcjJ4eEgInE4+072SFsMYkL 99azgdhCAksZJa4vke1i5ACrubVcvouRCyi8iFFi3+zrrBBOG5PEmd2nmEEa2AR0JbY8f8UI 0iAioCqx/rIYSA2zwHpGiR+bZoENFRZIlNix5zYLiM0CVHN7QidYL6+Ah8TNKe8YIZYpSMyZ ZANicgp4Siy9bgJiCgFVnPtoCjJRQmARu8TN59+ZIKYISHybfIgFolNWYtMBZohPJCUOrrjB MoFReAEjwypG0dSC5ILipPQiI73ixNzi0rx0veT83E2MwCA//e9Z3w7GmwesDzEmA42byCwl mpwPjJK8knhDYzMjC1MTU2Mjc0sz0oSVxHnVWqwDhQTSE0tSs1NTC1KL4otKc1KLDzEycXBK NTAGTBfRDZcs8RCV2PVl9nHH1rkbc+Pd0ybJHmk7M+P05st6q++xFhy8NXnVW/PiXKuAd9Wt 1c91b8b2LbPwPnbo8e41f+xeVT2a4vnnSEqu+gtdnY2/X75MkJr2eLnb7MnzhAuaHb5/U3m5 v2Viw0sV/amTlNfr39mhs85g5uy4i4ZOhz8FZGguVGIpzkg01GIuKk4EAG2M/Y6IAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrMIsWRmVeSWpSXmKPExsVy+t9jAd3icyxBBu/PMllc3q9tsbn/AZvF 5E33GS3ONr1ht9j0+BqrxYzz+5gsXvbtZ3Fg95jY/I7dY/Gel0wed67tYfPYvKTeo2/LKkaP z5vkAtiiGhhtMlITU1KLFFLzkvNTMvPSbZW8g+Od403NDAx1DS0tzJUU8hJzU22VXHwCdN0y c4BOUVIoS8wpBQoFJBYXK+nbYZoQGuKmawHTGKHrGxIE12NkgAYS1jBmbDz6nbXggnFFx4QJ 7A2M0zW7GDk4JARMJG4tl+9i5AQyxSQu3FvP1sXIxSEksIhRYt/s66wQThuTxJndp5hBqtgE dCW2PH/FCNIsIqAqsf6yGEgNs8B6Rokfm2axgdQICyRK7NhzmwXEZgGquT2hE6yXV8BD4uaU d4wQixUk5kyyATE5BTwlll43ATGFgCrOfTSdwMi7gJFhFaNoakFyQXFSeq6hXnFibnFpXrpe cn7uJkZwFD2T2sG4ssHiEKMAB6MSD6/iduYgIdbEsuLK3EOMEhzMSiK82yewBAnxpiRWVqUW 5ccXleakFh9iTAY6aSKzlGhyPjDC80riDY1NzIwsjcwNLYyMzUkTVhLnPdBqHSgkkJ5Ykpqd mlqQWgSzhYmDU6qB0X/l366jNhu4vbt8V8T9ef59Qsfjbl/OgKCWmf1VlTKtn7WfvDrS8s1o r2Rkvavk/tdPX9798p/fNN4hMaL95oUXEx783xhe9P7blhsKk2NSLX/z3Fwxb6agI5PLmqp3 btJrrV9GMtpFrdX89t76EOO1invfJlxmuPOlNy7xaIBWo5VLujZbqRJLcUaioRZzUXEiADmS j0fmAgAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds prep_dma_sg function to transfer memory to memory which mapped in scatter/gather list. The patch move get_burst_len to upwards to call in the __pl330_prep_dma_mecpy. Some duplicated code was splitted off from prep_dma_memcpy. Signed-off-by: Chanho Park Acked-by : Jassi Brar Signed-off-by: Kyungmin Park --- drivers/dma/pl330.c | 179 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 138 insertions(+), 41 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index ebc2af9..b6d9087 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2636,9 +2636,33 @@ static inline void fill_px(struct pl330_xfer *px, px->src_addr = src; } +/* Call after fixing burst size */ +static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) +{ + struct dma_pl330_chan *pch = desc->pchan; + struct pl330_info *pi = &pch->dmac->pif; + int burst_len; + + burst_len = pi->pcfg.data_bus_width / 8; + burst_len *= pi->pcfg.data_buf_dep; + burst_len >>= desc->rqcfg.brst_size; + + /* src/dst_burst_len can't be more than 16 */ + if (burst_len > 16) + burst_len = 16; + + while (burst_len > 1) { + if (!(len % (burst_len << desc->rqcfg.brst_size))) + break; + burst_len--; + } + + return burst_len; +} + static struct dma_pl330_desc * __pl330_prep_dma_memcpy(struct dma_pl330_chan *pch, dma_addr_t dst, - dma_addr_t src, size_t len) + dma_addr_t src, size_t len, int burst) { struct dma_pl330_desc *desc = pl330_get_desc(pch); @@ -2660,31 +2684,23 @@ __pl330_prep_dma_memcpy(struct dma_pl330_chan *pch, dma_addr_t dst, */ fill_px(&desc->px, dst, src, len); - return desc; -} - -/* Call after fixing burst size */ -static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) -{ - struct dma_pl330_chan *pch = desc->pchan; - struct pl330_info *pi = &pch->dmac->pif; - int burst_len; - - burst_len = pi->pcfg.data_bus_width / 8; - burst_len *= pi->pcfg.data_buf_dep; - burst_len >>= desc->rqcfg.brst_size; - - /* src/dst_burst_len can't be more than 16 */ - if (burst_len > 16) - burst_len = 16; + desc->rqcfg.src_inc = 1; + desc->rqcfg.dst_inc = 1; + desc->req.rqtype = MEMTOMEM; - while (burst_len > 1) { - if (!(len % (burst_len << desc->rqcfg.brst_size))) + while (burst > 1) { + if (!(len % burst)) break; - burst_len--; + burst /= 2; } - return burst_len; + desc->rqcfg.brst_size = 0; + while (burst != (1 << desc->rqcfg.brst_size)) + desc->rqcfg.brst_size++; + + desc->rqcfg.brst_len = get_burst_len(desc, len); + + return desc; } static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( @@ -2786,28 +2802,12 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, pi = &pch->dmac->pif; - desc = __pl330_prep_dma_memcpy(pch, dst, src, len); - if (!desc) - return NULL; - - desc->rqcfg.src_inc = 1; - desc->rqcfg.dst_inc = 1; - desc->req.rqtype = MEMTOMEM; - /* Select max possible burst size */ burst = pi->pcfg.data_bus_width / 8; - while (burst > 1) { - if (!(len % burst)) - break; - burst /= 2; - } - - desc->rqcfg.brst_size = 0; - while (burst != (1 << desc->rqcfg.brst_size)) - desc->rqcfg.brst_size++; - - desc->rqcfg.brst_len = get_burst_len(desc, len); + desc = __pl330_prep_dma_memcpy(pch, dst, src, len, burst); + if (!desc) + return NULL; desc->txd.flags = flags; @@ -2837,6 +2837,102 @@ static void __pl330_giveback_desc(struct dma_pl330_dmac *pdmac, } static struct dma_async_tx_descriptor * +pl330_prep_dma_sg(struct dma_chan *chan, + struct scatterlist *dst_sg, unsigned int dst_nents, + struct scatterlist *src_sg, unsigned int src_nents, + unsigned long flags) +{ + struct dma_pl330_desc *first, *desc = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); + struct pl330_info *pi; + dma_addr_t src, dst; + size_t len, dst_len = 0, src_len = 0; + int burst; + + if (unlikely(!pch)) + return NULL; + + pi = &pch->dmac->pif; + + /* basic sanity checks */ + if (dst_nents == 0 || src_nents == 0) + return NULL; + + if (dst_sg == NULL || src_sg == NULL) + return NULL; + + first = NULL; + + /* Select max possible burst size */ + burst = pi->pcfg.data_bus_width / 8; + + /* get prepared for the loop */ + dst_len = sg_dma_len(dst_sg); + src_len = sg_dma_len(src_sg); + + while (true) { + len = min_t(size_t, src_len, dst_len); + + if (len == 0) + goto fetch; + + dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) - dst_len; + src = sg_dma_address(src_sg) + sg_dma_len(src_sg) - src_len; + + desc = __pl330_prep_dma_memcpy(pch, dst, src, len, burst); + if (!desc) { + struct dma_pl330_dmac *pdmac = pch->dmac; + + dev_err(pdmac->pif.dev, + "%s:%d Unable to fetch desc\n", + __func__, __LINE__); + + __pl330_giveback_desc(pdmac, first); + + return NULL; + } + if (!first) + first = desc; + else + list_add_tail(&desc->node, &first->node); + + desc->txd.flags = flags; + + dst_len -= len; + src_len -= len; + +fetch: + /* fetch the next dst scatterlist entry */ + if (dst_len == 0) { + /* no more entries: we're done */ + if (dst_nents == 0) + break; + /* fetch the next entry: if there are no more: done */ + dst_sg = sg_next(dst_sg); + if (dst_sg == NULL) + break; + dst_nents--; + dst_len = sg_dma_len(dst_sg); + } + + /* fetch the next src scatterlist entry */ + if (src_len == 0) { + /* no more entries: we're done */ + if (src_nents == 0) + break; + /* fetch the next entry: if there are no more: done */ + src_sg = sg_next(src_sg); + if (src_sg == NULL) + break; + src_nents--; + src_len = sg_dma_len(src_sg); + } + } + + return &first->txd; +} + +static struct dma_async_tx_descriptor * pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flg, void *context) @@ -3029,6 +3125,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pd->device_alloc_chan_resources = pl330_alloc_chan_resources; pd->device_free_chan_resources = pl330_free_chan_resources; pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy; + pd->device_prep_dma_sg = pl330_prep_dma_sg; pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic; pd->device_tx_status = pl330_tx_status; pd->device_prep_slave_sg = pl330_prep_slave_sg;