WSL2-Linux-Kernel/drivers/dma
Serge Semin 131ee27d0c dmaengine: dw: Add memory bus width verification
[ Upstream commit d04b21bfa1c50a2ade4816cab6fdc91827b346b1 ]

Currently in case of the DEV_TO_MEM or MEM_TO_DEV DMA transfers the memory
data width (single transfer width) is determined based on the buffer
length, buffer base address or DMA master-channel max address width
capability. It isn't enough in case of the channel disabling prior the
block transfer is finished. Here is what DW AHB DMA IP-core databook says
regarding the port suspension (DMA-transfer pause) implementation in the
controller:

"When CTLx.SRC_TR_WIDTH < CTLx.DST_TR_WIDTH and the CFGx.CH_SUSP bit is
high, the CFGx.FIFO_EMPTY is asserted once the contents of the FIFO do not
permit a single word of CTLx.DST_TR_WIDTH to be formed. However, there may
still be data in the channel FIFO, but not enough to form a single
transfer of CTLx.DST_TR_WIDTH. In this scenario, once the channel is
disabled, the remaining data in the channel FIFO is not transferred to the
destination peripheral."

So in case if the port gets to be suspended and then disabled it's
possible to have the data silently discarded even though the controller
reported that FIFO is empty and the CTLx.BLOCK_TS indicated the dropped
data already received from the source device. This looks as if the data
somehow got lost on a way from the peripheral device to memory and causes
problems for instance in the DW APB UART driver, which pauses and disables
the DMA-transfer as soon as the recv data timeout happens. Here is the way
it looks:

 Memory <------- DMA FIFO <------ UART FIFO <---------------- UART
  DST_TR_WIDTH -+--------|       |         |
                |        |       |         |                No more data
   Current lvl -+--------|       |---------+- DMA-burst lvl
                |        |       |---------+- Leftover data
                |        |       |---------+- SRC_TR_WIDTH
               -+--------+-------+---------+

In the example above: no more data is getting received over the UART port
and BLOCK_TS is not even close to be fully received; some data is left in
the UART FIFO, but not enough to perform a bursted DMA-xfer to the DMA
FIFO; some data is left in the DMA FIFO, but not enough to be passed
further to the system memory in a single transfer. In this situation the
8250 UART driver catches the recv timeout interrupt, pauses the
DMA-transfer and terminates it completely, after which the IRQ handler
manually fetches the leftover data from the UART FIFO into the
recv-buffer. But since the DMA-channel has been disabled with the data
left in the DMA FIFO, that data will be just discarded and the recv-buffer
will have a gap of the "current lvl" size in the recv-buffer at the tail
of the lately received data portion. So the data will be lost just due to
the misconfigured DMA transfer.

Note this is only relevant for the case of the transfer suspension and
_disabling_. No problem will happen if the transfer will be re-enabled
afterwards or the block transfer is fully completed. In the later case the
"FIFO flush mode" will be executed at the transfer final stage in order to
push out the data left in the DMA FIFO.

In order to fix the denoted problem the DW AHB DMA-engine driver needs to
make sure that the _bursted_ source transfer width is greater or equal to
the single destination transfer (note the HW databook describes more
strict constraint than actually required). Since the peripheral-device
side is prescribed by the client driver logic, the memory-side can be only
used for that. The solution can be easily implemented for the DEV_TO_MEM
transfers just by adjusting the memory-channel address width. Sadly it's
not that easy for the MEM_TO_DEV transfers since the mem-to-dma burst size
is normally dynamically determined by the controller. So the only thing
that can be done is to make sure that memory-side address width is greater
than the peripheral device address width.

