[SRU][R][PATCH v5 8/8] ASoC: SDCA: Move kcontrol search out of IRQ
Andrei Gherzan
andrei.gherzan at canonical.com
Fri Sep 11 12:07:19 UTC 2026
On 26/09/11 04:44PM, Chris Chiu via kernel-team wrote:
> From: Charles Keepax <ckeepax at opensource.cirrus.com>
>
> BugLink: https://bugs.launchpad.net/bugs/2163215
>
> Now that the IRQs are always registered after all the ALSA
> controls are created it is possible to search for the control
> at the point the IRQ is requested. Move the control search out
> of the IRQ handler and do it at IRQ request time.
>
> This also fixes a potential issue when the card was torn down
> and reprobed without destroying the codec device, the kctl
> pointer stored by the IRQ handler would not be updated to the
> new control on the second probe.
>
> Signed-off-by: Charles Keepax <ckeepax at opensource.cirrus.com>
> Link: https://patch.msgid.link/20260721143636.361814-8-ckeepax@opensource.cirrus.com
> Signed-off-by: Mark Brown <broonie at kernel.org>
> (backported from commit bf1b7821f85383a8804441f8fd5165be148f3ec8)
> [ChrisChiu: Remove duplicated struct members in struct jack_state.
> Remove dead helper 'type_get_mask' from this series and implement
> local mapping in sdca_jack_report(). Place sdca_jack_free_state/init
> before sdca_jack_set_jack and remove unused locals]
> Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
> ---
> v5 change:
> - Remove dead helper 'type_get_mask' from this series
> - lace sdca_jack_free_state/init before sdca_jack_set_jack and remove unused locals
>
> include/sound/sdca_jack.h | 3 ++
> sound/soc/sdca/sdca_interrupts.c | 12 ++++++
> sound/soc/sdca/sdca_jack.c | 66 ++++++++++++++++++++------------
> 3 files changed, 56 insertions(+), 25 deletions(-)
>
> diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h
> index 8624c51eea26..a55a1bad1904 100644
> --- a/include/sound/sdca_jack.h
> +++ b/include/sound/sdca_jack.h
> @@ -22,9 +22,12 @@ struct snd_soc_jack;
> struct jack_state {
> struct snd_kcontrol *kctl;
> struct snd_soc_jack *jack;
> + /* legacy mask field; wiring of proper masks (cb3c257e0824) is out of scope */
> + unsigned int mask;
> };
>
> int sdca_jack_alloc_state(struct sdca_interrupt *interrupt);
> +int sdca_jack_init_state(struct sdca_interrupt *interrupt);
> void sdca_jack_free_state(struct sdca_interrupt *interrupt);
>
> int sdca_jack_process(struct sdca_interrupt *interrupt);
> diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
> index 79a17d827f99..15da7c2aea50 100644
> --- a/sound/soc/sdca/sdca_interrupts.c
> +++ b/sound/soc/sdca/sdca_interrupts.c
> @@ -512,6 +512,8 @@ int sdca_irq_populate(struct sdca_function_data *function,
>
> for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
> struct sdca_interrupt *interrupt = &info->irqs[i];
> + struct sdca_control *control = interrupt->control;
> + struct sdca_entity *entity = interrupt->entity;
> int irq;
>
> if (interrupt->function != function || interrupt->irq)
> @@ -519,6 +521,16 @@ int sdca_irq_populate(struct sdca_function_data *function,
>
> interrupt->component = component;
>
> + switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
> + case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
> + ret = sdca_jack_init_state(interrupt);
> + if (ret)
> + return ret;
> + break;
> + default:
> + break;
> + }
> +
> irq = interrupt->control->interrupt_position;
> ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
> interrupt->handler, interrupt);
> diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
> index 2a77e28ba43e..c6b9cb3fcc2f 100644
> --- a/sound/soc/sdca/sdca_jack.c
> +++ b/sound/soc/sdca/sdca_jack.c
> @@ -47,23 +47,6 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
>
> guard(rwsem_write)(rwsem);
>
> - if (!kctl) {
> - const char *name __free(kfree) = kasprintf(GFP_KERNEL, "%s %s",
> - interrupt->entity->label,
> - SDCA_CTL_SELECTED_MODE_NAME);
> -
> - if (!name)
> - return -ENOMEM;
> -
> - kctl = snd_soc_component_get_kcontrol(component, name);
> - if (!kctl) {
> - dev_err(dev, "control not found: %s\n", name);
> - return -ENODEV;
> - }
> -
> - state->kctl = kctl;
> - }
> -
> reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id,
> interrupt->control->sel, 0);
>
> @@ -143,16 +126,36 @@ EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA");
> * @interrupt: SDCA interrupt structure.
> */
> void sdca_jack_free_state(struct sdca_interrupt *interrupt)
This reverts the implementation of patch 3 back to the uptream's approach. It
introduces a transient defect - between 3 and 8 there is a real leak.
> +{
> + kfree(interrupt->priv);
> +}
> +EXPORT_SYMBOL_NS_GPL(sdca_jack_free_state, "SND_SOC_SDCA");
> +
> +/**
> + * sdca_jack_init_state - Initialise transient state for a jack interrupt
> + * @interrupt: SDCA interrupt structure.
> + *
> + * Return: Zero on success or a negative error code.
> + */
> +int sdca_jack_init_state(struct sdca_interrupt *interrupt)
> {
> struct jack_state *jack_state = interrupt->priv;
> + const char *name __free(kfree) = kasprintf(GFP_KERNEL, "%s %s",
> + interrupt->entity->label,
> + SDCA_CTL_SELECTED_MODE_NAME);
>
> - if (!jack_state)
> - return;
> + if (!name)
> + return -ENOMEM;
> +
> + jack_state->kctl = snd_soc_component_get_kcontrol(interrupt->component, name);
> + if (!jack_state->kctl) {
> + dev_err(interrupt->dev, "control not found: %s\n", name);
> + return -ENODEV;
> + }
>
> - /* devm allocation: just clear the pointer */
> - interrupt->priv = NULL;
> + return 0;
> }
> -EXPORT_SYMBOL_NS_GPL(sdca_jack_free_state, "SND_SOC_SDCA");
> +EXPORT_SYMBOL_NS_GPL(sdca_jack_init_state, "SND_SOC_SDCA");
>
>
> /**
> @@ -164,7 +167,8 @@ EXPORT_SYMBOL_NS_GPL(sdca_jack_free_state, "SND_SOC_SDCA");
> */
> int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack)
> {
> - int i, ret;
> + int i, j;
> + int ret;
>
> guard(mutex)(&info->irq_lock);
>
> @@ -172,6 +176,7 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
> struct sdca_interrupt *interrupt = &info->irqs[i];
> struct sdca_control *control = interrupt->control;
> struct sdca_entity *entity = interrupt->entity;
> + struct sdca_control_range *range;
> struct jack_state *jack_state;
>
> if (!interrupt->dev)
> @@ -179,7 +184,14 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
>
> switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
> case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
> + /* Keep scope small: do not backport cb3c257e0824 which wires
> + * type_get_mask into jack_state->mask. Use legacy behaviour
> + * and report a full mask (0xFFFF) here.
> + */
> jack_state = interrupt->priv;
> +
> + jack_state->mask = 0xFFFF;
> +
> jack_state->jack = jack;
>
> /* Report initial state in case IRQ was already handled */
> @@ -201,7 +213,6 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
> struct jack_state *jack_state = interrupt->priv;
> struct sdca_control_range *range;
> enum sdca_terminal_type type;
> - unsigned int report = 0;
> unsigned int reg, val;
> int ret;
>
> @@ -223,6 +234,11 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
> type = sdca_range_search(range, SDCA_SELECTED_MODE_INDEX,
> val, SDCA_SELECTED_MODE_TERM_TYPE);
>
> + /* Map the terminal type to a jack report without relying on the
> + * helper that was introduced upstream in cb3c257e0824 (out of scope).
> + */
> + unsigned int report = 0;
> +
> switch (type) {
> case SDCA_TERM_TYPE_LINEIN_STEREO:
> case SDCA_TERM_TYPE_LINEIN_FRONT_LR:
> @@ -251,7 +267,7 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
> break;
> }
>
> - snd_soc_jack_report(jack_state->jack, report, 0xFFFF);
> + snd_soc_jack_report(jack_state->jack, report, jack_state->mask);
>
> return 0;
> }
> --
> 2.43.0
>
>
> --
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
--
Andrei Gherzan
gpg: rsa4096/D4D94F67AD0E9640
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20260911/232a1352/attachment.sig>
More information about the kernel-team
mailing list