From: Thomas Pfaff <tpfaff@xxxxxxx> calling atc_chain_complete with unlocked spinlock in the middle of atc_advance_work might cause a race condition regarding the next dma transfer. If the dma_callback is handled by a task with higher priority and starts a new dma transfer it might call atc_issue_pending before the spinlock is locked again. In this case, the active list contains already a new entry that is started, and atc_advance_work tries to start it again, which will fail because the channel is already enabled. Signed-off-by: Thomas Pfaff <tpfaff@xxxxxxx> --- diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 68c1bfbefc5c..9b2a1cf23763 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -529,15 +529,12 @@ static void atc_advance_work(struct at_dma_chan *atchan) desc = atc_first_active(atchan); /* Remove the transfer node from the active list. */ list_del_init(&desc->desc_node); - spin_unlock_irqrestore(&atchan->lock, flags); - atc_chain_complete(atchan, desc); - /* advance work */ - spin_lock_irqsave(&atchan->lock, flags); atc_start_next(atchan); spin_unlock_irqrestore(&atchan->lock, flags); -} + atc_chain_complete(atchan, desc); +} /** * atc_handle_error - handle errors reported by DMA controller