From: Chancel Liu <chancel.liu@oss.nxp.com>
To: Liam Girdwood <lgirdwood@gmail.com>,
Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>,
Takashi Iwai <tiwai@suse.com>,
Shenghao Ding <shenghao-ding@ti.com>, Kevin Lu <kevin-lu@ti.com>,
Baojun Xu <baojun.xu@ti.com>, Sen Wang <sen@ti.com>,
David Rhodes <david.rhodes@cirrus.com>,
Richard Fitzgerald <rf@opensource.cirrus.com>
Cc: Charles Keepax <ckeepax@opensource.cirrus.com>,
patches@opensource.cirrus.com, linux-sound@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep leaks on card re-bind
Date: Sun, 13 Sep 2026 19:15:26 +0900 [thread overview]
Message-ID: <20260913101531.2787654-2-chancel.liu@oss.nxp.com> (raw)
In-Reply-To: <20260913101531.2787654-1-chancel.liu@oss.nxp.com>
From: Chancel Liu <chancel.liu@nxp.com>
wm8962 registers its regulator disable notifiers and allocates its beep
input device from the ASoC component probe, but the associated devres
cleanup is tied to the underlying I2C device.
These resources are only leaked when the sound card is unregistered and
re-registered while the I2C device stays bound. On that path the
component probe runs again and:
- re-registers the same notifier_block on the still-registered
regulator notifier chain, which triggers
notifier callback wm8962_regulator_event_N already registered
WARNING: ... at kernel/notifier.c:23 notifier_chain_register
and corrupts the chain.
- allocates and registers a new beep input device every time while
wm8962_free_beep() only clears the pointer, leaking the previous
input device and its sysfs/input node.
Fix both:
- Move the regulator notifier registration to wm8962_i2c_probe() so it
runs once per I2C device bind.
- Allocate the beep device with input_allocate_device() and pair it
with the component lifecycle: input_free_device() on registration
failure and input_unregister_device() in wm8962_free_beep().
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/wm8962.c | 52 +++++++++++++++++++++------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index af4716051220..ae6cc9c72439 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3355,7 +3355,7 @@ static void wm8962_init_beep(struct snd_soc_component *component)
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int ret;
- wm8962->beep = devm_input_allocate_device(component->dev);
+ wm8962->beep = input_allocate_device();
if (!wm8962->beep) {
dev_err(component->dev, "Failed to allocate beep device\n");
return;
@@ -3376,8 +3376,10 @@ static void wm8962_init_beep(struct snd_soc_component *component)
ret = input_register_device(wm8962->beep);
if (ret != 0) {
+ input_free_device(wm8962->beep);
wm8962->beep = NULL;
dev_err(component->dev, "Failed to register beep device\n");
+ return;
}
ret = device_create_file(component->dev, &dev_attr_beep);
@@ -3393,7 +3395,10 @@ static void wm8962_free_beep(struct snd_soc_component *component)
device_remove_file(component->dev, &dev_attr_beep);
cancel_work_sync(&wm8962->beep_work);
- wm8962->beep = NULL;
+ if (wm8962->beep) {
+ input_unregister_device(wm8962->beep);
+ wm8962->beep = NULL;
+ }
snd_soc_component_update_bits(component, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0);
}
@@ -3525,34 +3530,12 @@ static void wm8962_free_gpio(struct snd_soc_component *component)
static int wm8962_probe(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
- int ret;
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int i;
bool dmicclk, dmicdat;
wm8962->component = component;
- wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
- wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1;
- wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2;
- wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3;
- wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4;
- wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5;
- wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6;
- wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7;
-
- /* This should really be moved into the regulator core */
- for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) {
- ret = devm_regulator_register_notifier(
- wm8962->supplies[i].consumer,
- &wm8962->disable_nb[i]);
- if (ret != 0) {
- dev_err(component->dev,
- "Failed to register regulator notifier: %d\n",
- ret);
- }
- }
-
wm8962_add_widgets(component);
/* Save boards having to disable DMIC when not in use */
@@ -3742,6 +3725,27 @@ static int wm8962_i2c_probe(struct i2c_client *i2c)
regcache_cache_bypass(wm8962->regmap, false);
+ wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
+ wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1;
+ wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2;
+ wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3;
+ wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4;
+ wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5;
+ wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6;
+ wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7;
+
+ /* This should really be moved into the regulator core */
+ for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) {
+ ret = devm_regulator_register_notifier(wm8962->supplies[i].consumer,
+ &wm8962->disable_nb[i]);
+ if (ret != 0) {
+ dev_err(&i2c->dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ goto err_enable;
+ }
+ }
+
ret = wm8962_reset(wm8962);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
--
2.50.1
next prev parent reply other threads:[~2026-09-13 10:15 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource " Chancel Liu
2026-09-13 10:15 ` Chancel Liu [this message]
2026-09-14 10:56 ` [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep " Charles Keepax
2026-09-13 10:15 ` [PATCH 2/6] ASoC: wm8995: Register regulator notifiers from the bus probe Chancel Liu
2026-09-14 12:49 ` Charles Keepax
2026-09-13 10:15 ` [PATCH 3/6] ASoC: tlv320aic31xx: Register regulator notifier from the I2C probe Chancel Liu
2026-09-13 10:15 ` [PATCH 4/6] ASoC: tlv320aic3x: Register regulator notifier from the bus probe Chancel Liu
2026-09-13 10:15 ` [PATCH 5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind Chancel Liu
2026-09-14 12:51 ` Charles Keepax
2026-09-13 10:15 ` [PATCH 6/6] ASoC: cs42l56: " Chancel Liu
2026-09-14 12:52 ` Charles Keepax
2026-09-14 13:58 ` [PATCH 0/6] ASoC: codecs: Fix resource leaks " Mark Brown
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=20260913101531.2787654-2-chancel.liu@oss.nxp.com \
--to=chancel.liu@oss.nxp.com \
--cc=baojun.xu@ti.com \
--cc=broonie@kernel.org \
--cc=ckeepax@opensource.cirrus.com \
--cc=david.rhodes@cirrus.com \
--cc=kevin-lu@ti.com \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
--cc=perex@perex.cz \
--cc=rf@opensource.cirrus.com \
--cc=sen@ti.com \
--cc=shenghao-ding@ti.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®