Fixes: a09820043c ("dw_dmac: autoconfigure data_width or get it via platform data")
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
Acked-by: Andy Shevchenko <andy@kernel.org>
Link: https://lore.kernel.org/r/20240802075100.6475-3-fancer.lancer@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2024-09-04 13:23:40 +02:00
..
bestcomm dmaengine: bestcomm: fix system boot lockups 2021-11-18 19:17:16 +01:00
dw dmaengine: dw: Add memory bus width verification 2024-09-04 13:23:40 +02:00
dw-axi-dmac Avoid hw_desc array overrun in dw-axi-dmac 2024-07-05 09:14:28 +02:00
dw-edma dmaengine: dw-edma: Fix to enable to issue dma request on DMA processing 2023-05-11 23:00:38 +09:00
fsl-dpaa2-qdma dmaengine: fsl-dpaa2-qdma: Fix the size of dma pools 2024-02-23 08:54:56 +01:00
hsu dmaengine: hsu: Account transferred bytes 2021-05-31 09:50:39 +05:30
idxd dmaengine: idxd: Fix possible Use-After-Free in irq_process_work_list 2024-07-05 09:14:32 +02:00
ioat dmaengine: ioatdma: Fix missing kmem_cache_destroy() 2024-07-05 09:14:33 +02:00
ipu dmaengine: ipu: Fix fall-through warning for Clang 2021-07-13 14:38:47 -05:00
lgm dmaengine: lgm: Move DT parsing after initialization 2023-01-24 07:22:47 +01:00
mediatek dmaengine: mediatek: Fix deadlock caused by synchronize_irq() 2023-10-19 23:05:37 +02:00
ppc4xx ppc4xx: replace sscanf() by kstrtoul() 2021-07-28 12:40:51 +05:30
ptdma dmaengine: ptdma: use consistent DMA masks 2024-03-06 14:38:48 +00:00
qcom dma: gpi: remove spurious unlock in gpi_ch_init 2023-05-11 23:00:38 +09:00
sf-pdma dmaengine: sf-pdma: pdma_desc memory leak fix 2023-03-10 09:39:42 +01:00
sh dmaengine: shdma: increase size of 'dev_id' 2024-03-01 13:21:43 +01:00
ti dmaengine: ti: k3-udma: Fix BCHAN count with UHC and HC channels 2024-08-19 05:45:23 +02:00
xilinx dma: xilinx_dpdma: Fix locking 2024-05-02 16:24:49 +02:00
Kconfig dmaengine: tegra210-adma: Update dependency to ARCH_TEGRA 2024-03-26 18:21:25 -04:00
Makefile dmaengine: ptdma: Initial driver for the AMD PTDMA 2021-08-29 19:14:20 +05:30
TODO
acpi-dma.c dmaengine: acpi: Check for errors from acpi_register_gsi() separately 2021-08-06 21:48:11 +05:30
altera-msgdma.c dmaengine: altera-msgdma: make response port optional 2021-07-28 12:25:10 +05:30
amba-pl08x.c treewide: Use fallthrough pseudo-keyword 2020-08-23 17:36:59 -05:00
at_hdmac.c dmaengine: at_hdmac: Check return code of dma_async_device_register 2022-11-16 09:58:30 +01:00
at_hdmac_regs.h dmaengine: at_hdmac: Fix at_lli struct definition 2022-11-16 09:58:28 +01:00
at_xdmac.c dmaengine: at_xdmac: fix potential Oops in at_xdmac_prep_interleaved() 2023-06-09 10:32:15 +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
dma-axi-dmac.c dmaengine: axi-dmac: fix possible race in remove() 2024-07-05 09:14:21 +02:00
dma-jz4780.c dmaengine: jz4780: Add support for the JZ4760(B) 2021-01-26 22:45:22 +05:30
dmaengine.c dmaengine: fix NULL pointer in channel unregistration function 2024-02-23 08:54:21 +01:00
dmaengine.h dmaengine: dmaengine_desc_callback_valid(): Check for `callback_result` 2021-11-18 19:17:02 +01:00
dmatest.c dmaengine: dmatest: Use dmaengine_get_dma_device 2020-12-11 21:20:08 +05:30
ep93xx_dma.c dmaengine: ep93xx: Prepare clock before using it 2021-08-02 12:27:10 +05:30
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: init irq after reg initialization 2024-03-06 14:38:48 +00:00
fsl_raid.c dmaengine: fsl: remove bad channel update 2020-10-05 09:59:17 +05:30
fsl_raid.h
fsldma.c dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function 2021-01-12 18:00:39 +05:30
fsldma.h fsldma: fix very broken 32-bit ppc ioread64 functionality 2020-08-29 13:50:56 -07:00
hisi_dma.c dmaengine: hisilicon: Add multi-thread support for a DMA channel 2022-10-26 12:35:08 +02:00
idma64.c dmaengine: idma64: Add check for dma_set_max_seg_size 2024-06-16 13:39:34 +02:00
idma64.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
img-mdc-dma.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 422 2019-06-05 17:37:15 +02:00
imx-dma.c dmaengine: imx-dma: Cast of_device_get_match_data() with (uintptr_t) 2022-08-17 14:23:56 +02:00
imx-sdma.c dmaengine: imx-sdma: Fix a possible memory leak in sdma_transfer_init 2023-02-06 07:59:00 +01: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: use the correct HiSilicon copyright 2021-04-12 17:14:53 +05:30
lpc18xx-dmamux.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
mcf-edma.c dmaengine: mcf-edma: Fix a potential un-allocated memory access 2023-08-16 18:22:02 +02:00
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 2020-12-29 10:08:00 +05:30
mmp_pdma.c dmaengine: pxa/mmp: stop referencing config->slave_id 2022-01-27 11:04:13 +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: moxart-dma: remove redundant irqsave and irqrestore in hardIRQ 2020-11-09 17:25:54 +05:30
mpc512x_dma.c dmaengine: mpc512x: Fix fall-through warning for Clang 2021-07-14 11:05:55 -05:00
mv_xor.c dmaengine: mv_xor: drop of_match_ptr from of_device_id table 2020-11-24 23:02:20 +05:30
mv_xor.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 288 2019-06-05 17:36:37 +02:00
mv_xor_v2.c dmaengine: mv_xor_v2: Fix an error code. 2023-05-11 23:00:37 +09:00
mxs-dma.c dmaengine: mxs: use platform_driver_register 2022-10-26 12:34:23 +02:00
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-07-28 12:54:50 +05:30
owl-dma.c dmaengine: owl: fix register access functions 2024-05-02 16:24:49 +02: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: Revert "dmaengine: pl330: issue_pending waits until WFP state" 2024-05-17 11:50:43 +02:00
plx_dma.c dmaengine: plx_dma: add a missing put_device() on error path 2021-04-12 15:13:51 +05:30
pxa_dma.c dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc() 2023-11-20 11:08:26 +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
sprd-dma.c dmaengine: sprd: Cleanup in .remove() after pm_runtime_get_sync() failed 2022-08-25 11:40:38 +02:00
st_fdma.c dmaengine: st_fdma: fix MODULE_ALIAS 2021-12-22 09:32:41 +01:00
st_fdma.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
ste_dma40.c dmaengine: ste_dma40: Fix PM disable depth imbalance in d40_probe 2023-11-08 17:26:45 +01:00
ste_dma40_ll.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 194 2019-05-30 11:29:22 -07:00
ste_dma40_ll.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 194 2019-05-30 11:29:22 -07:00
stm32-dma.c dmaengine: stm32-dma: avoid 64-bit division in stm32_dma_get_max_width 2021-11-18 19:17:11 +01:00
stm32-dmamux.c dmaengine: stm32-dmamux: Fix PM disable depth imbalance in stm32_dmamux_probe 2022-02-23 12:03:21 +01:00
stm32-mdma.c dmaengine: stm32-mdma: correct desc prep when channel running 2023-11-28 16:56:31 +00:00
sun4i-dma.c dmaengine: sun4i: Use list_move_tail instead of list_del/list_add_tail 2021-06-07 17:06:38 +05:30
sun6i-dma.c dmaengine: sun6i: Add support for A100 DMA 2020-11-18 16:28:49 +05:30
tegra20-apb-dma.c dmaengine: tegra20: Fix runtime PM imbalance on error 2021-04-12 15:10:44 +05:30
tegra210-adma.c dmaengine: tegra210-adma: fix global intr clear 2023-01-24 07:22:47 +01:00
timb_dma.c dmaengine: timb_dma: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
txx9dmac.c dmaengine: txx9dmac: convert tasklets to use new tasklet_setup() API 2020-09-18 12:19:07 +05:30
txx9dmac.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
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 11:05:23 +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