dmaengine: qcom_hidma: pause the channel on shutdown
authorSinan Kaya <okaya@codeaurora.org>
Sat, 25 Mar 2017 23:04:03 +0000 (19:04 -0400)
committerVinod Koul <vinod.koul@intel.com>
Mon, 27 Mar 2017 05:13:38 +0000 (10:43 +0530)
We need to ensure that all DMAs and interrupts are cleared during
shutdown operation in order for kexec to start the next kernel clearly.

Otherwise, HW could be performing a DMA into random addresses in the
middle of second kernel start.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
drivers/dma/qcom/hidma.c

index 3c982c96b4b7ccc4f65bec3ed048163be6c86bf8..5072a7d306d480724bb5d233f72c3bbf01d0efde 100644 (file)
@@ -865,6 +865,20 @@ bailout:
        return rc;
 }
 
+static void hidma_shutdown(struct platform_device *pdev)
+{
+       struct hidma_dev *dmadev = platform_get_drvdata(pdev);
+
+       dev_info(dmadev->ddev.dev, "HI-DMA engine shutdown\n");
+
+       pm_runtime_get_sync(dmadev->ddev.dev);
+       if (hidma_ll_disable(dmadev->lldev))
+               dev_warn(dmadev->ddev.dev, "channel did not stop\n");
+       pm_runtime_mark_last_busy(dmadev->ddev.dev);
+       pm_runtime_put_autosuspend(dmadev->ddev.dev);
+
+}
+
 static int hidma_remove(struct platform_device *pdev)
 {
        struct hidma_dev *dmadev = platform_get_drvdata(pdev);
@@ -908,6 +922,7 @@ MODULE_DEVICE_TABLE(of, hidma_match);
 static struct platform_driver hidma_driver = {
        .probe = hidma_probe,
        .remove = hidma_remove,
+       .shutdown = hidma_shutdown,
        .driver = {
                   .name = "hidma",
                   .of_match_table = hidma_match,