[SRU][R][PATCH v7 3/3] UBUNTU: SAUCE: ASoC: SDCA: Do not leak or reuse jack state across a card rebind
Chris Chiu
chris.chiu at canonical.com
Tue Sep 22 04:41:15 UTC 2026
BugLink: https://bugs.launchpad.net/bugs/2163215
The jack state is allocated with devm against the codec device, but it
is populated with pointers owned by the soundcard: the "Selected Mode"
kcontrol and the ASoC jack. The codec device outlives the card, so a
card teardown and rebind - a module reload, or a suspend/resume that
tears the card down - leaves both pointers dangling in a structure that
is still reachable.
sdca_irq_cleanup() frees the interrupt and its name but leaves
interrupt->priv alone, and sdca_irq_populate() then calls
sdca_jack_alloc_state() again on the next probe. That hides the stale
pointers behind a fresh allocation, at the cost of leaking the previous
one on every rebind, since devm only unwinds when the codec device
itself goes away.
Clear the card-owned pointers where the card goes away, in
sdca_irq_cleanup(), and reuse the existing allocation on re-probe. The
state is no longer stale between unbind and rebind, and a rebind no
longer costs an allocation.
Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
Tested-by: Chris Chiu <chris.chiu at canonical.com>
---
include/sound/sdca_jack.h | 1 +
sound/soc/sdca/sdca_interrupts.c | 23 ++++++++++++++++++++---
sound/soc/sdca/sdca_jack.c | 21 +++++++++++++++++++++
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h
index 623116460938..6054f8a1d311 100644
--- a/include/sound/sdca_jack.h
+++ b/include/sound/sdca_jack.h
@@ -25,6 +25,7 @@ struct jack_state {
};
int sdca_jack_alloc_state(struct sdca_interrupt *interrupt);
+void sdca_jack_reset_state(struct sdca_interrupt *interrupt);
int sdca_jack_process(struct sdca_interrupt *interrupt);
int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack);
void sdca_jack_fixup_controls(struct sdca_interrupt_info *info);
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 5cdabf8ae9da..0f6d3412c00a 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -519,9 +519,17 @@ int sdca_irq_populate(struct sdca_function_data *function,
handler = function_status_handler;
break;
case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
- ret = sdca_jack_alloc_state(interrupt);
- if (ret)
- return ret;
+ /*
+ * The state outlives the card, so on a rebind
+ * reuse the one already allocated against this
+ * device rather than leaking it and starting a
+ * new one.
+ */
+ if (!interrupt->priv) {
+ ret = sdca_jack_alloc_state(interrupt);
+ if (ret)
+ return ret;
+ }
handler = detected_mode_handler;
break;
@@ -577,6 +585,15 @@ void sdca_irq_cleanup(struct device *dev,
sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt);
+ switch (SDCA_CTL_TYPE(interrupt->entity->type,
+ interrupt->control->sel)) {
+ case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
+ sdca_jack_reset_state(interrupt);
+ break;
+ default:
+ break;
+ }
+
kfree(interrupt->name);
}
}
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 98374ae2aa88..63a91751d89c 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -145,6 +145,27 @@ int sdca_jack_alloc_state(struct sdca_interrupt *interrupt)
}
EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA");
+/**
+ * sdca_jack_reset_state - drop state belonging to a card that is going away
+ * @interrupt: SDCA interrupt structure.
+ *
+ * The kcontrol and the ASoC jack are owned by the soundcard, not by the
+ * codec device the state is allocated against, so both are dangling once
+ * the card is torn down. Clear them, leaving the allocation in place to
+ * be reused if the card is bound again.
+ */
+void sdca_jack_reset_state(struct sdca_interrupt *interrupt)
+{
+ struct jack_state *jack_state = interrupt->priv;
+
+ if (!jack_state)
+ return;
+
+ jack_state->kctl = NULL;
+ jack_state->jack = NULL;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_jack_reset_state, "SND_SOC_SDCA");
+
/**
* sdca_jack_set_jack - attach an ASoC jack to SDCA
* @info: SDCA interrupt information.
--
2.43.0
More information about the kernel-team
mailing list