[PATCH 1/4] ASoC: rt5668: cancel pending delayed works on component remove
From: Tristan Madani
Date: Mon Oct 26 2026 - 07:29:07 EST
From: Tristan Madani <tristan@xxxxxxxxxxxxxxxxxxx>
The rt5668 codec initializes two delayed works (jack_detect_work,
jd_check_work) but neither is cancelled during component removal.
If the card is unbound while these works are pending, they fire on
freed resources when snd_soc_jack_report() dereferences the cleared
card pointer.
Track successful IRQ acquisition with a flag so that disable_irq()
only quiesces a line this driver actually owns. On component remove,
disable the IRQ to stop the handler from rescheduling work, then
drain both delayed works before resetting the codec. On the next
component probe (card rebind), re-enable the IRQ to restore jack
detection.
Fixes: d59fb2856223 ("ASoC: rt5668: add rt5668B codec driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Tristan Madani <tristan@xxxxxxxxxxxxxxxxxxx>
---
sound/soc/codecs/rt5668.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c
index 4154bad276101..01b14c62fde7f 100644
--- a/sound/soc/codecs/rt5668.c
+++ b/sound/soc/codecs/rt5668.c
@@ -62,6 +62,8 @@ struct rt5668_priv {
int pll_out;
int jack_type;
+ bool irq_acquired;
+ bool irq_disabled;
};
static const struct reg_default rt5668_reg[] = {
@@ -2213,6 +2215,12 @@ static int rt5668_set_bias_level(struct snd_soc_component *component,
static int rt5668_probe(struct snd_soc_component *component)
{
struct rt5668_priv *rt5668 = snd_soc_component_get_drvdata(component);
+ struct i2c_client *i2c = to_i2c_client(component->dev);
+
+ if (rt5668->irq_disabled) {
+ enable_irq(i2c->irq);
+ rt5668->irq_disabled = false;
+ }
rt5668->component = component;
@@ -2222,7 +2230,15 @@ static int rt5668_probe(struct snd_soc_component *component)
static void rt5668_remove(struct snd_soc_component *component)
{
struct rt5668_priv *rt5668 = snd_soc_component_get_drvdata(component);
+ struct i2c_client *i2c = to_i2c_client(component->dev);
+ if (rt5668->irq_acquired) {
+ disable_irq(i2c->irq);
+ rt5668->irq_disabled = true;
+ }
+
+ cancel_delayed_work_sync(&rt5668->jack_detect_work);
+ cancel_delayed_work_sync(&rt5668->jd_check_work);
rt5668_reset(rt5668->regmap);
}
@@ -2531,7 +2547,9 @@ static int rt5668_i2c_probe(struct i2c_client *i2c)
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
rt5668_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5668", rt5668);
- if (ret)
+ if (!ret)
+ rt5668->irq_acquired = true;
+ else
dev_err(&i2c->dev, "Failed to request IRQ: %d\n", ret);
}
--
2.47.3