From patchwork Thu Apr 17 14:40:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 4009141 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 31899BFF02 for ; Thu, 17 Apr 2014 14:43:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 56ADC20395 for ; Thu, 17 Apr 2014 14:43:40 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (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 79B3C2038E for ; Thu, 17 Apr 2014 14:43:39 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WanUr-0004Nh-MG; Thu, 17 Apr 2014 14:41:01 +0000 Received: from galois.linutronix.de ([2001:470:1f0b:db:abcd:42:0:1]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WanUi-0004I6-CH for linux-arm-kernel@lists.infradead.org; Thu, 17 Apr 2014 14:40:54 +0000 Received: from localhost ([127.0.0.1] helo=ionos.tec.linutronix.de) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1WanUL-0004jy-Jz; Thu, 17 Apr 2014 16:40:29 +0200 Message-Id: <20140417143249.095049101@linutronix.de> User-Agent: quilt/0.60-1 Date: Thu, 17 Apr 2014 14:40:44 -0000 From: Thomas Gleixner To: dmaengine@vger.kernel.org Subject: [patch 1/6] dma: edma: Sanitize residue reporting References: <20140417133737.892475126@linutronix.de> Content-Disposition: inline; filename=dma-edma-sanitize-residue-reporting.patch X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1, SHORTCIRCUIT=-0.0001 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140417_074052_652644_9BA75109 X-CRM114-Status: GOOD ( 11.77 ) X-Spam-Score: -0.7 (/) Cc: vinod.koul@intel.com, nsekhar@ti.com, Peter Ujfalusi , joelf@ti.com, dan.j.williams@intel.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=-2.6 required=5.0 tests=BAYES_00,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 The residue reporting in edma_tx_status() is just broken. It blindly walks the psets and recalculates the lenght of the transfer from the hardware parameters. For cyclic transfers it adds the link pset, which results in interestingly large residues. For non-cyclic it adds the dummy pset, which is stupid as well. Aside of that it's silly to walk through the pset params when the per descriptor residue is known at the point of creating it. Store the information in edma_desc and use it. Signed-off-by: Thomas Gleixner Reviewed-by: Joel Fernandes --- drivers/dma/edma.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) Index: linux-2.6/drivers/dma/edma.c =================================================================== --- linux-2.6.orig/drivers/dma/edma.c +++ linux-2.6/drivers/dma/edma.c @@ -64,6 +64,7 @@ struct edma_desc { int absync; int pset_nr; int processed; + u32 residue; struct edmacc_param pset[0]; }; @@ -416,6 +417,7 @@ static struct dma_async_tx_descriptor *e } edesc->pset_nr = sg_len; + edesc->residue = 0; /* Allocate a PaRAM slot, if needed */ nslots = min_t(unsigned, MAX_NR_SG, sg_len); @@ -450,6 +452,7 @@ static struct dma_async_tx_descriptor *e } edesc->absync = ret; + edesc->residue += sg_dma_len(sg); /* If this is the last in a current SG set of transactions, enable interrupts so that next set is processed */ @@ -527,6 +530,7 @@ static struct dma_async_tx_descriptor *e edesc->cyclic = 1; edesc->pset_nr = nslots; + edesc->residue = buf_len; dev_dbg(dev, "%s: nslots=%d\n", __func__, nslots); dev_dbg(dev, "%s: period_len=%d\n", __func__, period_len); @@ -622,6 +626,7 @@ static void edma_callback(unsigned ch_nu vchan_cyclic_callback(&edesc->vdesc); } else if (edesc->processed == edesc->pset_nr) { dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num); + edesc->residue = 0; edma_stop(echan->ch_num); vchan_cookie_complete(&edesc->vdesc); edma_execute(echan); @@ -754,25 +759,6 @@ static void edma_issue_pending(struct dm spin_unlock_irqrestore(&echan->vchan.lock, flags); } -static size_t edma_desc_size(struct edma_desc *edesc) -{ - int i; - size_t size; - - if (edesc->absync) - for (size = i = 0; i < edesc->pset_nr; i++) - size += (edesc->pset[i].a_b_cnt & 0xffff) * - (edesc->pset[i].a_b_cnt >> 16) * - edesc->pset[i].ccnt; - else - size = (edesc->pset[0].a_b_cnt & 0xffff) * - (edesc->pset[0].a_b_cnt >> 16) + - (edesc->pset[0].a_b_cnt & 0xffff) * - (SZ_64K - 1) * edesc->pset[0].ccnt; - - return size; -} - /* Check request completion status */ static enum dma_status edma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, @@ -789,12 +775,10 @@ static enum dma_status edma_tx_status(st spin_lock_irqsave(&echan->vchan.lock, flags); vdesc = vchan_find_desc(&echan->vchan, cookie); - if (vdesc) { - txstate->residue = edma_desc_size(to_edma_desc(&vdesc->tx)); - } else if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) { - struct edma_desc *edesc = echan->edesc; - txstate->residue = edma_desc_size(edesc); - } + if (vdesc) + txstate->residue = to_edma_desc(&vdesc->tx)->residue; + else if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) + txstate->residue = echan->edesc->residue; spin_unlock_irqrestore(&echan->vchan.lock, flags); return ret;