diff options
author | Huang Shijie <b32955@freescale.com> | 2012-04-28 06:15:42 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@linux.intel.com> | 2012-05-11 01:38:10 -0400 |
commit | abd9ccc84c35cf1e296335a7b655bba40c92386c (patch) | |
tree | 22c39af6cc57d6371cf4d74e76c04c60f979e9b5 /drivers/dma/imx-sdma.c | |
parent | d3f797d93e593aa891f5b04a404b4ab45fd0e66a (diff) |
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>
Diffstat (limited to 'drivers/dma/imx-sdma.c')
-rw-r--r-- | drivers/dma/imx-sdma.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d3e38e28bb6b..5a457777f5c0 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
@@ -271,6 +271,7 @@ struct sdma_channel { | |||
271 | enum dma_status status; | 271 | enum dma_status status; |
272 | unsigned int chn_count; | 272 | unsigned int chn_count; |
273 | unsigned int chn_real_count; | 273 | unsigned int chn_real_count; |
274 | struct tasklet_struct tasklet; | ||
274 | }; | 275 | }; |
275 | 276 | ||
276 | #define IMX_DMA_SG_LOOP BIT(0) | 277 | #define IMX_DMA_SG_LOOP BIT(0) |
@@ -534,8 +535,10 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) | |||
534 | sdmac->desc.callback(sdmac->desc.callback_param); | 535 | sdmac->desc.callback(sdmac->desc.callback_param); |
535 | } | 536 | } |
536 | 537 | ||
537 | static void mxc_sdma_handle_channel(struct sdma_channel *sdmac) | 538 | static void sdma_tasklet(unsigned long data) |
538 | { | 539 | { |
540 | struct sdma_channel *sdmac = (struct sdma_channel *) data; | ||
541 | |||
539 | complete(&sdmac->done); | 542 | complete(&sdmac->done); |
540 | 543 | ||
541 | /* not interested in channel 0 interrupts */ | 544 | /* not interested in channel 0 interrupts */ |
@@ -560,7 +563,7 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id) | |||
560 | int channel = fls(stat) - 1; | 563 | int channel = fls(stat) - 1; |
561 | struct sdma_channel *sdmac = &sdma->channel[channel]; | 564 | struct sdma_channel *sdmac = &sdma->channel[channel]; |
562 | 565 | ||
563 | mxc_sdma_handle_channel(sdmac); | 566 | tasklet_schedule(&sdmac->tasklet); |
564 | 567 | ||
565 | __clear_bit(channel, &stat); | 568 | __clear_bit(channel, &stat); |
566 | } | 569 | } |
@@ -1359,6 +1362,8 @@ static int __init sdma_probe(struct platform_device *pdev) | |||
1359 | dma_cookie_init(&sdmac->chan); | 1362 | dma_cookie_init(&sdmac->chan); |
1360 | sdmac->channel = i; | 1363 | sdmac->channel = i; |
1361 | 1364 | ||
1365 | tasklet_init(&sdmac->tasklet, sdma_tasklet, | ||
1366 | (unsigned long) sdmac); | ||
1362 | /* | 1367 | /* |
1363 | * Add the channel to the DMAC list. Do not add channel 0 though | 1368 | * Add the channel to the DMAC list. Do not add channel 0 though |
1364 | * because we need it internally in the SDMA driver. This also means | 1369 | * because we need it internally in the SDMA driver. This also means |