Commit 794a0f7b authored by Serge Semin's avatar Serge Semin Committed by Bjorn Helgaas
Browse files

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 bd96f1b2 ("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: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20220524152159.2370739-6-Frank.Li@nxp.com


Tested-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: default avatarSerge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-By: default avatarVinod Koul <vkoul@kernel.org>
parent 6951ee96
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -339,20 +339,39 @@ 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;
	/*
	 * 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;
	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;
	} else {
		if ((chan->dir == EDMA_DIR_WRITE && dir != DMA_DEV_TO_MEM) ||
		    (chan->dir == EDMA_DIR_READ && dir != DMA_MEM_TO_DEV))
			return NULL;
	}