dma: imx-sdma: keep the callbacks invoked in the tasklet
The current code keeps the callbacks invoked from interrupt context, this
does not conform to the Documentation/dmaengine.txt.
So add tasklet support to fix this issue.
Signed-off-by: Huang Shijie <b32955@freescale.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d3e38e2..5a45777 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -271,6 +271,7 @@
enum dma_status status;
unsigned int chn_count;
unsigned int chn_real_count;
+ struct tasklet_struct tasklet;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -534,8 +535,10 @@
sdmac->desc.callback(sdmac->desc.callback_param);
}
-static void mxc_sdma_handle_channel(struct sdma_channel *sdmac)
+static void sdma_tasklet(unsigned long data)
{
+ struct sdma_channel *sdmac = (struct sdma_channel *) data;
+
complete(&sdmac->done);
/* not interested in channel 0 interrupts */
@@ -560,7 +563,7 @@
int channel = fls(stat) - 1;
struct sdma_channel *sdmac = &sdma->channel[channel];
- mxc_sdma_handle_channel(sdmac);
+ tasklet_schedule(&sdmac->tasklet);
__clear_bit(channel, &stat);
}
@@ -1359,6 +1362,8 @@
dma_cookie_init(&sdmac->chan);
sdmac->channel = i;
+ tasklet_init(&sdmac->tasklet, sdma_tasklet,
+ (unsigned long) sdmac);
/*
* Add the channel to the DMAC list. Do not add channel 0 though
* because we need it internally in the SDMA driver. This also means