Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp5261927img; Wed, 27 Mar 2019 05:23:28 -0700 (PDT) X-Google-Smtp-Source: APXvYqwAVfVjDflKUxkKnV55ZCgR3y47xuTss/E1uabEVzbF9o78PT37IanlP8UwEDIZbl3IKr1p X-Received: by 2002:a63:114d:: with SMTP id 13mr12737200pgr.216.1553689408115; Wed, 27 Mar 2019 05:23:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553689408; cv=none; d=google.com; s=arc-20160816; b=B2PQ0b/PYoFjhuFnUHXrrhssueeLk2MkMouXwqBsWba+jMLxr8cUDzI7PZECBD44bc dmaMiRk01sJcVwD9kZVv0MO62sqgQXrTGNb2kEjdvwEuCcVbz8624yjXOci6AsHsUjdN f/F7mMzgzI3bUegyKnPh9W4wYCdS2d85aG936zn4B77Gt8Htv+mqQSGPW7yQNz/IEKcd Rw6bUo0ZnCv1J8BtYUSLMYG2E0oQ2HcwmmEp5NkBGerGFdYgx6uvRuVsxR4h1YiRlWim 50tL3GOwaAkLhHh9gFTFv81wZPq7P0jyhfgTyrCuwyCM0h4r7A5imBba463dcM0ZKv4B mzUA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:date:subject:cc :to:from; bh=Ayjz14w1GNigXDR5CKTTn64DzxBR4DJ9CdqQ2KycxAU=; b=PLKq9p7ztmv4ShQBrhdLkp6n0dAtIXnlQMs8xmkJgduId5AeWZTMp14sn8tAC0Pgvr +4Rtb1GIz6cYGZ4OS4xm7789Fv2d5bwLXpioXHlXu98346v+fqOIbuzsaVoDM0R+OU3D jTRk1mj4EQegcCZTrOva0LZBxVdzmsKd9s568IJHQkty8SL1wsN80HgMTm+WvbXKOwcq FghORjOL2cLKXzZJnw5G1MwYYBtAOY2FxVuct+1QnpEz42677yI4IPFuQaJuXwO91wak U+k/9alQdSwPOmc9BLJZ8Ph9gJu7nKSGAvnjZKMJKiYYFHu+ppkk2hFY2geoiGvWR1cm z8IQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a72si18214209pfj.216.2019.03.27.05.23.12; Wed, 27 Mar 2019 05:23:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728806AbfC0MWd (ORCPT + 99 others); Wed, 27 Mar 2019 08:22:33 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:5043 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726233AbfC0MWd (ORCPT ); Wed, 27 Mar 2019 08:22:33 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2RC8XTr021122; Wed, 27 Mar 2019 13:22:24 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2rddhtga81-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 27 Mar 2019 13:22:24 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 447BA31; Wed, 27 Mar 2019 12:22:23 +0000 (GMT) Received: from Webmail-eu.st.com (Safex1hubcas23.st.com [10.75.90.46]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id DD3CD5363; Wed, 27 Mar 2019 12:22:22 +0000 (GMT) Received: from SAFEX1HUBCAS22.st.com (10.75.90.93) by SAFEX1HUBCAS23.st.com (10.75.90.46) with Microsoft SMTP Server (TLS) id 14.3.435.0; Wed, 27 Mar 2019 13:22:22 +0100 Received: from localhost (10.48.0.131) by Webmail-ga.st.com (10.75.90.48) with Microsoft SMTP Server (TLS) id 14.3.361.1; Wed, 27 Mar 2019 13:22:22 +0100 From: Arnaud Pouliquen To: Vinod Koul CC: Dan Williams , , Pierre-Yves MORDRET , , , Subject: [PATCH] dmaengine: stm32-dma: fix residue calculation in stm32-dma Date: Wed, 27 Mar 2019 13:21:56 +0100 Message-ID: <1553689316-6231-1-git-send-email-arnaud.pouliquen@st.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.48.0.131] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-27_08:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org During residue calculation. the DMA can switch to the next sg. When this race condition occurs, the residue returned value is not valid. Indeed the position in the sg returned by the hardware is the position of the next sg, not the current sg. Solution is to check the sg after the calculation to verify it. If a transition is detected we consider that the DMA has switched to the beginning of next sg. Signed-off-by: Arnaud Pouliquen Signed-off-by: Pierre-Yves MORDRET --- drivers/dma/stm32-dma.c | 70 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 4903a40..30309d2 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1038,33 +1038,77 @@ static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan) return ndtr << width; } +static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan) +{ + struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); + struct stm32_dma_sg_req *sg_req; + u32 dma_scr, dma_smar, id; + + id = chan->id; + dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); + + if (!(dma_scr & STM32_DMA_SCR_DBM)) + return true; + + sg_req = &chan->desc->sg_req[chan->next_sg]; + + if (dma_scr & STM32_DMA_SCR_CT) { + dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id)); + return (dma_smar == sg_req->chan_reg.dma_sm0ar); + } + + dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id)); + + return (dma_smar == sg_req->chan_reg.dma_sm1ar); +} + static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, struct stm32_dma_desc *desc, u32 next_sg) { u32 modulo, burst_size; - u32 residue = 0; + u32 residue; + u32 n_sg = next_sg; + struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg]; int i; + residue = stm32_dma_get_remaining_bytes(chan); + /* - * In cyclic mode, for the last period, residue = remaining bytes from - * NDTR + * Calculate the residue means compute the descriptors + * information: + * - the sg currently transferred + * - the remaining position in this sg (NDTR). + * + * The issue is that a race condition can occur if DMA is + * running. DMA can have started to transfer the next sg before + * the position in sg is read. In this case the remaing position + * can correspond to the new sg position. + * The strategy implemented in the stm32 driver is to check the + * sg transition. If detected we can not trust the SxNDTR register + * value, this register can not be up to date during the transition. + * In this case we can assume that the dma is at the beginning of next + * sg so we calculate the residue in consequence. */ - if (chan->desc->cyclic && next_sg == 0) { - residue = stm32_dma_get_remaining_bytes(chan); - goto end; + + if (!stm32_dma_is_current_sg(chan)) { + n_sg++; + if (n_sg == chan->desc->num_sgs) + n_sg = 0; + residue = sg_req->len; } /* - * For all other periods in cyclic mode, and in sg mode, - * residue = remaining bytes from NDTR + remaining periods/sg to be - * transferred + * In cyclic mode, for the last period, residue = remaining bytes + * from NDTR, + * else for all other periods in cyclic mode, and in sg mode, + * residue = remaining bytes from NDTR + remaining + * periods/sg to be transferred */ - for (i = next_sg; i < desc->num_sgs; i++) - residue += desc->sg_req[i].len; - residue += stm32_dma_get_remaining_bytes(chan); + if (!chan->desc->cyclic || n_sg != 0) + for (i = n_sg; i < desc->num_sgs; i++) + residue += desc->sg_req[i].len; -end: if (!chan->mem_burst) return residue; -- 2.7.4