dmaengine: dw-edma: Drop dma_slave_config.direction field usage
authorSerge Semin <Sergey.Semin@baikalelectronics.ru>
Tue, 24 May 2022 15:21:56 +0000 (10:21 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 23 Jun 2022 19:56:34 +0000 (14:56 -0500)
The dma_slave_config.direction field usage in the DW eDMA driver was
introduced by bd96f1b2f43a ("dmaengine: dw-edma: support local dma device
transfer semantics"). Mainly the change introduced there was correct
(indeed DEV_TO_MEM means using RD-channel and MEM_TO_DEV - WR-channel for
the case of having eDMA accessed locally from CPU/Application side), but
providing an additional MEM_TO_MEM/DEV_TO_DEV-based semantics was quite
redundant if not to say potentially harmful (when it comes to removing the
denoted field). First of all since the dma_slave_config.direction field has
been marked as obsolete (see [1] and the struct dma_slave_config [2]) and
will be discarded in future, using it especially in a non-standard way is
discouraged. Secondly in accordance with the commit denoted above the
default dw_edma_device_transfer() semantics has been changed despite what
its message said. So claiming that the method was left backward compatible
was wrong.

Fix the problems denoted above and simplify the dw_edma_device_transfer()
method by dropping the parsing of the DMA-channel direction field. Instead
of having that implicit dma_slave_config.direction field semantic, use the
recently added DW_EDMA_CHIP_LOCAL flag to distinguish between the local and
remote DW eDMA setups thus preserving support for both cases. Add an ASCII
figure to clarify the situation.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/driver-api/dmaengine/provider.rst?id=v5.18#n478
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/dmaengine.h?id=v5.18#n389

[bhelgaas: convert references to specific URLs]
Co-developed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20220524152159.2370739-6-Frank.Li@nxp.com
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-By: Vinod Koul <vkoul@kernel.org>
drivers/dma/dw-edma/dw-edma-core.c

index af037ec61a869c75ab9cea8c5bb375867fa82b5f..23ad07496b10744487506012ed392d163f75b59e 100644 (file)
@@ -339,21 +339,40 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
        if (!chan->configured)
                return NULL;
 
-       switch (chan->config.direction) {
-       case DMA_DEV_TO_MEM: /* local DMA */
-               if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ)
-                       break;
-               return NULL;
-       case DMA_MEM_TO_DEV: /* local DMA */
-               if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE)
-                       break;
-               return NULL;
-       default: /* remote DMA */
-               if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ)
-                       break;
-               if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE)
-                       break;
-               return NULL;
+       /*
+        * Local Root Port/End-point              Remote End-point
+        * +-----------------------+ PCIe bus +----------------------+
+        * |                       |    +-+   |                      |
+        * |    DEV_TO_MEM   Rx Ch <----+ +---+ Tx Ch  DEV_TO_MEM    |
+        * |                       |    | |   |                      |
+        * |    MEM_TO_DEV   Tx Ch +----+ +---> Rx Ch  MEM_TO_DEV    |
+        * |                       |    +-+   |                      |
+        * +-----------------------+          +----------------------+
+        *
+        * 1. Normal logic:
+        * If eDMA is embedded into the DW PCIe RP/EP and controlled from the
+        * CPU/Application side, the Rx channel (EDMA_DIR_READ) will be used
+        * for the device read operations (DEV_TO_MEM) and the Tx channel
+        * (EDMA_DIR_WRITE) - for the write operations (MEM_TO_DEV).
+        *
+        * 2. Inverted logic:
+        * If eDMA is embedded into a Remote PCIe EP and is controlled by the
+        * MWr/MRd TLPs sent from the CPU's PCIe host controller, the Tx
+        * channel (EDMA_DIR_WRITE) will be used for the device read operations
+        * (DEV_TO_MEM) and the Rx channel (EDMA_DIR_READ) - for the write
+        * operations (MEM_TO_DEV).
+        *
+        * It is the client driver responsibility to choose a proper channel
+        * for the DMA transfers.
+        */
+       if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+               if ((chan->dir == EDMA_DIR_READ && dir != DMA_DEV_TO_MEM) ||
+                   (chan->dir == EDMA_DIR_WRITE && dir != DMA_MEM_TO_DEV))
+                       return NULL;
+       } else {
+               if ((chan->dir == EDMA_DIR_WRITE && dir != DMA_DEV_TO_MEM) ||
+                   (chan->dir == EDMA_DIR_READ && dir != DMA_MEM_TO_DEV))
+                       return NULL;
        }
 
        if (xfer->type == EDMA_XFER_CYCLIC) {