mbox series

[v2,00/11] spi: dw-dma: Add max SG entries burst capability support

Message ID 20200920112322.24585-1-Sergey.Semin@baikalelectronics.ru (mailing list archive)
Headers show
Series spi: dw-dma: Add max SG entries burst capability support | expand

Message

Serge Semin Sept. 20, 2020, 11:23 a.m. UTC
Mainly this series is about fixing a very nasty problem discovered in the
DW APB SSI driver working in a couple with DW DMAC, which doesn't have
multi-block capability support (a.k.a. accelerated SG list entries
traversal/burst, or automatic LLP entries reload, etc.).

DW DMA IP-core and its DMA channel on the synthesize stage can be tuned by
setting a vast number of the model parameters, some of which are provided
to create a more optimized/performant controller. In particular two of
those parameters are DMAH_CHx_MULTI_BLK_EN and DMAH_CHx_HC_LLP. If at
least one of them is set to zero (false) then the target DMA controller
will be smaller and faster but will lack of the DMA blocks chaining
support. In the kernel notation it means that the controller won't be able
to automatically reload a next SG-list entry, when a current one is
finished. Since Linux kernel DMA subsystem interface requires to have the
SG-lists execution supported, the DW DMA engine driver is developed in a
way so to resubmit each SG-list entry one-by-one by software means: each
SG-list entry execution finish is tracked by the DW DMA controller
interrupt, which handler executes a tasklet, which then re-charges a DW
DMA channel with a next SG-list entry if one is available. Such
implementation is a normal design and works well for the most of the DW
DMAC client devices. But it may cause problems for devices, which send and
receive data by means of internal FIFOs. That requires having several DMA
channels working synchronously in order to prevent the FIFOs overflow.

A bright example of such device is the DW APB SSI controller. It has Tx
and Rx FIFOs, which first need to be filled in with data before data
sending out or receiving in. But those FIFOs are inter-dependent because
of the SPI nature and its shift-register design. So each sent over Tx FIFO
byte immediately causes getting a byte from the SPI bus into the Rx FIFO.
It makes a strategy of working with the SPI controller a bit tricky. The
more data we push into the Tx FIFO and the faster the SPI bus is, the more
careful we have to be in pulling data from Rx FIFO since if software or
DMA engine misses a moment when the Rx FIFO is full, for instance, due to
being busy with some other activity or due to being blocked if system bus
is busy with doing something else or just due to being too slow to keep up
with incoming data, then Rx FIFO will be overflown, which consequently
causes data loss. Needless to say that such situation is fatal and mustn't
be tolerated for a bus like SPI.

In application to the DW APB SSI driver the problem above may happen when
DW DMAC is synthesized with no multi-block capability support and it's
enabled to be working with DW APB SSI for full-duplex transfers. DW APB
SSI driver allocates two DW DMAC channels to perform Tx and Rx SPI
transfers, initializes them, submits Tx and Rx SG-lists for execution and
then waits until the DMA transfers are finished. The issue happens when Rx
SG-list consists of more than one entry. Since the multi-block capability
is unsupported the DW DMAC driver will use the software-based SG-list
entries traverse implementation, which by design may cause
non-deterministic latency during the Rx SG-list entries re-charge. During
the entries re-charge procedure the DMA Tx channel will keep pushing data
into the SPI Tx FIFO. DW APB SSI controller in its turn will keep pushing
data out from the Tx FIFO to the SPI bus, and will immediately fill in the
Rx FIFO. So if the latency is big enough, then we'll eventually end up
with Rx FIFO overflow.

One of the possible solution of the problem denoted above is to feed the
DMA engine with the Tx and Rx SG-list entries one-by-one. This
patch-series provides an implementation of that approach. First it moves
the requested DMA channels configuration into the dma_setup() callback,
which should have been there in the first place. Then it's better to move
the DMA transfers submission into the DMA-preparation methods to collect
all the setups in a single method. After that the current implementation
of a straightforward SG-lists DMA transfer should be unpinned into a
dedicated method dw_spi_dma_transfer_all() since we are about to introduce
an alternative DMA-based SPI transfer approach. Since DMA-transfers finish
is now locally detected we can simplify the driver code a bit and move the
DMAC register cleanup to a single place in the dw_spi_dma_transfer_all()
method. In order to re-use the DMA-{wait, submit Tx, submit Rx} methods we
have to alter their prototypes, so they would accept SG-lists instead of
the SPI-transfer structure. Finally we introduce a new DMA-based
SPI-transfer method, which traverses the SG-list entries in a loop and
synchronously submits each of then to the Tx and Rx DMA channels in a way
so the DMA engine wouldn't need to activate the prone to errors in our
case SG-list entries re-charge implementation. That new method is utilized
only for the DMA controllers, which can't handle all Tx and Rx SPI
transfer SG-lists in a single DMA transaction without software
intervention, and for the full-duplex SPI-transfers.

