* [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep leaks on card re-bind
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
@ 2026-09-13 10:15 ` Chancel Liu
2026-09-14 10:56 ` Charles Keepax
2026-09-13 10:15 ` [PATCH 2/6] ASoC: wm8995: Register regulator notifiers from the bus probe Chancel Liu
` (5 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Chancel Liu @ 2026-09-13 10:15 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald
Cc: Charles Keepax, patches, linux-sound, linux-kernel
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
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep leaks on card re-bind
2026-09-13 10:15 ` [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep " Chancel Liu
@ 2026-09-14 10:56 ` Charles Keepax
0 siblings, 0 replies; 12+ messages in thread
From: Charles Keepax @ 2026-09-14 10:56 UTC (permalink / raw)
To: Chancel Liu
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald, patches, linux-sound, linux-kernel
On Sun, Sep 13, 2026 at 07:15:26PM +0900, Chancel Liu wrote:
> 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>
> ---
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Thanks,
Charles
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/6] ASoC: wm8995: Register regulator notifiers from the bus probe
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
2026-09-13 10:15 ` [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep " Chancel Liu
@ 2026-09-13 10:15 ` 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
` (4 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Chancel Liu @ 2026-09-13 10:15 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald
Cc: Charles Keepax, patches, linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
wm8995 requests its regulator supplies and registers the regulator
disable notifiers from the ASoC component probe, but the associated
devres cleanup is tied to the underlying I2C/SPI device.
These resources are only mishandled when the sound card is unregistered
and re-registered while the bus 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 and corrupts the chain.
Move the supply request and notifier registration into a helper,
wm8995_hw_init(), and call it from wm8995_i2c_probe() and
wm8995_spi_probe() so they run once per bus device bind. The regulator
enable and the register accesses that need the component stay in
wm8995_probe().
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/wm8995.c | 41 ++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 799989a5bf0f..35cbd0fb7f1a 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -1993,23 +1993,17 @@ static int wm8995_set_bias_level(struct snd_soc_component *component,
return 0;
}
-static int wm8995_probe(struct snd_soc_component *component)
+static int wm8995_hw_init(struct device *dev, struct wm8995_priv *wm8995)
{
- struct wm8995_priv *wm8995;
- int i;
- int ret;
-
- wm8995 = snd_soc_component_get_drvdata(component);
- wm8995->component = component;
+ int i, ret;
for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++)
wm8995->supplies[i].supply = wm8995_supply_names[i];
- ret = devm_regulator_bulk_get(component->dev,
- ARRAY_SIZE(wm8995->supplies),
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8995->supplies),
wm8995->supplies);
if (ret) {
- dev_err(component->dev, "Failed to request supplies: %d\n", ret);
+ dev_err(dev, "Failed to request supplies: %d\n", ret);
return ret;
}
@@ -2024,16 +2018,27 @@ static int wm8995_probe(struct snd_soc_component *component)
/* This should really be moved into the regulator core */
for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) {
- ret = devm_regulator_register_notifier(
- wm8995->supplies[i].consumer,
- &wm8995->disable_nb[i]);
+ ret = devm_regulator_register_notifier(wm8995->supplies[i].consumer,
+ &wm8995->disable_nb[i]);
if (ret) {
- dev_err(component->dev,
+ dev_err(dev,
"Failed to register regulator notifier: %d\n",
ret);
+ return ret;
}
}
+ return 0;
+}
+
+static int wm8995_probe(struct snd_soc_component *component)
+{
+ struct wm8995_priv *wm8995;
+ int ret;
+
+ wm8995 = snd_soc_component_get_drvdata(component);
+ wm8995->component = component;
+
ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies),
wm8995->supplies);
if (ret) {
@@ -2216,6 +2221,10 @@ static int wm8995_spi_probe(struct spi_device *spi)
return ret;
}
+ ret = wm8995_hw_init(&spi->dev, wm8995);
+ if (ret)
+ return ret;
+
ret = devm_snd_soc_register_component(&spi->dev,
&soc_component_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
@@ -2249,6 +2258,10 @@ static int wm8995_i2c_probe(struct i2c_client *i2c)
return ret;
}
+ ret = wm8995_hw_init(&i2c->dev, wm8995);
+ if (ret)
+ return ret;
+
ret = devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
--
2.50.1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 2/6] ASoC: wm8995: Register regulator notifiers from the bus probe
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
0 siblings, 0 replies; 12+ messages in thread
From: Charles Keepax @ 2026-09-14 12:49 UTC (permalink / raw)
To: Chancel Liu
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald, patches, linux-sound, linux-kernel
On Sun, Sep 13, 2026 at 07:15:27PM +0900, Chancel Liu wrote:
> From: Chancel Liu <chancel.liu@nxp.com>
>
> wm8995 requests its regulator supplies and registers the regulator
> disable notifiers from the ASoC component probe, but the associated
> devres cleanup is tied to the underlying I2C/SPI device.
>
> These resources are only mishandled when the sound card is unregistered
> and re-registered while the bus 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 and corrupts the chain.
>
> Move the supply request and notifier registration into a helper,
> wm8995_hw_init(), and call it from wm8995_i2c_probe() and
> wm8995_spi_probe() so they run once per bus device bind. The regulator
> enable and the register accesses that need the component stay in
> wm8995_probe().
>
> Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
> ---
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Thanks,
Charles
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 3/6] ASoC: tlv320aic31xx: Register regulator notifier from the I2C probe
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
2026-09-13 10:15 ` [PATCH 1/6] ASoC: wm8962: Fix regulator notifier and beep " Chancel Liu
2026-09-13 10:15 ` [PATCH 2/6] ASoC: wm8995: Register regulator notifiers from the bus probe Chancel Liu
@ 2026-09-13 10:15 ` Chancel Liu
2026-09-13 10:15 ` [PATCH 4/6] ASoC: tlv320aic3x: Register regulator notifier from the bus probe Chancel Liu
` (3 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Chancel Liu @ 2026-09-13 10:15 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald
Cc: Charles Keepax, patches, linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
aic31xx registers its regulator disable notifiers from the ASoC
component probe, but the associated devres cleanup is tied to the
underlying I2C device.
The notifiers are only mishandled 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 and corrupts the chain.
Move the notifier registration to aic31xx_i2c_probe() so it runs once
per I2C device bind, right after the supplies are requested there.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/tlv320aic31xx.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 43bcbc5449e1..b0df6e6435e7 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1366,27 +1366,12 @@ static int aic31xx_set_jack(struct snd_soc_component *component,
static int aic31xx_codec_probe(struct snd_soc_component *component)
{
struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
- int i, ret;
+ int ret;
dev_dbg(aic31xx->dev, "## %s\n", __func__);
aic31xx->component = component;
- for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
- aic31xx->disable_nb[i].nb.notifier_call =
- aic31xx_regulator_event;
- aic31xx->disable_nb[i].aic31xx = aic31xx;
- ret = devm_regulator_register_notifier(
- aic31xx->supplies[i].consumer,
- &aic31xx->disable_nb[i].nb);
- if (ret) {
- dev_err(component->dev,
- "Failed to request regulator notifier: %d\n",
- ret);
- return ret;
- }
- }
-
regcache_cache_only(aic31xx->regmap, true);
regcache_mark_dirty(aic31xx->regmap);
@@ -1791,6 +1776,19 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c)
if (ret)
return dev_err_probe(aic31xx->dev, ret, "Failed to request supplies\n");
+ for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
+ aic31xx->disable_nb[i].nb.notifier_call = aic31xx_regulator_event;
+ aic31xx->disable_nb[i].aic31xx = aic31xx;
+ ret = devm_regulator_register_notifier(aic31xx->supplies[i].consumer,
+ &aic31xx->disable_nb[i].nb);
+ if (ret) {
+ dev_err(aic31xx->dev,
+ "Failed to request regulator notifier: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
aic31xx_configure_ocmv(aic31xx);
if (aic31xx->irq > 0) {
--
2.50.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH 4/6] ASoC: tlv320aic3x: Register regulator notifier from the bus probe
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
` (2 preceding siblings ...)
2026-09-13 10:15 ` [PATCH 3/6] ASoC: tlv320aic31xx: Register regulator notifier from the I2C probe Chancel Liu
@ 2026-09-13 10:15 ` Chancel Liu
2026-09-13 10:15 ` [PATCH 5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind Chancel Liu
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Chancel Liu @ 2026-09-13 10:15 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald
Cc: Charles Keepax, patches, linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
aic3x registers its regulator disable notifiers from the ASoC component
probe, but the associated devres cleanup is tied to the underlying bus
device.
The notifiers are only mishandled when the sound card is unregistered
and re-registered while the bus 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 and corrupts the chain.
Move the notifier registration to aic3x_probe(), the shared bus probe
helper called from the I2C and SPI probes, so it runs once per bus
device bind, right after the supplies are requested there.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/tlv320aic3x.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b38393a8130f..405c60ec1448 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1627,24 +1627,9 @@ static int aic3x_init(struct snd_soc_component *component)
static int aic3x_component_probe(struct snd_soc_component *component)
{
struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component);
- int ret, i;
aic3x->component = component;
- for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
- aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
- aic3x->disable_nb[i].aic3x = aic3x;
- ret = devm_regulator_register_notifier(
- aic3x->supplies[i].consumer,
- &aic3x->disable_nb[i].nb);
- if (ret) {
- dev_err(component->dev,
- "Failed to request regulator notifier: %d\n",
- ret);
- return ret;
- }
- }
-
regcache_mark_dirty(aic3x->regmap);
aic3x_init(component);
@@ -1845,6 +1830,19 @@ int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver
if (ret)
return dev_err_probe(dev, ret, "Failed to request supplies\n");
+ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
+ aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
+ aic3x->disable_nb[i].aic3x = aic3x;
+ ret = devm_regulator_register_notifier(aic3x->supplies[i].consumer,
+ &aic3x->disable_nb[i].nb);
+ if (ret) {
+ dev_err(dev,
+ "Failed to request regulator notifier: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
aic3x_configure_ocmv(dev, aic3x);
ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1);
--
2.50.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH 5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
` (3 preceding siblings ...)
2026-09-13 10:15 ` [PATCH 4/6] ASoC: tlv320aic3x: Register regulator notifier from the bus probe Chancel Liu
@ 2026-09-13 10:15 ` Chancel Liu
2026-09-14 12:51 ` Charles Keepax
2026-09-13 10:15 ` [PATCH 6/6] ASoC: cs42l56: " Chancel Liu
2026-09-14 13:58 ` [PATCH 0/6] ASoC: codecs: Fix resource leaks " Mark Brown
6 siblings, 1 reply; 12+ messages in thread
From: Chancel Liu @ 2026-09-13 10:15 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald
Cc: Charles Keepax, patches, linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
cs42l52 allocates its beep input device with devm_input_allocate_device()
from the ASoC component probe, but the associated devres cleanup is tied
to the underlying I2C device, while cs42l52_free_beep() on the component
remove path only clears the cs42l52->beep pointer.
The input device is 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 allocates and registers a new input
device every time, leaking the previous one and its sysfs/input node.
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 cs42l52_free_beep().
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/cs42l52.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 9d6bcfbbf0b2..0cced269f300 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -1000,7 +1000,7 @@ static void cs42l52_init_beep(struct snd_soc_component *component)
struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component);
int ret;
- cs42l52->beep = devm_input_allocate_device(component->dev);
+ cs42l52->beep = input_allocate_device();
if (!cs42l52->beep) {
dev_err(component->dev, "Failed to allocate beep device\n");
return;
@@ -1021,8 +1021,10 @@ static void cs42l52_init_beep(struct snd_soc_component *component)
ret = input_register_device(cs42l52->beep);
if (ret != 0) {
+ input_free_device(cs42l52->beep);
cs42l52->beep = NULL;
dev_err(component->dev, "Failed to register beep device\n");
+ return;
}
ret = device_create_file(component->dev, &dev_attr_beep);
@@ -1038,7 +1040,10 @@ static void cs42l52_free_beep(struct snd_soc_component *component)
device_remove_file(component->dev, &dev_attr_beep);
cancel_work_sync(&cs42l52->beep_work);
- cs42l52->beep = NULL;
+ if (cs42l52->beep) {
+ input_unregister_device(cs42l52->beep);
+ cs42l52->beep = NULL;
+ }
snd_soc_component_update_bits(component, CS42L52_BEEP_TONE_CTL,
CS42L52_BEEP_EN_MASK, 0);
--
2.50.1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind
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
0 siblings, 0 replies; 12+ messages in thread
From: Charles Keepax @ 2026-09-14 12:51 UTC (permalink / raw)
To: Chancel Liu
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald, patches, linux-sound, linux-kernel
On Sun, Sep 13, 2026 at 07:15:30PM +0900, Chancel Liu wrote:
> From: Chancel Liu <chancel.liu@nxp.com>
>
> cs42l52 allocates its beep input device with devm_input_allocate_device()
> from the ASoC component probe, but the associated devres cleanup is tied
> to the underlying I2C device, while cs42l52_free_beep() on the component
> remove path only clears the cs42l52->beep pointer.
>
> The input device is 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 allocates and registers a new input
> device every time, leaking the previous one and its sysfs/input node.
>
> 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 cs42l52_free_beep().
>
> Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
> ---
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Thanks,
Charles
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 6/6] ASoC: cs42l56: Fix beep input device leak on card re-bind
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
` (4 preceding siblings ...)
2026-09-13 10:15 ` [PATCH 5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind Chancel Liu
@ 2026-09-13 10:15 ` Chancel Liu
2026-09-14 12:52 ` Charles Keepax
2026-09-14 13:58 ` [PATCH 0/6] ASoC: codecs: Fix resource leaks " Mark Brown
6 siblings, 1 reply; 12+ messages in thread
From: Chancel Liu @ 2026-09-13 10:15 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald
Cc: Charles Keepax, patches, linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
cs42l56 allocates its beep input device with devm_input_allocate_device()
from the ASoC component probe, but the associated devres cleanup is tied
to the underlying I2C device, while cs42l56_free_beep() on the component
remove path only clears the cs42l56->beep pointer.
The input device is 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 allocates and registers a new input
device every time, leaking the previous one and its sysfs/input node.
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 cs42l56_free_beep().
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/cs42l56.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index 4d9a22a1029c..37df94fbc887 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -1077,7 +1077,7 @@ static void cs42l56_init_beep(struct snd_soc_component *component)
struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component);
int ret;
- cs42l56->beep = devm_input_allocate_device(component->dev);
+ cs42l56->beep = input_allocate_device();
if (!cs42l56->beep) {
dev_err(component->dev, "Failed to allocate beep device\n");
return;
@@ -1098,8 +1098,10 @@ static void cs42l56_init_beep(struct snd_soc_component *component)
ret = input_register_device(cs42l56->beep);
if (ret != 0) {
+ input_free_device(cs42l56->beep);
cs42l56->beep = NULL;
dev_err(component->dev, "Failed to register beep device\n");
+ return;
}
ret = device_create_file(component->dev, &dev_attr_beep);
@@ -1115,7 +1117,10 @@ static void cs42l56_free_beep(struct snd_soc_component *component)
device_remove_file(component->dev, &dev_attr_beep);
cancel_work_sync(&cs42l56->beep_work);
- cs42l56->beep = NULL;
+ if (cs42l56->beep) {
+ input_unregister_device(cs42l56->beep);
+ cs42l56->beep = NULL;
+ }
snd_soc_component_update_bits(component, CS42L56_BEEP_TONE_CFG,
CS42L56_BEEP_EN_MASK, 0);
--
2.50.1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 6/6] ASoC: cs42l56: Fix beep input device leak on card re-bind
2026-09-13 10:15 ` [PATCH 6/6] ASoC: cs42l56: " Chancel Liu
@ 2026-09-14 12:52 ` Charles Keepax
0 siblings, 0 replies; 12+ messages in thread
From: Charles Keepax @ 2026-09-14 12:52 UTC (permalink / raw)
To: Chancel Liu
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, David Rhodes,
Richard Fitzgerald, patches, linux-sound, linux-kernel
On Sun, Sep 13, 2026 at 07:15:31PM +0900, Chancel Liu wrote:
> From: Chancel Liu <chancel.liu@nxp.com>
>
> cs42l56 allocates its beep input device with devm_input_allocate_device()
> from the ASoC component probe, but the associated devres cleanup is tied
> to the underlying I2C device, while cs42l56_free_beep() on the component
> remove path only clears the cs42l56->beep pointer.
>
> The input device is 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 allocates and registers a new input
> device every time, leaking the previous one and its sysfs/input node.
>
> 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 cs42l56_free_beep().
>
> Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
> ---
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Thanks,
Charles
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind
2026-09-13 10:15 [PATCH 0/6] ASoC: codecs: Fix resource leaks on card re-bind Chancel Liu
` (5 preceding siblings ...)
2026-09-13 10:15 ` [PATCH 6/6] ASoC: cs42l56: " Chancel Liu
@ 2026-09-14 13:58 ` Mark Brown
6 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2026-09-14 13:58 UTC (permalink / raw)
To: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Sen Wang, David Rhodes, Richard Fitzgerald,
Chancel Liu
Cc: Charles Keepax, patches, linux-sound, linux-kernel
On Sun, 13 Sep 2026 19:15:25 +0900, Chancel Liu wrote:
> ASoC: codecs: Fix resource leaks on card re-bind
>
> From: Chancel Liu <chancel.liu@nxp.com>
>
> Several ASoC codec drivers set up per-device resources from their ASoC
> component probe, but the associated cleanup is tied to the underlying bus
> (I2C/SPI) device rather than being balanced per component probe. This is
> fine for a plain probe/remove, but it breaks when the sound card is
> unregistered and re-registered while the bus device stays bound (a card
> re-bind): the component probe runs again while the previous bus-level
> resources are still live.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.4
Thanks!
[1/6] ASoC: wm8962: Fix regulator notifier and beep leaks on card re-bind
https://git.kernel.org/broonie/sound/c/b9e5343ba72a
[2/6] ASoC: wm8995: Register regulator notifiers from the bus probe
https://git.kernel.org/broonie/sound/c/644914663c9f
[3/6] ASoC: tlv320aic31xx: Register regulator notifier from the I2C probe
https://git.kernel.org/broonie/sound/c/10e2ccaae497
[4/6] ASoC: tlv320aic3x: Register regulator notifier from the bus probe
https://git.kernel.org/broonie/sound/c/3efb5b99f642
[5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind
https://git.kernel.org/broonie/sound/c/115a5655bcbb
[6/6] ASoC: cs42l56: Fix beep input device leak on card re-bind
https://git.kernel.org/broonie/sound/c/c5907dcc13ad
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 12+ messages in thread