From: bui duc phuc <[email protected]>

On unbind, fsl_asrc_remove() gates the clocks before devres
unregisters the component and frees the IRQ, while the component
may still be in use.

Move the cleanup to devm. The action that disables the clocks is
registered before devm_pm_runtime_enable(), so it runs last, after
runtime PM is disabled, as in fsl_asrc_remove().

Signed-off-by: bui duc phuc <[email protected]>
---
 sound/soc/fsl/fsl_asrc.c | 48 ++++++++++++++++++++++++----------------
 1 file changed, 29 insertions(+), 19 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index c97f814d7358..09e09164a106 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1258,6 +1258,15 @@ static int fsl_asrc_m2m_pair_resume(struct fsl_asrc_pair 
*pair)
 static int fsl_asrc_runtime_resume(struct device *dev);
 static int fsl_asrc_runtime_suspend(struct device *dev);
 
+/* devm action: runtime suspend the device if it is not runtime suspended yet 
*/
+static void fsl_asrc_runtime_suspend_action(void *data)
+{
+       struct device *dev = data;
+
+       if (!pm_runtime_status_suspended(dev))
+               fsl_asrc_runtime_suspend(dev);
+}
+
 static int fsl_asrc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1413,22 +1422,34 @@ static int fsl_asrc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, asrc);
        spin_lock_init(&asrc->lock);
-       pm_runtime_enable(&pdev->dev);
+
+       /*
+        * Ensure the device is suspended after the IRQ and component
+        * have been released.
+        */
+       ret = devm_add_action(&pdev->dev, fsl_asrc_runtime_suspend_action,
+                             &pdev->dev);
+       if (ret)
+               return ret;
+
+       ret = devm_pm_runtime_enable(&pdev->dev);
+       if (ret)
+               return ret;
        if (!pm_runtime_enabled(&pdev->dev)) {
                ret = fsl_asrc_runtime_resume(&pdev->dev);
                if (ret)
-                       goto err_pm_disable;
+                       return ret;
        }
 
        ret = pm_runtime_resume_and_get(&pdev->dev);
        if (ret < 0)
-               goto err_pm_get_sync;
+               return ret;
 
        ret = fsl_asrc_init(asrc);
        if (ret) {
                dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
                pm_runtime_put_noidle(&pdev->dev);
-               goto err_pm_get_sync;
+               return ret;
        }
 
        /* Request the IRQ only once the device is initialized */
@@ -1436,32 +1457,25 @@ static int fsl_asrc_probe(struct platform_device *pdev)
                               dev_name(&pdev->dev), asrc);
        if (ret) {
                pm_runtime_put_noidle(&pdev->dev);
-               goto err_pm_get_sync;
+               return ret;
        }
 
        ret = pm_runtime_put_sync(&pdev->dev);
        if (ret < 0 && ret != -ENOSYS)
-               goto err_pm_get_sync;
+               return ret;
 
        ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component,
                                              fsl_asrc_dai, 
ARRAY_SIZE(fsl_asrc_dai));
        if (ret)
-               goto err_pm_get_sync;
+               return ret;
 
        ret = fsl_asrc_m2m_init(asrc);
        if (ret) {
                dev_err(&pdev->dev, "failed to init m2m device %d\n", ret);
-               goto err_pm_get_sync;
+               return ret;
        }
 
        return 0;
-
-err_pm_get_sync:
-       if (!pm_runtime_status_suspended(&pdev->dev))
-               fsl_asrc_runtime_suspend(&pdev->dev);
-err_pm_disable:
-       pm_runtime_disable(&pdev->dev);
-       return ret;
 }
 
 static void fsl_asrc_remove(struct platform_device *pdev)
@@ -1469,10 +1483,6 @@ static void fsl_asrc_remove(struct platform_device *pdev)
        struct fsl_asrc *asrc = dev_get_drvdata(&pdev->dev);
 
        fsl_asrc_m2m_exit(asrc);
-
-       pm_runtime_disable(&pdev->dev);
-       if (!pm_runtime_status_suspended(&pdev->dev))
-               fsl_asrc_runtime_suspend(&pdev->dev);
 }
 
 static int fsl_asrc_runtime_resume(struct device *dev)
-- 
2.43.0


Reply via email to