Commit ea62aa80 authored by Vinod Koul's avatar Vinod Koul
Browse files

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: default avatarVinod Koul <vinod.koul@intel.com>
parent 6f93b93b
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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 @@ static int __init imxdma_probe(struct platform_device *pdev)
	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)