[PATCH v2 3/9] ASoC: nau8825: restore safe state after resume errors
From: Pengpeng Hou
Date: Tue Oct 13 2026 - 23:25:48 EST
nau8825_resume() ignores regcache_sync() failure before continuing
dependent resume operations. Restore cache-only mode, leave the cache
dirty, and return the replay error before those operations.
Do not start crosstalk protection or enable its IRQ after a failed
replay.
ASoC still marks the component resumed when the callback reports failure.
Track the suspend-owned IRQ disable so another suspend does not increment
the disable depth again after a failed resume. A later successful resume
releases that one disable reference. This does not add automatic retry or
change the framework's best-effort card resume policy.
The issue was found by our static-analysis tool and manually reviewed.
Fixes: 4454a8378be5 ("ASoC: nau8825: add pm function")
Assisted-by: gpt 5
Signed-off-by: Pengpeng Hou <hppiscas@xxxxxxx>
---
Changes since v1:
- restore cache-only mode and dirty state on replay failure
- keep suspend-owned IRQ disables balanced across failed resume cycles
- send as one correctly threaded series, as Mark requested
Previous series:
https://lore.kernel.org/all/20260906034321.86080-1-hppiscas@xxxxxxx/
sound/soc/codecs/nau8825.c | 17 ++++++++++++++---
sound/soc/codecs/nau8825.h | 1 +
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index 63d927f3140902e179bd491f757f4c47e8c314b1..11c548b99ea6d758ba3843090ee65b3d9f8f8245 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -2683,7 +2683,10 @@ static int __maybe_unused nau8825_suspend(struct snd_soc_component *component)
{
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
- disable_irq(nau8825->irq);
+ if (!nau8825->suspend_irq_disabled) {
+ disable_irq(nau8825->irq);
+ nau8825->suspend_irq_disabled = true;
+ }
snd_soc_dapm_force_bias_level(nau8825->dapm, SND_SOC_BIAS_OFF);
/* Power down codec power; don't suppoet button wakeup */
snd_soc_dapm_disable_pin(nau8825->dapm, "SAR");
@@ -2701,12 +2704,20 @@ static int __maybe_unused nau8825_resume(struct snd_soc_component *component)
int ret;
regcache_cache_only(nau8825->regmap, false);
- regcache_sync(nau8825->regmap);
+ ret = regcache_sync(nau8825->regmap);
+ if (ret) {
+ regcache_cache_only(nau8825->regmap, true);
+ regcache_mark_dirty(nau8825->regmap);
+ return ret;
+ }
nau8825->xtalk_protect = true;
ret = nau8825_sema_acquire(nau8825, 0);
if (ret)
nau8825->xtalk_protect = false;
- enable_irq(nau8825->irq);
+ if (nau8825->suspend_irq_disabled) {
+ nau8825->suspend_irq_disabled = false;
+ enable_irq(nau8825->irq);
+ }
return 0;
}
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h
index 2abfbb5184da80f3637f06d57a7564fbf1c7574c..8238570ed48c2b147a4a1a0d7061603f8b9b4835 100644
--- a/sound/soc/codecs/nau8825.h
+++ b/sound/soc/codecs/nau8825.h
@@ -502,6 +502,7 @@ struct nau8825 {
struct semaphore xtalk_sem;
int sw_id;
int irq;
+ bool suspend_irq_disabled;
int mclk_freq; /* 0 - mclk is disabled */
int button_pressed;
int micbias_voltage;
base-commit: 8ef28aef33f2d5da6959ad6b579ec3cfccc009f6