MLK-17410: ASoC: fsl_asrc: fix kernel panic in suspend resume
authorShengjiu Wang <shengjiu.wang@nxp.com>
Mon, 22 Jan 2018 07:23:25 +0000 (15:23 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:53:27 +0000 (14:53 -0500)
After ASRC convert, there will be kernel panic

[   54.365777] [<ffff000008636528>] regmap_mmio_read32le+0x8/0x18
[   54.371615] [<ffff00000862f004>] _regmap_bus_reg_read+0x14/0x20
[   54.377538] [<ffff000008630830>] _regmap_read+0x60/0xe8
[   54.382769] [<ffff000008630c30>] _regmap_update_bits+0xa0/0xf0
[   54.388606] [<ffff000008631be8>] regmap_update_bits_base+0x60/0x90
[   54.394794] [<ffff000008a275c4>] fsl_asrc_resume+0x74/0xa8
[   54.400287] [<ffff0000086226a8>] dpm_run_callback.isra.6+0x30/0x98
[   54.406468] [<ffff000008622b20>] device_resume+0x100/0x188
[   54.411958] [<ffff0000086239c8>] dpm_resume+0x100/0x218
[   54.417188] [<ffff000008623c9c>] dpm_resume_end+0x14/0x28
[   54.422594] [<ffff0000080fd990>] suspend_devices_and_enter+0x138/0x500
[   54.429124] [<ffff0000080fdfc0>] pm_suspend+0x268/0x2d8
[   54.434348] [<ffff0000080fcabc>] state_store+0x84/0xf8
[   54.439491] [<ffff0000083dfcac>] kobj_attr_store+0x14/0x28
[   54.444982] [<ffff000008254e58>] sysfs_kf_write+0x48/0x58
[   54.450383] [<ffff0000082541c8>] kernfs_fop_write+0xb0/0x1f8
[   54.456050] [<ffff0000081dc5c4>] __vfs_write+0x1c/0x100
[   54.461277] [<ffff0000081dd3cc>] vfs_write+0x9c/0x1b0
[   54.466332] [<ffff0000081de814>] SyS_write+0x44/0xa0
[   54.471295] [<ffff000008082f4c>] __sys_trace_return+0x0/0x4

The reason is that the power of subsystem is disabled in suspend
the register can't be accessed. so we need to call pm_runtime_force_suspend
and pm_runtime_force_resume in suspend and resume state.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
sound/soc/fsl/fsl_asrc.c

index 4236f8a..da902f6 100644 (file)
@@ -1268,41 +1268,22 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
 static int fsl_asrc_suspend(struct device *dev)
 {
        struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+       int ret;
 
        fsl_asrc_m2m_suspend(asrc_priv);
 
-       regmap_read(asrc_priv->regmap, REG_ASRCFG,
-                   &asrc_priv->regcache_cfg);
-
-       regcache_cache_only(asrc_priv->regmap, true);
-       regcache_mark_dirty(asrc_priv->regmap);
+       ret = pm_runtime_force_suspend(dev);
 
-       return 0;
+       return ret;
 }
 
 static int fsl_asrc_resume(struct device *dev)
 {
-       struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
-       u32 asrctr;
-
-       /* Stop all pairs provisionally */
-       regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr);
-       regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
-                          ASRCTR_ASRCEi_ALL_MASK, 0);
-
-       /* Restore all registers */
-       regcache_cache_only(asrc_priv->regmap, false);
-       regcache_sync(asrc_priv->regmap);
-
-       regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
-                          ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
-                          ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
+       int ret;
 
-       /* Restart enabled pairs */
-       regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
-                          ASRCTR_ASRCEi_ALL_MASK, asrctr);
+       ret = pm_runtime_force_resume(dev);
 
-       return 0;
+       return ret;
 }
 #endif /* CONFIG_PM_SLEEP */