From patchwork Mon Feb 17 11:29:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Mack X-Patchwork-Id: 3662801 Return-Path: X-Original-To: patchwork-linux-arm@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 BEF35BF13A for ; Mon, 17 Feb 2014 11:31:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CF329201E7 for ; Mon, 17 Feb 2014 11:31:27 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C79F5201D3 for ; Mon, 17 Feb 2014 11:31:26 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WFMOr-0005mG-Uk; Mon, 17 Feb 2014 11:30:15 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WFMOJ-0002h6-33; Mon, 17 Feb 2014 11:29:39 +0000 Received: from mail-ee0-x236.google.com ([2a00:1450:4013:c00::236]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WFMOG-0002fs-DL for linux-arm-kernel@lists.infradead.org; Mon, 17 Feb 2014 11:29:37 +0000 Received: by mail-ee0-f54.google.com with SMTP id e53so6954761eek.41 for ; Mon, 17 Feb 2014 03:29:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=w2INsd+lGiMdylJNPfqUhEYHHofUzKW8jModHXoK0Fk=; b=sL9QROnxY/IO9h0iU0lGh6kZScKctP3gb7Tbv3DhIscc8Jwecbw20p+JKyeGewVD1i llAMpP57DkkWx2v2mK9S+fNJYaaDjU0x1vIy4WXDNl5RxXRhSfdT+8SucZTC3MfMpKJp kiSd4B9iMSCyWuhh8dNUvJjPgD/W1ndAqtC0J/h7CkaoS7ZGbMuds8Zb/EJLNeCMqvas HcgDCa5OeTUN3KDINZP1wv8qnl3tmmGHDC/M0+GZMMA2/i0Pp+INrPOmKwJ7WAJsgIym orewLOC99vZt2XE+MMwDulqDbvKp5oRSBHzh7oDnc73Njzjili/cpN48os1fvHZcCN1g yo8A== X-Received: by 10.14.95.134 with SMTP id p6mr1539930eef.73.1392636554208; Mon, 17 Feb 2014 03:29:14 -0800 (PST) Received: from tamtam.fritz.box ([2001:4dd0:ff00:9394:224:d7ff:fec6:a0ec]) by mx.google.com with ESMTPSA id k41sm56405181een.19.2014.02.17.03.29.11 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Feb 2014 03:29:13 -0800 (PST) From: Daniel Mack To: vinod.koul@intel.com Subject: [PATCH RESEND] dma: mmp_pdma: add support for residue reporting Date: Mon, 17 Feb 2014 12:29:06 +0100 Message-Id: <1392636546-15541-1-git-send-email-zonque@gmail.com> X-Mailer: git-send-email 1.8.5.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140217_062936_587592_64DE750F X-CRM114-Status: GOOD ( 22.35 ) X-Spam-Score: 0.9 (/) Cc: wangx@marvell.com, linux@arm.linux.org.uk, nico@fluxnic.net, haojian.zhuang@gmail.com, Daniel Mack , cxie4@marvell.com, ezequiel.garcia@free-electrons.com, djbw@fb.com, eric.y.miao@gmail.com, 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 X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, KHOP_BIG_TO_CC, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=no 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 A channel can accommodate more than one transaction, each consisting of multiple descriptors, the last of which has the DCMD_ENDIRQEN bit set. In order to report the channel's residue, we hence have to walk the list of running descriptors, look for those which match the cookie, and then try to find the descriptor which defines upper and lower boundaries that embrace the current transport pointer. Once it is found, walk forward until we find the descriptor that tells us about the end of a transaction via a set DCMD_ENDIRQEN bit. Signed-off-by: Daniel Mack --- Hi Vinod, everyone, I'd like to get the disussion regarding this patch started again which left off here: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/217429.html I think the biggest issue in the previous discussion was a confusion about the term 'descriptor', as it refers to both the internal pdma implementation detail as well as the handle used in the dma subsystem. I hope I explained that well enough in the link above. Many thanks, Daniel drivers/dma/mmp_pdma.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index b439679..2eb1c10 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -29,8 +29,8 @@ #define DALGN 0x00a0 #define DINT 0x00f0 #define DDADR 0x0200 -#define DSADR 0x0204 -#define DTADR 0x0208 +#define DSADR(n) (0x0204 + ((n) << 4)) +#define DTADR(n) (0x0208 + ((n) << 4)) #define DCMD 0x020c #define DCSR_RUN BIT(31) /* Run Bit (read / write) */ @@ -748,11 +748,92 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, return 0; } +static unsigned int mmp_pdma_residue(struct mmp_pdma_chan *chan, + dma_cookie_t cookie) +{ + struct mmp_pdma_desc_sw *sw; + u32 curr, residue = 0; + bool passed = false; + bool cyclic = chan->cyclic_first != NULL; + + /* + * If the channel does not have a phy pointer anymore, it has already + * been completed. Therefore, its residue is 0. + */ + if (!chan->phy) + return 0; + + if (chan->dir == DMA_DEV_TO_MEM) + curr = readl(chan->phy->base + DTADR(chan->phy->idx)); + else + curr = readl(chan->phy->base + DSADR(chan->phy->idx)); + + list_for_each_entry(sw, &chan->chain_running, node) { + u32 start, end, len; + + if (chan->dir == DMA_DEV_TO_MEM) + start = sw->desc.dtadr; + else + start = sw->desc.dsadr; + + len = sw->desc.dcmd & DCMD_LENGTH; + end = start + len; + + /* + * 'passed' will be latched once we found the descriptor which + * lies inside the boundaries of the curr pointer. All + * descriptors that occur in the list _after_ we found that + * partially handled descriptor are still to be processed and + * are hence added to the residual bytes counter. + */ + + if (passed) { + residue += len; + } else if (curr >= start && curr <= end) { + residue += end - curr; + passed = true; + } + + /* + * Descriptors that have the ENDIRQEN bit set mark the end of a + * transaction chain, and the cookie assigned with it has been + * returned previously from mmp_pdma_tx_submit(). + * + * In case we have multiple transactions in the running chain, + * and the cookie does not match the one the user asked us + * about, reset the state variables and start over. + * + * This logic does not apply to cyclic transactions, where all + * descriptors have the ENDIRQEN bit set, and for which we + * can't have multiple transactions on one channel anyway. + */ + if (cyclic || !(sw->desc.dcmd & DCMD_ENDIRQEN)) + continue; + + if (sw->async_tx.cookie == cookie) { + return residue; + } else { + residue = 0; + passed = false; + } + } + + /* We should only get here in case of cyclic transactions */ + return residue; +} + static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, struct dma_tx_state *txstate) { - return dma_cookie_status(dchan, cookie, txstate); + struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan); + enum dma_status ret; + + ret = dma_cookie_status(dchan, cookie, txstate); + if (likely(ret != DMA_ERROR)) + dma_set_residue(txstate, mmp_pdma_residue(chan, cookie)); + + return ret; } /**