Commit 50db2050 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Vinod Koul

dmaengine: xilinx: Introduce synchronize() callback

The Xilinx dmaengine driver uses a tasklet to process completed
descriptors and execute their callbacks.

Currently consumers of the DMA channel have to no method of synchronization
against this tasklet when using the Xilinx dmaengine drivers. This can lead
to race conditions when the consumer frees resources that are accessed in
the callback before the tasklet has finished running.

It is not enough to just call dmaengine_terminal_all() since on a
multi-processor system the tasklet can run concurrently to it and might
call the callback after dmaengine_terminate_all() has already finished.

To mitigate this issue implement the synchronize() callback for the driver,
which will wait until the tasklet has finished.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Link: https://lore.kernel.org/r/20210313125311.4823-1-lars@metafoo.deSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent a38fd874
...@@ -2453,6 +2453,13 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan) ...@@ -2453,6 +2453,13 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
return 0; return 0;
} }
static void xilinx_dma_synchronize(struct dma_chan *dchan)
{
struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
tasklet_kill(&chan->tasklet);
}
/** /**
* xilinx_dma_channel_set_config - Configure VDMA channel * xilinx_dma_channel_set_config - Configure VDMA channel
* Run-time configuration for Axi VDMA, supports: * Run-time configuration for Axi VDMA, supports:
...@@ -3074,6 +3081,7 @@ static int xilinx_dma_probe(struct platform_device *pdev) ...@@ -3074,6 +3081,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
xdev->common.device_free_chan_resources = xdev->common.device_free_chan_resources =
xilinx_dma_free_chan_resources; xilinx_dma_free_chan_resources;
xdev->common.device_terminate_all = xilinx_dma_terminate_all; xdev->common.device_terminate_all = xilinx_dma_terminate_all;
xdev->common.device_synchronize = xilinx_dma_synchronize;
xdev->common.device_tx_status = xilinx_dma_tx_status; xdev->common.device_tx_status = xilinx_dma_tx_status;
xdev->common.device_issue_pending = xilinx_dma_issue_pending; xdev->common.device_issue_pending = xilinx_dma_issue_pending;
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) { if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment