dmaengine: at_xdmac: Fix concurrency over xfers_list
authorTudor Ambarus <tudor.ambarus@microchip.com>
Wed, 15 Dec 2021 11:01:10 +0000 (13:01 +0200)
committerVinod Koul <vkoul@kernel.org>
Wed, 5 Jan 2022 10:20:03 +0000 (15:50 +0530)
Since tx_submit can be called from a hard IRQ, xfers_list must be
protected with a lock to avoid concurency on the list's elements.
Since at_xdmac_handle_cyclic() is called from a tasklet, spin_lock_irq
is enough to protect from a hard IRQ.

Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel eXtended DMA Controller driver")
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Link: https://lore.kernel.org/r/20211215110115.191749-8-tudor.ambarus@microchip.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/at_xdmac.c

index b6547f1b5645a0b6187e850ec9328c06dce6ce3b..eeb03065d4848091d88571ba726384d28bb27f1f 100644 (file)
@@ -1608,14 +1608,17 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
        struct at_xdmac_desc            *desc;
        struct dma_async_tx_descriptor  *txd;
 
-       if (!list_empty(&atchan->xfers_list)) {
-               desc = list_first_entry(&atchan->xfers_list,
-                                       struct at_xdmac_desc, xfer_node);
-               txd = &desc->tx_dma_desc;
-
-               if (txd->flags & DMA_PREP_INTERRUPT)
-                       dmaengine_desc_get_callback_invoke(txd, NULL);
+       spin_lock_irq(&atchan->lock);
+       if (list_empty(&atchan->xfers_list)) {
+               spin_unlock_irq(&atchan->lock);
+               return;
        }
+       desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc,
+                               xfer_node);
+       spin_unlock_irq(&atchan->lock);
+       txd = &desc->tx_dma_desc;
+       if (txd->flags & DMA_PREP_INTERRUPT)
+               dmaengine_desc_get_callback_invoke(txd, NULL);
 }
 
 static void at_xdmac_handle_error(struct at_xdmac_chan *atchan)