linux/drivers/dma
Serge Semin 267c5f17a0 dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics
[ Upstream commit c1e3397917 ]

In accordance with [1, 2] the DW eDMA controller has been created to be
part of the DW PCIe Root Port and DW PCIe End-point controllers and to
offload the transferring of large blocks of data between application and
remote PCIe domains leaving the system CPU free for other tasks. In the
first case (eDMA being part of DW PCIe Root Port) the eDMA controller is
always accessible via the CPU DBI interface and never over the PCIe wire.

The latter case is more complex. Depending on the DW PCIe End-Point IP-core
synthesize parameters it's possible to have the eDMA registers accessible
not only from the application CPU side, but also via mapping the eDMA CSRs
over a dedicated endpoint BAR. So based on the specifics denoted above the
eDMA driver is supposed to support two types of the DMA controller setups:

  1) eDMA embedded into the DW PCIe Root Port/End-point and accessible over
     the local CPU from the application side.

  2) eDMA embedded into the DW PCIe End-point and accessible via the PCIe
     wire with MWr/MRd TLPs generated by the CPU PCIe host controller.

Since the CPU memory resides different sides in these cases the semantics
of the MEM_TO_DEV and DEV_TO_MEM operations is flipped with respect to the
Tx and Rx DMA channels. So MEM_TO_DEV/DEV_TO_MEM corresponds to the Tx/Rx
channels in setup 1) and to the Rx/Tx channels in case of setup 2).

The DW eDMA driver has supported the case 2) since e63d79d1ff
("dmaengine: Add Synopsys eDMA IP core driver") in the framework of the
drivers/dma/dw-edma/dw-edma-pcie.c driver.

