| From fcaaba6c7136fe47e5a13352f99a64b019b6d2c5 Mon Sep 17 00:00:00 2001 |
| From: Michael Grzeschik <m.grzeschik@pengutronix.de> |
| Date: Tue, 17 Sep 2013 15:56:08 +0200 |
| Subject: dmaengine: imx-dma: fix callback path in tasklet |
| |
| From: Michael Grzeschik <m.grzeschik@pengutronix.de> |
| |
| commit fcaaba6c7136fe47e5a13352f99a64b019b6d2c5 upstream. |
| |
| We need to free the ld_active list head before jumping into the callback |
| routine. Otherwise the callback could run into issue_pending and change |
| our ld_active list head we just going to free. This will run the channel |
| list into an currupted and undefined state. |
| |
| Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> |
| Signed-off-by: Vinod Koul <vinod.koul@intel.com> |
| Cc: Jonghwan Choi <jhbird.choi@samsung.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/dma/imx-dma.c | 10 ++++++---- |
| 1 file changed, 6 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/dma/imx-dma.c |
| +++ b/drivers/dma/imx-dma.c |
| @@ -627,13 +627,11 @@ static void imxdma_tasklet(unsigned long |
| |
| if (list_empty(&imxdmac->ld_active)) { |
| /* Someone might have called terminate all */ |
| - goto out; |
| + spin_unlock_irqrestore(&imxdma->lock, flags); |
| + return; |
| } |
| desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node); |
| |
| - if (desc->desc.callback) |
| - desc->desc.callback(desc->desc.callback_param); |
| - |
| /* If we are dealing with a cyclic descriptor, keep it on ld_active |
| * and dont mark the descriptor as complete. |
| * Only in non-cyclic cases it would be marked as complete |
| @@ -661,6 +659,10 @@ static void imxdma_tasklet(unsigned long |
| } |
| out: |
| spin_unlock_irqrestore(&imxdma->lock, flags); |
| + |
| + if (desc->desc.callback) |
| + desc->desc.callback(desc->desc.callback_param); |
| + |
| } |
| |
| static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |