diff options
author | Serge Semin <Sergey.Semin@baikalelectronics.ru> | 2022-05-24 10:21:56 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2022-06-23 14:56:34 -0500 |
commit | 794a0f7b6f5ccbcb3bbb504b90d980bf2240d110 (patch) | |
tree | e59eb471561ce2aaf3bc405605770406de9eb3f8 /drivers/dma/dw-edma | |
parent | 6951ee96c649f6e963b98c11b2b1a92697d3c45c (diff) | |
download | linux-794a0f7b6f5ccbcb3bbb504b90d980bf2240d110.tar.gz |
dmaengine: dw-edma: Drop dma_slave_config.direction field usage
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>
Diffstat (limited to 'drivers/dma/dw-edma')
-rw-r--r-- | drivers/dma/dw-edma/dw-edma-core.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index af037ec61a86..23ad07496b10 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -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) { |