Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Brad Kim and committed by
Vinod Koul
8f6b6d06 78e7a522

+5 -5
+5 -5
drivers/dma/sf-pdma/sf-pdma.c
··· 295 295 } 296 296 spin_unlock_irqrestore(&chan->lock, flags); 297 297 298 - dmaengine_desc_get_callback_invoke(desc->async_tx, NULL); 298 + spin_lock_irqsave(&chan->vchan.lock, flags); 299 + list_del(&chan->desc->vdesc.node); 300 + vchan_cookie_complete(&chan->desc->vdesc); 301 + spin_unlock_irqrestore(&chan->vchan.lock, flags); 299 302 } 300 303 301 304 static void sf_pdma_errbh_tasklet(unsigned long arg) ··· 335 332 residue = readq(regs->residue); 336 333 337 334 if (!residue) { 338 - list_del(&chan->desc->vdesc.node); 339 - vchan_cookie_complete(&chan->desc->vdesc); 335 + tasklet_hi_schedule(&chan->done_tasklet); 340 336 } else { 341 337 /* submit next trascatioin if possible */ 342 338 struct sf_pdma_desc *desc = chan->desc; ··· 348 346 } 349 347 350 348 spin_unlock_irqrestore(&chan->vchan.lock, flags); 351 - 352 - tasklet_hi_schedule(&chan->done_tasklet); 353 349 354 350 return IRQ_HANDLED; 355 351 }