[PATCH 19/20] ASoC: mediatek: mt8186: Unwind runtime resume failures

Pengpeng Hou <[email protected]>
Newsgroups gmane.linux.sound,gmane.linux.kernel,gmane.linux.ports.arm.kernel,gmane.linux.ports.arm.mediatek
Message-ID <[email protected]>
mt8186_afe_runtime_resume() enables the base clocks and then a range of
clock gates before replaying the register cache.
mt8186_afe_enable_cgs() returns on the first failed gate without
disabling gates from the successful prefix, and runtime resume also
ignores regcache_sync().

Make the gate helper unwind its own partial prefix.  Route gate setup
failure through base-clock cleanup, and on cache replay failure restore
cache-only and dirty state before disabling all gates and base clocks.

The issue was identified via static analysis and manually reviewed.

Fixes: 097e874ad3fc ("ASoC: mediatek: mt8186: add platform driver")

Assisted-by: LLM
Signed-off-by: Pengpeng Hou <[email protected]>
---
 sound/soc/mediatek/mt8186/mt8186-afe-clk.c |  2 ++
 sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
index daaca36a2d08..a7034aea2678 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
@@ -221,6 +221,8 @@ int mt8186_afe_enable_cgs(struct mtk_base_afe *afe)
 		if (ret) {
 			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
 				__func__, aud_clks[i], ret);
+			while (--i >= CLK_I2S1_BCLK)
+				clk_disable_unprepare(afe_priv->clk[i]);
 			return ret;
 		}
 	}
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
index 44a521c3a610..2888a49e9db2 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
@@ -2737,13 +2737,18 @@ static int mt8186_afe_runtime_resume(struct device *dev)
 
 	ret = mt8186_afe_enable_cgs(afe);
 	if (ret)
-		return ret;
+		goto disable_clock;
 
 	if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
 		goto skip_regmap;
 
 	regcache_cache_only(afe->regmap, false);
-	regcache_sync(afe->regmap);
+	ret = regcache_sync(afe->regmap);
+	if (ret) {
+		regcache_cache_only(afe->regmap, true);
+		regcache_mark_dirty(afe->regmap);
+		goto disable_cgs;
+	}
 
 	/* enable audio sys DCM for power saving */
 	regmap_update_bits(afe_priv->infracfg, PERI_BUS_DCM_CTRL, BIT(29), BIT(29));
@@ -2761,6 +2766,12 @@ static int mt8186_afe_runtime_resume(struct device *dev)
 
 skip_regmap:
 	return 0;
+
+disable_cgs:
+	mt8186_afe_disable_cgs(afe);
+disable_clock:
+	mt8186_afe_disable_clock(afe);
+	return ret;
 }
 
 static int mt8186_afe_component_probe(struct snd_soc_component *component)
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.