Re: [PATCH] at_xdmac fix status read in cyclic mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi David,

On Wed, Feb 17, 2016 at 02:12:19PM +0100, David Engraf wrote:
> Hi,
> 
> I encountered an issue when using atmel_serial.c driver with at_xdmac.c on a
> SAMA5D4 board. The serial driver uses a cyclic DMA receive buffer. While
> doing tests with a high baudrate and high data load, at_xdmac_tx_status()
> sometimes returns an invalid value for residue. This happens when the serial
> driver calls dmaengine_tx_status() while the DMA is still in progress
> (DMA_IN_PROGRESS). In this case, going through the microblock list is not
> save because the content might be modified. This may happen when
> AT_XDMAC_CNDA has been changed while going through the list.
> 
> The only reliable solution working in my test scenario was to pause and
> resume the DMA channel when it is in progress.
> 

Thanks for your patch. You're right, it sounds safer to pause dma to have an
accurate residue.

> 
> Signed-off-by: David Engraf <david.engraf@xxxxxxxxx>
> 
Minor comment otherwise
Acked-by: Ludovic Desroches <ludovic.desroches@xxxxxxxxx>

> diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
> index 64f5d1b..295a06a 100644
> --- a/drivers/dma/at_xdmac.c
> +++ b/drivers/dma/at_xdmac.c
> @@ -254,6 +254,9 @@ struct at_xdmac_desc {
>  	struct list_head		xfer_node;
>  };
>  
> +static int at_xdmac_device_pause(struct dma_chan *chan);
> +static int at_xdmac_device_resume(struct dma_chan *chan);
> +
>  static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
>  {
>  	return atxdmac->regs + (AT_XDMAC_CHAN_REG_BASE + chan_nb * 0x40);
> @@ -1407,6 +1410,11 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
>  	if (!txstate)
>  		return ret;
>  
> +	if (ret == DMA_IN_PROGRESS) {
> +		/* pause DMA while calculating residue */
> +		at_xdmac_device_pause(chan);
> +	}

	/* Pause DMA while calculating residue. */
	if (ret == DMA_IN_PROGRESS)
		at_xdmac_device_pause(chan);

> +
>  	spin_lock_irqsave(&atchan->lock, flags);
>  
>  	desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
> @@ -1456,6 +1464,10 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
>  
>  spin_unlock:
>  	spin_unlock_irqrestore(&atchan->lock, flags);
> +
> +	if (ret == DMA_IN_PROGRESS)
> +		at_xdmac_device_resume(chan);
> +
>  	return ret;
>  }
>  

Regards

Ludovic

--
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux PCI]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux