From patchwork Wed Oct 31 16:03:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10662885 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 204804B7E for ; Wed, 31 Oct 2018 16:03:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0FA102B234 for ; Wed, 31 Oct 2018 16:03:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 038122B264; Wed, 31 Oct 2018 16:03:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A158C2B234 for ; Wed, 31 Oct 2018 16:03:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729695AbeKABBz (ORCPT ); Wed, 31 Oct 2018 21:01:55 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:53437 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729723AbeKABBz (ORCPT ); Wed, 31 Oct 2018 21:01:55 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gHsxc-0005lc-Be; Wed, 31 Oct 2018 16:03:12 +0000 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gHsxc-0005Ki-1l; Wed, 31 Oct 2018 16:03:12 +0000 From: Ben Dooks To: dan.j.williams@intel.com, vkoul@kernel.org Cc: ldewangan@nvidia.com, dmaengine@vger.kernel.org, linux-tegra@vger.kernel.org, Ben Dooks Subject: [PATCH 1/6] dma: tegra: avoid overflow of byte tracking Date: Wed, 31 Oct 2018 16:03:04 +0000 Message-Id: <20181031160309.20408-2-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181031160309.20408-1-ben.dooks@codethink.co.uk> References: <20181031160309.20408-1-ben.dooks@codethink.co.uk> MIME-Version: 1.0 Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The dma_desc->bytes_transferred counter tracks the number of bytes moved by the DMA channel. This is then used to calculate the information passed back in the in the tegra_dma_tx_status callback, which is usually fine. When the DMA channel is configured as continous, then the bytes_transferred counter will increase over time and eventually overflow to become negative so the residue count will become invalid and the ALSA sound-dma code will report invalid hardware pointer values to the application. This results in some users becoming confused about the playout position and putting audio data in the wrong place. To fix this issue, always ensure the bytes_transferred field is modulo the size of the request. We only do this for the case of the cyclic transfer done ISR as anyone attempting to move 2GiB of DMA data in one transfer is unlikely. Note, we don't fix the issue that we should /never/ transfer a negative number of bytes so we could make those fields unsigned. Signed-off-by: Ben Dooks Reviewed-by: Dmitry Osipenko --- drivers/dma/tegra20-apb-dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 9a558e30c461..8219ab88a507 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -636,7 +636,10 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc, sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), node); dma_desc = sgreq->dma_desc; - dma_desc->bytes_transferred += sgreq->req_len; + /* if we dma for long enough the transfer count will wrap */ + dma_desc->bytes_transferred = + (dma_desc->bytes_transferred + sgreq->req_len) % + dma_desc->bytes_requested; /* Callback need to be call */ if (!dma_desc->cb_count)