From: John Keeping Date: Tue, 17 Jul 2018 10:48:16 +0000 (+0100) Subject: dmaengine: pl330: fix irq race with terminate_all X-Git-Tag: v4.19-rc1~95^2^2 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=e49756544a21f5625b379b3871d27d8500764670;p=linux.git dmaengine: pl330: fix irq race with terminate_all In pl330_update() when checking if a channel has been aborted, the channel's lock is not taken, only the overall pl330_dmac lock. But in pl330_terminate_all() the aborted flag (req_running==-1) is set under the channel lock and not the pl330_dmac lock. With threaded interrupts, this leads to a potential race: pl330_terminate_all pl330_update ------------------- ------------ lock channel entry lock pl330 _stop channel unlock pl330 lock pl330 check req_running != -1 req_running = -1 _start channel Signed-off-by: John Keeping Signed-off-by: Vinod Koul --- diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 451370da909d..9e38947f6ffe 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2256,13 +2256,14 @@ static int pl330_terminate_all(struct dma_chan *chan) pm_runtime_get_sync(pl330->ddma.dev); spin_lock_irqsave(&pch->lock, flags); + spin_lock(&pl330->lock); _stop(pch->thread); - spin_unlock(&pl330->lock); - pch->thread->req[0].desc = NULL; pch->thread->req[1].desc = NULL; pch->thread->req_running = -1; + spin_unlock(&pl330->lock); + power_down = pch->active; pch->active = false;