dmaengine: sf-pdma: Fix an error that calls callback twice

Because a callback is called twice when DMA transfer complete
the second callback may be possible to access a freed memory
if the first callback routines perform the dma_release_channel function.
So this patch serialized the callback functions

Signed-off-by: Brad Kim <brad.kim@semifive.com>
Tested-and-reviewed-by: Green Wan <green.wan@sifive.com>
Signed-off-by: Brad Kim <brad.kim@sifive.com>
Link: https://lore.kernel.org/r/20200903111726.3413-1-brad.kim@sifive.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Brad Kim 2020-09-03 20:17:26 +09:00 committed by Vinod Koul
parent 78e7a52269
commit 8f6b6d0606

View File

@ -295,7 +295,10 @@ static void sf_pdma_donebh_tasklet(unsigned long arg)
}
spin_unlock_irqrestore(&chan->lock, flags);
dmaengine_desc_get_callback_invoke(desc->async_tx, NULL);
spin_lock_irqsave(&chan->vchan.lock, flags);
list_del(&chan->desc->vdesc.node);
vchan_cookie_complete(&chan->desc->vdesc);
spin_unlock_irqrestore(&chan->vchan.lock, flags);
}
static void sf_pdma_errbh_tasklet(unsigned long arg)
@ -332,8 +335,7 @@ static irqreturn_t sf_pdma_done_isr(int irq, void *dev_id)
residue = readq(regs->residue);
if (!residue) {
list_del(&chan->desc->vdesc.node);
vchan_cookie_complete(&chan->desc->vdesc);
tasklet_hi_schedule(&chan->done_tasklet);
} else {
/* submit next trascatioin if possible */
struct sf_pdma_desc *desc = chan->desc;
@ -347,8 +349,6 @@ static irqreturn_t sf_pdma_done_isr(int irq, void *dev_id)
spin_unlock_irqrestore(&chan->vchan.lock, flags);
tasklet_hi_schedule(&chan->done_tasklet);
return IRQ_HANDLED;
}