The case 1) support was added later by bd96f1b2f4 ("dmaengine: dw-edma:
support local dma device transfer semantics").  Afterwards the driver was
supposed to cover the both possible eDMA setups, but the latter commit
turned out to be not fully correct.

The problem was that the commit together with the new functionality support
also changed the channel direction semantics so the eDMA Read-channel
(corresponding to the DMA_DEV_TO_MEM direction for case 1) now uses the
sgl/cyclic base addresses as the Source addresses of the DMA transfers and
dma_slave_config.dst_addr as the Destination address of the DMA transfers.

Similarly the eDMA Write-channel (corresponding to the DMA_MEM_TO_DEV
direction for case 1) now uses dma_slave_config.src_addr as a source
address of the DMA transfers and sgl/cyclic base address as the Destination
address of the DMA transfers. This contradicts the logic of the
DMA-interface, which implies that DEV side is supposed to belong to the
PCIe device memory and MEM - to the CPU/Application memory. Indeed it seems
irrational to have the SG-list defined in the PCIe bus space, while
expecting a contiguous buffer allocated in the CPU memory. Moreover the
passed SG-list and cyclic DMA buffers are supposed to be mapped in a way so
to be seen by the DW eDMA Application (CPU) interface.

So in order to have the correct DW eDMA interface we need to invert the
eDMA Rd/Wr-channels and DMA-slave directions semantics by selecting the
src/dst addresses based on the DMA transfer direction instead of using the
channel direction capability.

[1] DesignWare Cores PCI Express Controller Databook - DWC PCIe Root Port,
    v.5.40a, March 2019, p.1092
[2] DesignWare Cores PCI Express Controller Databook - DWC PCIe Endpoint,
    v.5.40a, March 2019, p.1189

Co-developed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Fixes: bd96f1b2f4 ("dmaengine: dw-edma: support local dma device transfer semantics")
Link: https://lore.kernel.org/r/20220524152159.2370739-7-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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-08-21 15:15:55 +02:00
..
bestcomm
dw dmaengine: dw: Make it dependent to HAS_IOMEM 2021-04-21 13:00:50 +02:00
dw-axi-dmac dmaengine: virt-dma: Add missing locking 2019-12-26 10:04:18 +05:30
dw-edma dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics 2022-08-21 15:15:55 +02:00
fsl-dpaa2-qdma dmaengine: fsl-dpaa2-qdma: Fix error return code in two functions 2021-06-23 14:42:40 +02:00
hsu dmaengine: hsu: disable spurious interrupt 2021-03-04 11:37:55 +01:00
idxd dmaengine: idxd: add missing callback function to support DMA_INTERRUPT 2022-06-14 18:32:47 +02:00
ioat dmaengine: ioatdma: remove unused function missed during dma_v2 removal 2020-11-16 22:42:28 +05:30
ipu dmaengine: ipu: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
mediatek dmaengine: mediatek:Fix PM usage reference leak of mtk_uart_apdma_alloc_chan_resources 2022-04-27 13:53:48 +02:00
ppc4xx dmaengine: ppc4xx: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
qcom dmaengine: QCOM_HIDMA_MGMT depends on HAS_IOMEM 2021-06-23 14:42:40 +02:00
sf-pdma dmaengine: SF_PDMA depends on HAS_IOMEM 2021-06-23 14:42:40 +02:00
sh dmaengine: Revert "dmaengine: shdma: Fix runtime PM imbalance on error" 2022-04-13 21:01:10 +02:00
ti dmaengine: ti: Add missing put_device in ti_dra7_xbar_route_allocate 2022-07-12 16:32:23 +02:00
xilinx dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type 2022-06-14 18:32:38 +02:00
acpi-dma.c dmaengine: acpi: Avoid comparison GSI with Linux vIRQ 2021-09-26 14:08:57 +02:00
altera-msgdma.c dmaengine: altera-msgdma: fix kernel-doc style for tasklet 2020-10-08 15:18:37 +05:30
amba-pl08x.c treewide: Use fallthrough pseudo-keyword 2020-08-23 17:36:59 -05:00
at_hdmac_regs.h dmaengine: at_hdmac: Replace zero-length array with flexible-array 2020-05-13 20:25:16 +05:30
at_hdmac.c dmaengine: at_hdmac: convert tasklets to use new tasklet_setup() API 2020-09-18 12:18:11 +05:30
at_xdmac.c dmaengine: at_xdma: handle errors of at_xdmac_alloc_desc() correctly 2022-07-12 16:32:23 +02:00
bcm-sba-raid.c dmaengine: bcm-sba-raid: Replace zero-length array with flexible-array member 2020-02-13 20:15:35 +05:30
bcm2835-dma.c dmaengine: bcm2835: Drop local dma_parms 2020-09-11 17:42:12 +05:30
coh901318_lli.c
coh901318.c dmaengine: coh901318: convert tasklets to use new tasklet_setup() API 2020-09-18 12:18:11 +05:30
coh901318.h
dma-axi-dmac.c dmaengine: axi-dmac: Drop local dma_parms 2020-09-11 17:42:12 +05:30
dma-jz4780.c dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status 2020-10-05 09:58:48 +05:30
dmaengine.c dmaengine: Fix a double free in dma_async_device_register 2021-04-21 13:00:50 +02:00
dmaengine.h dmaengine: dmaengine_desc_callback_valid(): Check for callback_result 2021-11-18 14:04:24 +01:00
dmatest.c dmaengine: dmatest: Return boolean result directly in filter() 2020-09-22 20:18:41 +05:30
ep93xx_dma.c dmaengine: ep93xx: convert tasklets to use new tasklet_setup() API 2020-09-18 12:18:11 +05:30
fsl_raid.c dmaengine: fsl: remove bad channel update 2020-10-05 09:59:17 +05:30
fsl_raid.h
fsl-edma-common.c dmaengine: fsl-edma: fix wrong tcd endianness for big-endian cpu 2020-07-06 14:49:22 +05:30
fsl-edma-common.h dmaengine: fsl-edma-common: correct DSIZE_32BYTE 2020-07-06 10:24:49 +05:30
fsl-edma.c dmaengine: fsl-edma: Fix NULL pointer exception in fsl_edma_tx_handler 2020-06-24 13:05:01 +05:30
fsl-qdma.c dmaengine: fsl-qdma: check dma_set_mask return value 2021-07-20 16:05:38 +02:00
fsldma.c dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function 2021-03-04 11:37:55 +01:00
fsldma.h fsldma: fix very broken 32-bit ppc ioread64 functionality 2020-08-29 13:50:56 -07:00
hisi_dma.c dmaengine: hisi_dma: fix MSI allocate fail when reload hisi_dma 2022-04-08 14:40:26 +02:00
idma64.c
idma64.h
img-mdc-dma.c
imx-dma.c dmaengine: imx-dma: configure the generic DMA type to make it work 2021-08-12 13:22:05 +02:00
imx-sdma.c dmaengine: imx-sdma: Allow imx8m for imx7 FW revs 2022-07-12 16:32:22 +02:00
iop-adma.c Merge branch 'topic/tasklet' into next 2020-10-01 10:18:59 +05:30
iop-adma.h treewide: Use fallthrough pseudo-keyword 2020-08-23 17:36:59 -05:00
k3dma.c dmaengine: k3dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
Kconfig dmaengine: ioat: depends on !UML 2021-09-26 14:09:00 +02:00
lpc18xx-dmamux.c
Makefile misc: mic: remove the MIC drivers 2020-10-28 19:12:03 +01:00
mcf-edma.c dmaengine: mcf-edma: Fix NULL pointer exception in mcf_edma_tx_handler 2020-06-24 13:06:15 +05:30
milbeaut-hdmac.c dmaengine: Replace zero-length array with flexible-array 2020-06-15 23:08:30 -05:00
milbeaut-xdmac.c dmaengine: milbeaut-xdmac: Fix a resource leak in the error handling path of the probe function 2021-01-17 14:17:02 +01:00
mmp_pdma.c dmaengine: pxa/mmp: stop referencing config->slave_id 2022-01-27 10:54:07 +01:00
mmp_tdma.c dmaengine: mmp: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
moxart-dma.c dmaengine: Replace zero-length array with flexible-array 2020-06-15 23:08:30 -05:00
mpc512x_dma.c dmaengine: mpc512x: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
mv_xor_v2.c dmaengine: mv_xor_v2: Fix error return code in mv_xor_v2_probe() 2020-12-30 11:53:21 +01:00
mv_xor.c dmaengine: mv_xor: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
mv_xor.h
mxs-dma.c dmaengine: mxs-dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
nbpfaxi.c dmaengine: nbpfaxi: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
of-dma.c dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not yet available 2021-08-26 08:35:36 -04:00
owl-dma.c dmaengine: owl-dma: Fix a resource leak in the remove function 2021-03-04 11:37:55 +01:00
pch_dma.c dmaengine: pch_dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:06 +05:30
pl330.c dmaengine: pl330: Fix lockdep warning about non-static key 2022-07-12 16:32:23 +02:00
plx_dma.c dmaengine: plx_dma: add a missing put_device() on error path 2021-04-21 13:00:51 +02:00
pxa_dma.c dmaengine: pxa/mmp: stop referencing config->slave_id 2022-01-27 10:54:07 +01:00
s3c24xx-dma.c dmaengine: s3c24xx-dma: fix spelling mistake "to" -> "too" 2020-01-23 17:03:25 +05:30
sa11x0-dma.c dmaengine: sa11x0: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
sirf-dma.c dmaengine: sirf-dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
sprd-dma.c dmaengine: sprd: Add missing MODULE_DEVICE_TABLE 2021-09-26 14:08:59 +02:00
st_fdma.c dmaengine: st_fdma: fix MODULE_ALIAS 2021-12-22 09:30:53 +01:00
st_fdma.h
ste_dma40_ll.c
ste_dma40_ll.h
ste_dma40.c dmaengine: stedma40: add missing iounmap() on error in d40_probe() 2021-06-23 14:42:40 +02:00
stm32-dma.c dmaengine: stm32-dma: Fix PM usage counter imbalance in stm32 dma ops 2021-08-12 13:22:04 +02:00
stm32-dmamux.c dmaengine: stm32-dmamux: Fix PM disable depth imbalance in stm32_dmamux_probe 2022-02-23 12:01:07 +01:00
stm32-mdma.c dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler() 2022-06-09 10:21:20 +02:00
sun4i-dma.c dmaengine: sun4i-dma: Demote obvious misuse of kerneldoc to standard comment blocks 2020-07-15 17:50:47 +05:30
sun6i-dma.c dmaengine: sun6i: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
tegra20-apb-dma.c dmaengine: tegra20: Fix runtime PM imbalance on error 2021-04-28 13:40:01 +02:00
tegra210-adma.c dmaengine: tegra210-adma: Fix runtime PM imbalance on error 2020-06-24 15:11:39 +05:30
timb_dma.c dmaengine: timb_dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
TODO
txx9dmac.c dmaengine: txx9dmac: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
txx9dmac.h
uniphier-mdmac.c dmaengine: uniphier-mdmac: replace zero-length array with flexible-array member 2020-02-13 20:15:57 +05:30
uniphier-xdmac.c dmaengine: uniphier-xdmac: Fix type of address variables 2022-01-27 10:54:29 +01:00
virt-dma.c dmaengine: virt-dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
virt-dma.h dmaengine: virt-dma: Add missing locking around list operations 2019-12-26 10:04:18 +05:30
xgene-dma.c dmaengine: xgene: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
zx_dma.c dmaengine: zx: remove redundant irqsave in hardIRQ 2020-09-18 12:30:50 +05:30