summaryrefslogtreecommitdiff
path: root/drivers/dma/imx-dma.c
diff options
context:
space:
mode:
authorVinod Koul <vinod.koul@intel.com>2016-07-02 12:55:01 +0300
committerVinod Koul <vinod.koul@intel.com>2016-07-16 17:49:01 +0300
commitea62aa80bbcc881d0805cbee9afd74e3d029e48e (patch)
treecf718b1312b51824c0e38176a3ea230a39f65e97 /drivers/dma/imx-dma.c
parent6f93b93b2a1bd53f1dad9f3deb4e75874db0256a (diff)
downloadlinux-ea62aa80bbcc881d0805cbee9afd74e3d029e48e.tar.xz
dmaengine: imx-dma: explicitly freeup irq
dmaengine device should explicitly call devm_free_irq() when using devm_request_irq(). The irq is still ON when devices remove is executed and irq should be quiesced before remove is completed. Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/imx-dma.c')
-rw-r--r--drivers/dma/imx-dma.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 48d85f8b95fe..9301d3d09563 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -167,6 +167,7 @@ struct imxdma_channel {
u32 ccr_to_device;
bool enabled_2d;
int slot_2d;
+ unsigned int irq;
};
enum imx_dma_type {
@@ -186,6 +187,9 @@ struct imxdma_engine {
struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS];
struct imxdma_channel channel[IMX_DMA_CHANNELS];
enum imx_dma_type devtype;
+ unsigned int irq;
+ unsigned int irq_err;
+
};
struct imxdma_filter_data {
@@ -1100,6 +1104,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
dev_warn(imxdma->dev, "Can't register IRQ for DMA\n");
goto disable_dma_ahb_clk;
}
+ imxdma->irq = irq;
irq_err = platform_get_irq(pdev, 1);
if (irq_err < 0) {
@@ -1113,6 +1118,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");
goto disable_dma_ahb_clk;
}
+ imxdma->irq_err = irq_err;
}
/* enable DMA module */
@@ -1150,6 +1156,8 @@ static int __init imxdma_probe(struct platform_device *pdev)
irq + i, i);
goto disable_dma_ahb_clk;
}
+
+ imxdmac->irq = irq + i;
init_timer(&imxdmac->watchdog);
imxdmac->watchdog.function = &imxdma_watchdog;
imxdmac->watchdog.data = (unsigned long)imxdmac;
@@ -1217,10 +1225,31 @@ disable_dma_ipg_clk:
return ret;
}
+static void imxdma_free_irq(struct platform_device *pdev, struct imxdma_engine *imxdma)
+{
+ int i;
+
+ if (is_imx1_dma(imxdma)) {
+ disable_irq(imxdma->irq);
+ disable_irq(imxdma->irq_err);
+ }
+
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ struct imxdma_channel *imxdmac = &imxdma->channel[i];
+
+ if (!is_imx1_dma(imxdma))
+ disable_irq(imxdmac->irq);
+
+ tasklet_kill(&imxdmac->dma_tasklet);
+ }
+}
+
static int imxdma_remove(struct platform_device *pdev)
{
struct imxdma_engine *imxdma = platform_get_drvdata(pdev);
+ imxdma_free_irq(pdev, imxdma);
+
dma_async_device_unregister(&imxdma->dma_device);
if (pdev->dev.of_node)