[PATCH 5/6] ASoC: cs42l52: Fix beep input device leak on card re-bind

From: Chancel Liu

Date: Sun Sep 13 2026 - 06:19:53 EST


From: Chancel Liu <chancel.liu@xxxxxxx>

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@xxxxxxx>
---
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