[PATCH v2 4/6] dmaengine: dw: Print warning if multi-block is unsupported

Serge Semin
2020-05-08T10:53:30Z

Multi-block support provides a way to map the kernel-specific SG-table so
the DW DMA device would handle it as a whole instead of handling the
SG-list items or so called LLP block items one by one. So if true LLP
list isn't supported by the DW DMA engine, then soft-LLP mode will be
utilized to load and execute each LLP-block one by one. A problem may
happen for multi-block DMA slave transfers, when the slave device buffers
(for example Tx and Rx FIFOs) depend on each other and have size smaller
than the block size. In this case writing data to the DMA slave Tx buffer
may cause the Rx buffer overflow if Rx DMA channel is paused to
reinitialize the DW DMA controller with a next Rx LLP item. In particular
We've discovered this problem in the framework of the DW APB SPI device
working in conjunction with DW DMA. Since there is no comprehensive way to
fix it right now lets at least print a warning for the first found
multi-blockless DW DMAC channel. This shall point a developer to the
possible cause of the problem if one would experience a sudden data loss.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org

---

Changelog v2:
- This is a new patch created instead of the dropped one:
"dmaengine: dw: Add LLP and block size config accessors"
---
drivers/dma/dw/core.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index 8bcd82c64478..e4749c296fca 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -1197,6 +1197,21 @@ int do_dma_probe(struct dw_dma_chip *chip)
*/
if (dwc->block_size > block_size)
block_size = dwc->block_size;
+
+ /*
+ * It might crucial for some devices to have the hardware
+ * accelerated multi-block transfers supported. Especially it
+ * concerns if Tx and Rx DMA slave device buffers somehow
+ * depend on each other. For instance an SPI controller may
+ * experience Rx buffer overflow error if Tx DMA channel keeps
+ * pushing data to the Tx FIFO, while Rx DMA channel is paused
+ * to initialize the DW DMA controller with a next Rx LLP item.
+ * Since there is no comprehensive way to fix it right now lets
+ * at least print a warning that hardware LLPs reloading is
+ * unsupported.
+ */
+ if (dwc->nollp)
+ dev_warn_once(chip->dev, "No hardware LLP support\n");
}

/* Clear all interrupts on all channels. */
--
2.25.1