From: Pengpeng Hou <hppiscas@163.com>
To: Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>
Cc: Pengpeng Hou <hppiscas@163.com>,
Oder Chiou <oder_chiou@realtek.com>,
Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
Bard Liao <bardliao@realtek.com>,
Stephen Warren <swarren@nvidia.com>,
linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org,
Charles Keepax <ckeepax@opensource.cirrus.com>
Subject: [PATCH v2 8/9] ASoC: rt5640: restore safe state after resume errors
Date: Wed, 14 Oct 2026 11:24:51 +0800 [thread overview]
Message-ID: <20261014032452.13456-9-hppiscas@163.com> (raw)
In-Reply-To: <20261014032452.13456-1-hppiscas@163.com>
rt5640_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.
Both the codec IRQ and the optional GPIO jack IRQ can queue jack work.
Quiesce both before cancelling that work, retain their disable
references on replay failure, and clear each reference if jack teardown
frees that IRQ. Restore the optional LDO GPIO on failure and reject new
jack setup until a later replay succeeds; teardown remains allowed.
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: 997b05203b0a ("ASoC: add RT5640 CODEC driver")
Assisted-by: gpt 5
Signed-off-by: Pengpeng Hou <hppiscas@163.com>
---
Changes since v1:
- restore cache-only mode and dirty state on replay failure
- keep suspend-owned IRQ disables balanced across failed resume cycles
- cover both IRQ producers and jack teardown/re-registration after failure
- send as one correctly threaded series, as Mark requested
Previous series:
https://lore.kernel.org/all/20260906034321.86080-1-hppiscas@163.com/
sound/soc/codecs/rt5640.c | 37 ++++++++++++++++++++++++++++++++++---
sound/soc/codecs/rt5640.h | 3 +++
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index d6068bb5cb4c841ebbc3892b5f6271fca246701d..8b592370d1294ae70d38cb40998f813b6eddc2ad 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2433,11 +2433,13 @@ static void rt5640_disable_irq_and_cancel_work(void *data)
if (rt5640->jd_gpio_irq_requested) {
free_irq(rt5640->jd_gpio_irq, rt5640);
rt5640->jd_gpio_irq_requested = false;
+ rt5640->suspend_jd_gpio_irq_disabled = false;
}
if (rt5640->irq_requested) {
free_irq(rt5640->irq, rt5640);
rt5640->irq_requested = false;
+ rt5640->suspend_irq_disabled = false;
}
cancel_delayed_work_sync(&rt5640->jack_work);
@@ -2646,6 +2648,10 @@ static int rt5640_set_jack(struct snd_soc_component *component,
{
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+ /* Do not publish fresh IRQs while the register cache is unrestored. */
+ if (jack && rt5640->resume_failed)
+ return -EIO;
+
if (jack) {
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
rt5640_enable_hda_jack_detect(component, jack);
@@ -2803,7 +2809,15 @@ static int rt5640_suspend(struct snd_soc_component *component)
if (rt5640->jack) {
/* disable jack interrupts during system suspend */
- disable_irq(rt5640->irq);
+ if (rt5640->irq_requested && !rt5640->suspend_irq_disabled) {
+ disable_irq(rt5640->irq);
+ rt5640->suspend_irq_disabled = true;
+ }
+ if (rt5640->jd_gpio_irq_requested &&
+ !rt5640->suspend_jd_gpio_irq_disabled) {
+ disable_irq(rt5640->jd_gpio_irq);
+ rt5640->suspend_jd_gpio_irq_disabled = true;
+ }
cancel_delayed_work_sync(&rt5640->jack_work);
cancel_delayed_work_sync(&rt5640->bp_work);
}
@@ -2821,6 +2835,7 @@ static int rt5640_suspend(struct snd_soc_component *component)
static int rt5640_resume(struct snd_soc_component *component)
{
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+ int ret;
if (rt5640->ldo1_en) {
gpiod_set_value_cansleep(rt5640->ldo1_en, 1);
@@ -2828,7 +2843,16 @@ static int rt5640_resume(struct snd_soc_component *component)
}
regcache_cache_only(rt5640->regmap, false);
- regcache_sync(rt5640->regmap);
+ ret = regcache_sync(rt5640->regmap);
+ if (ret) {
+ rt5640->resume_failed = true;
+ regcache_cache_only(rt5640->regmap, true);
+ regcache_mark_dirty(rt5640->regmap);
+ if (rt5640->ldo1_en)
+ gpiod_set_value_cansleep(rt5640->ldo1_en, 0);
+ return ret;
+ }
+ rt5640->resume_failed = false;
if (rt5640->jack) {
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
@@ -2857,7 +2881,14 @@ static int rt5640_resume(struct snd_soc_component *component)
}
}
- enable_irq(rt5640->irq);
+ if (rt5640->suspend_irq_disabled) {
+ rt5640->suspend_irq_disabled = false;
+ enable_irq(rt5640->irq);
+ }
+ if (rt5640->suspend_jd_gpio_irq_disabled) {
+ rt5640->suspend_jd_gpio_irq_disabled = false;
+ enable_irq(rt5640->jd_gpio_irq);
+ }
queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0);
}
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 8a12cee76bdc65b73c3a1c4b6ef53e0dc3bdb8b9..eceff517d44eb1b0d881c5a07c825cf4be7d714b 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -2154,7 +2154,10 @@ struct rt5640_priv {
bool hp_mute;
bool asrc_en;
bool irq_requested;
+ bool suspend_irq_disabled;
bool jd_gpio_irq_requested;
+ bool suspend_jd_gpio_irq_disabled;
+ bool resume_failed;
/* Jack and button detect data */
bool ovcd_irq_enabled;
base-commit: 8ef28aef33f2d5da6959ad6b579ec3cfccc009f6
next prev parent reply other threads:[~2026-10-14 3:25 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-14 3:24 [PATCH v2 0/9] ASoC: stop dependent resume work after restore failures Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 1/9] ASoC: nau8821: restore safe state after resume errors Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 2/9] ASoC: nau8824: " Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 3/9] ASoC: nau8825: " Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 4/9] ASoC: rt5663: " Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 5/9] ASoC: rt5682s: " Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 6/9] ASoC: rt5682: " Pengpeng Hou
2026-10-14 3:24 ` [PATCH v2 7/9] ASoC: wm8978: " Pengpeng Hou
2026-10-14 9:20 ` Charles Keepax
2026-10-14 3:24 ` Pengpeng Hou [this message]
2026-10-14 3:24 ` [PATCH v2 9/9] ASoC: rt5677: " Pengpeng Hou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261014032452.13456-9-hppiscas@163.com \
--to=hppiscas@163.com \
--cc=bardliao@realtek.com \
--cc=broonie@kernel.org \
--cc=ckeepax@opensource.cirrus.com \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=oder_chiou@realtek.com \
--cc=perex@perex.cz \
--cc=swarren@nvidia.com \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®