dmaengine: sf-pdma: Add multithread support for a DMA channel
authorViacheslav Mitrofanov <v.v.mitrofanov@yadro.com>
Fri, 1 Jul 2022 08:29:42 +0000 (11:29 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:23:49 +0000 (14:23 +0200)
commit5ab2782c944e324008ef5d658f2494a9f0e3c5ac
treeacfb19621ab556491c6f69e0eefeca6f0244ac85
parentebea637e9f4b5184b16a046e5be23e244694e61b
dmaengine: sf-pdma: Add multithread support for a DMA channel

[ Upstream commit b2cc5c465c2cb8ab697c3fd6583c614e3f6cfbcc ]

When we get a DMA channel and try to use it in multiple threads it
will cause oops and hanging the system.

% echo 64 > /sys/module/dmatest/parameters/threads_per_chan
% echo 10000 > /sys/module/dmatest/parameters/iterations
% echo 1 > /sys/module/dmatest/parameters/run
[   89.480664] Unable to handle kernel NULL pointer dereference at virtual
               address 00000000000000a0
[   89.488725] Oops [#1]
[   89.494708] CPU: 2 PID: 1008 Comm: dma0chan0-copy0 Not tainted
               5.17.0-rc5
[   89.509385] epc : vchan_find_desc+0x32/0x46
[   89.513553]  ra : sf_pdma_tx_status+0xca/0xd6

This happens because of data race. Each thread rewrite channels's
descriptor as soon as device_prep_dma_memcpy() is called. It leads to the
situation when the driver thinks that it uses right descriptor that
actually is freed or substituted for other one.

With current fixes a descriptor changes its value only when it has
been used. A new descriptor is acquired from vc->desc_issued queue that
is already filled with descriptors that are ready to be sent. Threads
have no direct access to DMA channel descriptor. Now it is just possible
to queue a descriptor for further processing.

Fixes: 6973886ad58e ("dmaengine: sf-pdma: add platform DMA support for HiFive Unleashed A00")
Signed-off-by: Viacheslav Mitrofanov <v.v.mitrofanov@yadro.com>
Link: https://lore.kernel.org/r/20220701082942.12835-1-v.v.mitrofanov@yadro.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/dma/sf-pdma/sf-pdma.c