Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp573949yba; Fri, 26 Apr 2019 05:19:48 -0700 (PDT) X-Google-Smtp-Source: APXvYqy9/cL38+PB1hCpEmfQI5K5U5KK92jaG5LabCeAb81+1gx2rs26Rej/cpQRZyR5A2jE8EPQ X-Received: by 2002:a17:902:28ab:: with SMTP id f40mr28549430plb.297.1556281188469; Fri, 26 Apr 2019 05:19:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1556281188; cv=none; d=google.com; s=arc-20160816; b=ptspJMdocy/fJD3CDvHdyuvai1t+jhrDW+0/IEhI5QifU30nDknvq6N6K5CnZgRYUD KG0zblDuZUiqx0UxKVbBU/kcjMcPzESZZ1j8ibyqFzgjFOCBgFxM6gJ/Oz7gdCtOMxwo J6Si8e9KiKgDLjyj8WURMeYuFEGni2fyJv2fWBqOYGeThxnK3DyVrkJ4x8n+KPtRUwQ+ m8Bq7757lqThWnzLMKL36nzMFsJsKmpaKTyI5ugsEdgO4yvVIRF2Y28GT7pBGTjD+iUB 0IniJH2zMwLOPZvmplagaLMWzSRg3z0Fxz7mg4FWXE0O1r5qFdpcKcr2qiuBLUDrt2Of /Rxw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature; bh=cefYL/v03f4ZY/6M8Z5wJK++DxMzJmvvk/p8phPaYZs=; b=0Gx9shBiGuWqjeObnrnKWVWE5UOcWH2tXZl/+82g4ituIqhfmpckCdps/Fb7E71HEJ B7RYwe745K2OSYyUfCbFuUgFEs+ommzF2CYdbFsAfoZUYofznL56915TQINmicKej6uS 2UbSJ1ksBjlld+7lW20iAU6M9nV/i8RAbiX3tir1poTc32IFnlNwFLBnqwKthithxlUx AOr6dJgBzjSz/CqeTMaBYQ8W7Ssq7acsvwm1U6XdhOhRS7T/NkNBz3dDU6jlqkxVn5VF NdTmbhw8QOvyFX6iGf0OX6hV2xUhadlMEywc1KQAl/6k+X0ukmVQxjrEG8RLbz4U4ca4 hqpA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=t0pB7TXq; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h66si23752383pgc.418.2019.04.26.05.19.32; Fri, 26 Apr 2019 05:19:48 -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; dkim=pass header.i=@kernel.org header.s=default header.b=t0pB7TXq; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726245AbfDZMR6 (ORCPT + 99 others); Fri, 26 Apr 2019 08:17:58 -0400 Received: from mail.kernel.org ([198.145.29.99]:57504 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725901AbfDZMR6 (ORCPT ); Fri, 26 Apr 2019 08:17:58 -0400 Received: from localhost (unknown [171.76.113.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 73FCF2089E; Fri, 26 Apr 2019 12:17:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1556281077; bh=de4ui+tuZDXUFHeZfBrIGjZoQ8NU2gODJGhbz3Cpnjk=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=t0pB7TXqBuFjcpZPFv/22gI3vnaBkSJqd/a0HdtbiXx8m09Kaqn1uUEJ3GVwyMfdH JK80Bd0SMsJ5Vu8ZXnynkAN3+SPvc64/IokPcSYcGcq6KMNyETIM4xyzJJzDzM6QYI rNhtzv3TXhjKZYHwJN/JGf6y9nrvQHXsFp5RuwZc= Date: Fri, 26 Apr 2019 17:47:51 +0530 From: Vinod Koul To: Arnaud Pouliquen Cc: Dan Williams , Pierre-Yves MORDRET , linux-stm32@st-md-mailman.stormreply.com, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org Subject: Re: [PATCH] dmaengine: stm32-dma: fix residue calculation in stm32-dma Message-ID: <20190426121751.GC28103@vkoul-mobl> References: <1553689316-6231-1-git-send-email-arnaud.pouliquen@st.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1553689316-6231-1-git-send-email-arnaud.pouliquen@st.com> User-Agent: Mutt/1.11.3 (2019-02-01) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Arnaud, Sorry for delay in review, the conference travel/vacation plan delayed this. On 27-03-19, 13:21, Arnaud Pouliquen wrote: > 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. Now, that sounds like duct tape. Why should we bother doing that. Also looking back at the stm32_dma_desc_residue() and calls to it from stm32_dma_tx_status() am not sure we are doing the right thing why are we looking at next_sg here, can you explain me that please > > 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 -- ~Vinod