From patchwork Tue Apr 2 12:01:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chanho Park X-Patchwork-Id: 2377621 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id BB7E13FD8C for ; Tue, 2 Apr 2013 12:05:04 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UMzvU-0007qy-4Y; Tue, 02 Apr 2013 12:02:56 +0000 Received: from mailout4.samsung.com ([203.254.224.34]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UMzv8-0007k0-TF for linux-arm-kernel@lists.infradead.org; Tue, 02 Apr 2013 12:02:36 +0000 Received: from epcpsbgr2.samsung.com (u142.gpu120.samsung.co.kr [203.254.230.142]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MKM00B9GMRREYR0@mailout4.samsung.com> for linux-arm-kernel@lists.infradead.org; Tue, 02 Apr 2013 21:02:31 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [203.254.230.44]) by epcpsbgr2.samsung.com (EPCPMTA) with SMTP id 7B.DE.07735.7D8CA515; Tue, 02 Apr 2013 21:02:31 +0900 (KST) X-AuditID: cbfee68e-b7f946d000001e37-b8-515ac8d72d1d Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id A8.F3.17838.7D8CA515; Tue, 02 Apr 2013 21:02:31 +0900 (KST) Received: from localhost.localdomain ([10.90.51.45]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MKM00FMEMRYX910@mmp1.samsung.com>; Tue, 02 Apr 2013 21:02:31 +0900 (KST) From: Chanho Park To: vinod.koul@intel.com, djbw@fb.com Subject: [PATCH 2/2] dma: pl330: add pl330_prep_dma_sg to transfer from sglist to sglist Date: Tue, 02 Apr 2013 21:01:16 +0900 Message-id: <1364904076-3130-3-git-send-email-chanho61.park@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1364904076-3130-1-git-send-email-chanho61.park@samsung.com> References: <1364904076-3130-1-git-send-email-chanho61.park@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpmkeLIzCtJLcpLzFFi42I5/e+Zju71E1GBBrtXG1q8OfmHzeLyfm2L zf0P2Cwmb7rPaHG26Q27xabH11gtZpzfx2Rxu3EFm8XLvv0sDpweE5vfsXss3vOSyePOtT1s HpuX1Hv0bVnF6PF5k1wAWxSXTUpqTmZZapG+XQJXxvo9y5gKrhlXvF34m6WBcZ5mFyMnh4SA icTfi4tZIGwxiQv31rN1MXJxCAksY5Q48eAZO0xRc/dSVojEIkaJ7T82M0E4LUwSq648ZwKp YhPQldjy/BVjFyMHh4iAqsT6y2IgNcwCjxklZlzqB1shLBAlse/MKVYQmwWo5vWVB2wgNq+A h0Tzl8msIL0SAgoScybZgIQ5BTwl/v/fBHaEEFDJyudNYHslBLaxS0zbc4sZYo6AxLfJh1gg emUlNh1ghjhaUuLgihssExiFFzAyrGIUTS1ILihOSi8y0itOzC0uzUvXS87P3cQIiYC+HYw3 D1gfYkwGGjeRWUo0OR8YQXkl8YbGZkYWpiamxkbmlmakCSuJ86q1WAcKCaQnlqRmp6YWpBbF F5XmpBYfYmTi4JRqYHRVepS3+LjnAoONC7MbpXOWG+8UM8lqNZXpMXs8y9UkS+y5n6612OyY vAvv7J6sOV0Rzv9xpxvr9+xHH2d9EbgxX55rgl/y2XWy/2YbV0/pmRBk2ySzt1FEUX1S1X1/ pVn75J7PumDk/bdK8vinHSlsM8XWbeJY11DyqO7HsZbjDGx3Fs9hM1ZiKc5INNRiLipOBAA1 AcjQlgIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrAIsWRmVeSWpSXmKPExsVy+t9jAd3rJ6ICDXa90LZ4c/IPm8Xl/doW m/sfsFlM3nSf0eJs0xt2i02Pr7FazDi/j8niduMKNouXfftZHDg9Jja/Y/dYvOclk8eda3vY PDYvqffo27KK0ePzJrkAtqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8 xNxUWyUXnwBdt8wcoKOUFMoSc0qBQgGJxcVK+naYJoSGuOlawDRG6PqGBMH1GBmggYR1jBnr 9yxjKrhmXPF24W+WBsZ5ml2MnBwSAiYSzd1LWSFsMYkL99azdTFycQgJLGKU2P5jMxOE08Ik serKcyaQKjYBXYktz18xdjFycIgIqEqsvywGUsMs8JhRYsalfhaQGmGBKIl9Z06BTWUBqnl9 5QEbiM0r4CHR/GUyK0ivhICCxJxJNiBhTgFPif//N7GD2EJAJSufNzFNYORdwMiwilE0tSC5 oDgpPddQrzgxt7g0L10vOT93EyM4vp5J7WBc2WBxiFGAg1GJh9dhTmSgEGtiWXFl7iFGCQ5m JRHeuJ1RgUK8KYmVValF+fFFpTmpxYcYk4GOmsgsJZqcD4z9vJJ4Q2MTMyNLIzNjE3NjY9KE lcR5D7RaBwoJpCeWpGanphakFsFsYeLglGpgnH9r535Zz99p0krlSfWm/z6ZrFvMeuJ+lfkO ueobnTrypdUqJ0OixafdbuY9Unbt8JpwXQXFVYbyWYZq35+eZPnzv9r/WEfkD/MpayzvazBa bj+pVXR8/syjHHufKL0onnRh36mSaVIV0ksvV6woS+poZZOSqfZzDjbLuaSR2GC4JmWnhtwG JZbijERDLeai4kQAcz2usPMCAAA= DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130402_080235_239066_9EE0EF24 X-CRM114-Status: GOOD ( 18.71 ) X-Spam-Score: -9.2 (---------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-9.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [203.254.224.34 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -2.3 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-samsung-soc@vger.kernel.org, boojin.kim@samsung.com, jaswinder.singh@linaro.org, kyungmin.park@samsung.com, myungjoo.ham@samsung.com, Chanho Park , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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 Signed-off-by: Myungjoo Ham 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 47ed13f..4c1e301 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2654,9 +2654,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); @@ -2678,31 +2702,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( @@ -2767,28 +2783,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; @@ -2818,6 +2818,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) @@ -2983,6 +3079,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;