diff mbox series

spi: dw-dma: Fix Tx DMA channel working too fast

Message ID 20200721203951.2159-1-Sergey.Semin@baikalelectronics.ru (mailing list archive)
State Accepted
Commit affe93dd5b35bb0e7b0aa0505ae432dd0ac72c3f
Headers show
Series spi: dw-dma: Fix Tx DMA channel working too fast | expand

Commit Message

Serge Semin July 21, 2020, 8:39 p.m. UTC
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")
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Feng Tang <feng.tang@intel.com>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
 drivers/spi/spi-dw-dma.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

Comments

Andy Shevchenko July 21, 2020, 9:41 p.m. UTC | #1
On Tue, Jul 21, 2020 at 11:39 PM Serge Semin
<Sergey.Semin@baikalelectronics.ru> wrote:
>
> 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.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Thanks!

> Fixes: 0b2b66514fc9 ("spi: dw: Use DMA max burst to set the request thresholds")
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Feng Tang <feng.tang@intel.com>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> ---
>  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 5986c520b196..bb390ff67d1d 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.26.2
>
Mark Brown July 22, 2020, 12:57 a.m. UTC | #2
On Tue, 21 Jul 2020 23:39:51 +0300, Serge Semin wrote:
> 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.

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: dw-dma: Fix Tx DMA channel working too fast
      commit: affe93dd5b35bb0e7b0aa0505ae432dd0ac72c3f

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
diff mbox series

Patch

diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index 5986c520b196..bb390ff67d1d 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;