Link: https://lore.kernel.org/linux-spi/20200731075953.14416-1-Sergey.Semin@baikalelectronics.ru
Changelog v2:
- Replace negative conditional statements with the positive ones in the
  dw_spi_dma_submit_{tx,rx}() methods.
- Terminate the prepared DMA Tx-descriptors on submission errors.
- Split the patch "spi: dw-dma: Move DMA transfers submission to the
  channels prep methods" up into a series of more simple commits.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Feng Tang <feng.tang@intel.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: linux-spi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Serge Semin (11):
  spi: dw-dma: Set DMA Level registers on init
  spi: dw-dma: Fail DMA-based transfer if no Tx-buffer specified
  spi: dw-dma: Configure the DMA channels in dma_setup
  spi: dw-dma: Check rx_buf availability in the xfer method
  spi: dw-dma: Move DMA transfers submission to the channels prep
    methods
  spi: dw-dma: Check DMA Tx-desc submission status
  spi: dw-dma: Remove DMA Tx-desc passing around
  spi: dw-dma: Detach DMA transfer into a dedicated method
  spi: dw-dma: Move DMAC register cleanup to DMA transfer method
  spi: dw-dma: Pass exact data to the DMA submit and wait methods
  spi: dw-dma: Add one-by-one SG list entries transfer

 drivers/spi/spi-dw-dma.c | 316 ++++++++++++++++++++++++++++++---------
 drivers/spi/spi-dw.h     |   1 +
 2 files changed, 245 insertions(+), 72 deletions(-)

Comments

Mark Brown Sept. 29, 2020, 4:23 p.m. UTC | #1
On Sun, 20 Sep 2020 14:23:11 +0300, Serge Semin wrote:
> Mainly this series is about fixing a very nasty problem discovered in the
> DW APB SSI driver working in a couple with DW DMAC, which doesn't have
> multi-block capability support (a.k.a. accelerated SG list entries
> traversal/burst, or automatic LLP entries reload, etc.).
> 
> DW DMA IP-core and its DMA channel on the synthesize stage can be tuned by
> setting a vast number of the model parameters, some of which are provided
> to create a more optimized/performant controller. In particular two of
> those parameters are DMAH_CHx_MULTI_BLK_EN and DMAH_CHx_HC_LLP. If at
> least one of them is set to zero (false) then the target DMA controller
> will be smaller and faster but will lack of the DMA blocks chaining
> support. In the kernel notation it means that the controller won't be able
> to automatically reload a next SG-list entry, when a current one is
> finished. Since Linux kernel DMA subsystem interface requires to have the
> SG-lists execution supported, the DW DMA engine driver is developed in a
> way so to resubmit each SG-list entry one-by-one by software means: each
> SG-list entry execution finish is tracked by the DW DMA controller
> interrupt, which handler executes a tasklet, which then re-charges a DW
> DMA channel with a next SG-list entry if one is available. Such
> implementation is a normal design and works well for the most of the DW
> DMAC client devices. But it may cause problems for devices, which send and
> receive data by means of internal FIFOs. That requires having several DMA
> channels working synchronously in order to prevent the FIFOs overflow.
> 
> [...]

Applied to

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

Thanks!

[01/11] spi: dw-dma: Set DMA Level registers on init
        commit: 01ddbbb0b0af255d93b279f83c4ff91d494397d9
[02/11] spi: dw-dma: Fail DMA-based transfer if no Tx-buffer specified
        commit: 7ef30385b05fa8bc13f473c9b0b3ecc7dfb2b208
[03/11] spi: dw-dma: Configure the DMA channels in dma_setup
        commit: a874d811f0c2d285fd7409b5fc569c454c05c835
[04/11] spi: dw-dma: Check rx_buf availability in the xfer method
        commit: be3034d9f9f3ea28588932d10bba6d06b71489a7
[05/11] spi: dw-dma: Move DMA transfers submission to the channels prep methods
        commit: ab7a4d758b278fe44ded648e731c0638b6fa7fd3
[06/11] spi: dw-dma: Check DMA Tx-desc submission status
        commit: 9a6471a1a2c24964838a5bfa4d374e644e9daf07
[07/11] spi: dw-dma: Remove DMA Tx-desc passing around
        commit: 7a4d61f1dc94871154b2d06d671a5c20aea16ff2
[08/11] spi: dw-dma: Detach DMA transfer into a dedicated method
        commit: b86fed121fe6bf5bcac1c258472791ca352f47cf
[09/11] spi: dw-dma: Move DMAC register cleanup to DMA transfer method
        commit: 945b5b60f7110a81d1fd8145b197793edef3282d
[10/11] spi: dw-dma: Pass exact data to the DMA submit and wait methods
        commit: 917ce29ef559630cfeaea5b05f93d8744a6e9d97
[11/11] spi: dw-dma: Add one-by-one SG list entries transfer
        commit: ad4fe1264b396e94b78d91c49ecea425a593b28d

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