From patchwork Wed Sep 30 17:42:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Jarzmik X-Patchwork-Id: 7301261 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.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id EA84EBEEA4 for ; Wed, 30 Sep 2015 17:49:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1C84120660 for ; Wed, 30 Sep 2015 17:49:32 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CFFC820650 for ; Wed, 30 Sep 2015 17:49:30 +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 1ZhLTt-0006Vi-EC; Wed, 30 Sep 2015 17:47:53 +0000 Received: from smtp06.smtpout.orange.fr ([80.12.242.128] helo=smtp.smtpout.orange.fr) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZhLTq-0006SA-Ju for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2015 17:47:51 +0000 Received: from belgarion.home ([86.199.64.143]) by mwinf5d41 with ME id PVnU1r00535SnZi03VnUrl; Wed, 30 Sep 2015 19:47:29 +0200 X-ME-Helo: belgarion.home X-ME-Date: Wed, 30 Sep 2015 19:47:29 +0200 X-ME-IP: 86.199.64.143 From: Robert Jarzmik To: Daniel Mack , Haojian Zhuang , Robert Jarzmik , Vinod Koul Subject: [PATCH v2 2/2] dma: pxa_dma: fix residue corner case Date: Wed, 30 Sep 2015 19:42:15 +0200 Message-Id: <1443634935-28989-2-git-send-email-robert.jarzmik@free.fr> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1443634935-28989-1-git-send-email-robert.jarzmik@free.fr> References: <1443634935-28989-1-git-send-email-robert.jarzmik@free.fr> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150930_104750_982690_72C154C8 X-CRM114-Status: GOOD ( 13.65 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org 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=-4.2 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_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 A very tiny temporal window exists in the residue calculation where : - upon entering residue calculation, the transfer is ongoing - when reading the current transfer pointer, it just changed to the "finisher/linker" descriptor In this case, the residue returned is the whole transfer length instead of 0. Fix it. This appears almost in one extreme case, where the driver is used by older clients which inquire for residue in interrupt context, such as the smsc91x ethernet driver, in a tight loop : interrupt_handler() dmaengine_submit() do { dmaengine_tx_status() } while (residue > 0 || status != DMA_ERROR) Signed-off-by: Robert Jarzmik --- Since v1: reworded the commit message for typos --- drivers/dma/pxa_dma.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 7d3ff56caa0a..51f294e4227c 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -1185,6 +1185,16 @@ static unsigned int pxad_residue(struct pxad_chan *chan, else curr = phy_readl_relaxed(chan->phy, DTADR); + /* + * curr has to be actually read before checking descriptor + * completion, so that a curr inside a status updater + * descriptor implies the following test returns true, and + * preventing reordering of curr load and the test. + */ + rmb(); + if (is_desc_completed(vd)) + goto out; + for (i = 0; i < sw_desc->nb_desc - 1; i++) { hw_desc = sw_desc->hw_desc[i]; if (sw_desc->hw_desc[0]->dcmd & PXA_DCMD_INCSRCADDR)