From: Serge Semin <Sergey.Semin@xxxxxxxxxxxxxxxxxxxx> [ Upstream commit affe93dd5b35bb0e7b0aa0505ae432dd0ac72c3f ] It turns out having a Rx DMA channel serviced with higher priority than a Tx DMA channel is not enough to provide a well balanced DMA-based SPI transfer interface. There might still be moments when the Tx DMA channel is occasionally handled faster than the Rx DMA channel. That in its turn will eventually cause the SPI Rx FIFO overflow if SPI bus speed is high enough to fill the SPI Rx FIFO in before it's cleared by the Rx DMA channel. That's why having the DMA-based SPI Tx interface too optimized is the errors prone, so the commit 0b2b66514fc9 ("spi: dw: Use DMA max burst to set the request thresholds") though being perfectly normal from the standard functionality point of view implicitly introduced the problem described above. In order to fix that the Tx DMA activity is intentionally slowed down by limiting the SPI Tx FIFO depth with a value twice bigger than the Tx burst length calculated earlier by the dw_spi_dma_maxburst_init() method. Fixes: 0b2b66514fc9 ("spi: dw: Use DMA max burst to set the request thresholds") Signed-off-by: Serge Semin <Sergey.Semin@xxxxxxxxxxxxxxxxxxxx> Reviewed-by: Andy Shevchenko <andy.shevchenko@xxxxxxxxx> Cc: Andy Shevchenko <andy.shevchenko@xxxxxxxxx> Cc: Alexey Malahov <Alexey.Malahov@xxxxxxxxxxxxxxxxxxxx> Cc: Feng Tang <feng.tang@xxxxxxxxx> Link: https://lore.kernel.org/r/20200721203951.2159-1-Sergey.Semin@xxxxxxxxxxxxxxxxxxxx Signed-off-by: Mark Brown <broonie@xxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> --- drivers/spi/spi-dw-dma.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index 5986c520b1965..bb390ff67d1d8 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -372,8 +372,20 @@ static int dw_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer) { u16 imr = 0, dma_ctrl = 0; + /* + * Having a Rx DMA channel serviced with higher priority than a Tx DMA + * channel might not be enough to provide a well balanced DMA-based + * SPI transfer interface. There might still be moments when the Tx DMA + * channel is occasionally handled faster than the Rx DMA channel. + * That in its turn will eventually cause the SPI Rx FIFO overflow if + * SPI bus speed is high enough to fill the SPI Rx FIFO in before it's + * cleared by the Rx DMA channel. In order to fix the problem the Tx + * DMA activity is intentionally slowed down by limiting the SPI Tx + * FIFO depth with a value twice bigger than the Tx burst length + * calculated earlier by the dw_spi_dma_maxburst_init() method. + */ dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1); - dw_writel(dws, DW_SPI_DMATDLR, dws->fifo_len - dws->txburst); + dw_writel(dws, DW_SPI_DMATDLR, dws->txburst); if (xfer->tx_buf) dma_ctrl |= SPI_DMA_TDMAE; -- 2.25.1