On Fri, May 15, 2020 at 01:47:42PM +0300, Serge Semin wrote: > If DMAC register is left uncleared any further DMAless transfers > may cause the DMAC hardware handshaking interface getting activated. > So the next DMA-based Rx/Tx transaction will be started right > after the dma_async_issue_pending() method is invoked even if no > DMATDLR/DMARDLR conditions are met. This at the same time may cause > the Tx/Rx FIFO buffers underrun/overrun. In order to fix this we > must clear DMAC register after a current DMA-based transaction is > finished. After adding a Fixes tag, Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> > > Co-developed-by: Georgy Vlasov <Georgy.Vlasov@xxxxxxxxxxxxxxxxxxxx> > Signed-off-by: Georgy Vlasov <Georgy.Vlasov@xxxxxxxxxxxxxxxxxxxx> > Signed-off-by: Serge Semin <Sergey.Semin@xxxxxxxxxxxxxxxxxxxx> > Cc: Ramil Zaripov <Ramil.Zaripov@xxxxxxxxxxxxxxxxxxxx> > Cc: Alexey Malahov <Alexey.Malahov@xxxxxxxxxxxxxxxxxxxx> > Cc: Thomas Bogendoerfer <tsbogend@xxxxxxxxxxxxxxxx> > Cc: Paul Burton <paulburton@xxxxxxxxxx> > Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx> > Cc: Arnd Bergmann <arnd@xxxxxxxx> > Cc: Allison Randal <allison@xxxxxxxxxxx> > Cc: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> > Cc: Gareth Williams <gareth.williams.jx@xxxxxxxxxxx> > Cc: Rob Herring <robh+dt@xxxxxxxxxx> > Cc: linux-mips@xxxxxxxxxxxxxxx > Cc: devicetree@xxxxxxxxxxxxxxx > > --- > > Changelog v2: > - Move the patch to the head of the series so one could be picked up to > the stable kernels as a fix. > - Clear the DMACR in the DMA exit callback too. > --- > drivers/spi/spi-dw-mid.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c > index 7a5ae1506365..0c597b6bb154 100644 > --- a/drivers/spi/spi-dw-mid.c > +++ b/drivers/spi/spi-dw-mid.c > @@ -108,6 +108,8 @@ static void mid_spi_dma_exit(struct dw_spi *dws) > dmaengine_terminate_sync(dws->rxchan); > dma_release_channel(dws->rxchan); > } > + > + dw_writel(dws, DW_SPI_DMACR, 0); > } > > static irqreturn_t dma_transfer(struct dw_spi *dws) > @@ -178,6 +180,8 @@ static void dw_spi_dma_tx_done(void *arg) > clear_bit(TX_BUSY, &dws->dma_chan_busy); > if (test_bit(RX_BUSY, &dws->dma_chan_busy)) > return; > + > + dw_writel(dws, DW_SPI_DMACR, 0); > spi_finalize_current_transfer(dws->master); > } > > @@ -249,6 +253,8 @@ static void dw_spi_dma_rx_done(void *arg) > clear_bit(RX_BUSY, &dws->dma_chan_busy); > if (test_bit(TX_BUSY, &dws->dma_chan_busy)) > return; > + > + dw_writel(dws, DW_SPI_DMACR, 0); > spi_finalize_current_transfer(dws->master); > } > > @@ -342,6 +348,8 @@ static void mid_spi_dma_stop(struct dw_spi *dws) > dmaengine_terminate_sync(dws->rxchan); > clear_bit(RX_BUSY, &dws->dma_chan_busy); > } > + > + dw_writel(dws, DW_SPI_DMACR, 0); > } > > static const struct dw_spi_dma_ops mfld_dma_ops = { > -- > 2.25.1 > -- With Best Regards, Andy Shevchenko