[PATCH 19/20] ASoC: mediatek: mt8186: Unwind runtime resume failures
From: Pengpeng Hou
Date: Fri Aug 28 2026 - 07:37:37 EST
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 <pengpeng@xxxxxxxxxxx>
---
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