From nobody Sat Jun 13 03:33:18 2026 Received: from mail-dy1-f175.google.com (mail-dy1-f175.google.com [74.125.82.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 020961CD2C for ; Mon, 11 May 2026 04:29:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778473794; cv=none; b=FZVtVl9lyAMgMl/twV4WgRQQ5/KpDwtThEffYJFbBYpDzuvBO/6aPokp1/dzNeTPFlcOXgOnzUuuza00zpxbcnE1u1fqoyco01YJ2rOimQIblw6eyqxnewAcL60H7sX70sKZbF/1tcYJWkiB5eF7bgX8wp4P8jmM8d8SpwKp3G0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778473794; c=relaxed/simple; bh=Fs0OJQxWXkrUkceQIIh8xUwlumLQ4eJxzykdIOR4reI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=lhdBdeUuIc5d2MXr5ASo8d8dpHjnw+do/ZUjGBTOt/B6hX6uJsaw22TzrRa4B/3zfe+lRxax6CP6xb8OMpaHRHQEqL6QYdz8+riSqloPOzpiY49QWGJGOKK+jJBodDKkxV/S/Hn8tlXUCou1/soxOUxUagZe8KLqD+ltqtsnuPM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Lk3aR6Ju; arc=none smtp.client-ip=74.125.82.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Lk3aR6Ju" Received: by mail-dy1-f175.google.com with SMTP id 5a478bee46e88-2ef8d6ba48bso2233463eec.1 for ; Sun, 10 May 2026 21:29:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778473792; x=1779078592; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=3Nn7+K5hKPTTZ9BGRsS3kwvWBcEqqW1Azh+i+IcZJ/Q=; b=Lk3aR6Ju/6g1Psr6gki748DjPaZiAMV7WJEw7kWHjkimwtOuqyI/G67S0lRUfQkhLm 4oyOhrBDMugogjrQs5gtPbKQEKzN9AYn5pr2JiUGggVGCRexKho5O3waSElRPxvPNWkn nIOTBvKGbjFnztV1a1w/N+ZF2QtIRVE4gpfbqzZimTbYhPvzUDEGeViGzom7W3jDf77/ 0KHh+C0IDEI7ze7Qd9px7quTQbm4sSJ4NqmUZlaKFs3GhpB+c6N4sUJeLFqWcexCEHhk gIhLKErOvhgsQB/LCz4mOyb3JPh4fi4yV4zUsoFzZOqtDSmdaowaGfH9yeyC/4hTI0cW 0OFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778473792; x=1779078592; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=3Nn7+K5hKPTTZ9BGRsS3kwvWBcEqqW1Azh+i+IcZJ/Q=; b=Sqb3Qkku0F7+UjDvkHp4Ksy1I4jY+xPtsPIlYjbMPUWeYdXU0jzE8thdVOfV1+S21e Fb2l1P2GFhM4nlsoHwsrnNqbJfhpHlGZCZ9CBz8nM9YNczymlZTeHJZHCmjSuLf+PsHO toSVcKNU/LPmOTzPWW7q1cdrkhhjnSRloMhy+r+GtqQdZkYm8jO8tDvlbgylRm8IjTHG 5NGVTfwSLj1DphqMMK+El8x2NtYHOl9MSXUqwyJqIxzgez+HGC7ImcKvHgftIBddpTIv DUrKZZI6h1j/B8/BqeTF75LPBZ92QWhXhr+sp1cZO2Xrc1K0TClT0kVoH9u9HqFWIhYy 90yw== X-Forwarded-Encrypted: i=1; AFNElJ/mu5a4yo78GAnuOWeL/0qy3jM/LIDVQ77ak/gB/H7KankRFYK6Iii69wXRuGD/tJaS7rJSKsa2hjNNGH8=@vger.kernel.org X-Gm-Message-State: AOJu0Yx0qq4Fy3BRFuM9ap5vpvxk8tKJgYOyJdDArdpGu/prE7Sk4E/H DZ/vj3Tn/d+5h/L8AT6r61wsz97WCN01A4CSk1wi3/uEsY6VWv7X7E6k X-Gm-Gg: Acq92OHJ/ertgF0cm1TjFB/sgaP/UwZdkNoT6UDkploCpWH2AgyZvjY58osUvtx56TX vyb2IVDFPr3cuyfszGYX678v/Htlf18+GLz4KFLek3gAwBUNe0gZmmuipw+GwQcOOJycdGpKpn6 DInrKzjgB4dZrrWfewrC468B7ysE6gj8L6v4gfO8rGGuSTRbaO9/xd6pT4tuLwfxjNokO5avrc6 9V9ylimRJ2yqnLF7X6fKRy2Aj6cI4g8xMy8Q4i9YSHz2S997DCkdUt8vT453t9m1pdns1wvN0NM av9nrA7mR440+Y5hJngF9xf+bjVxx41F5lB5tAlitaxg3WCSBKz3tyaGXIRQRe0UXNWPo23/kbC N5TxcpDO+BC69XRYoDV5W99Gx9OS1FmeBQ4uJ2SXntddgnf07Sti9Fh60azR0Z51NUk+wUMYsCJ oMEzoehId72K5XhYS8jf2lFV2rYG+kZj9ZIBhw14DYfYaEZejgoB0ny7DxQ7HNUvLMg7FcAxZXS DgHx/cdZ1Bk X-Received: by 2002:a05:7300:2d07:b0:2d3:9c91:6c45 with SMTP id 5a478bee46e88-2f6e24f93acmr7143307eec.6.1778473792018; Sun, 10 May 2026 21:29:52 -0700 (PDT) Received: from [192.168.1.18] (177-4-161-87.user3p.v-tal.net.br. [177.4.161.87]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2f88885b87dsm14492043eec.21.2026.05.10.21.29.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2026 21:29:51 -0700 (PDT) From: =?utf-8?q?C=C3=A1ssio_Gabriel?= Date: Mon, 11 May 2026 01:29:34 -0300 Subject: [PATCH RESEND] ALSA: hda/cs35l41: Fix firmware load work teardown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260511-alsa-hda-cs35l41-fw-work-teardown-v1-1-1184e9bc4f25@gmail.com> To: David Rhodes , Richard Fitzgerald , Takashi Iwai , Stefan Binding , Vitaly Rodionov , Jaroslav Kysela Cc: linux-sound@vger.kernel.org, patches@opensource.cirrus.com, linux-kernel@vger.kernel.org, stable@vger.kernel.org, =?utf-8?q?C=C3=A1ssio_Gabriel?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6027; i=cassiogabrielcontato@gmail.com; h=from:subject:message-id; bh=Fs0OJQxWXkrUkceQIIh8xUwlumLQ4eJxzykdIOR4reI=; b=owGbwMvMwCV2IdZeKur/u2bG02pJDFmM0dY8Ed07Xu0S+LLN8cbtLSEC/aoNXK+flJzUz+U6/ E476ppsRykLgxgXg6yYIsvqpEWWe7oeXK2PW+EBM4eVCWQIAxenAExEvomRYcXCoPjplRPS/Nf9 +XpTOYhZYav0hYiTSysfvjp93rf74xJGhulnnuvM4lhU9PfK9N3cGgenz73IP+OPX9N+pkuRyrb vrvMBAA== X-Developer-Key: i=cassiogabrielcontato@gmail.com; a=openpgp; fpr=AB62A239BC8AE0D57F5EA848D05D3F1A5AFFEE83 cs35l41_hda creates ALSA controls whose private data points at the cs35l41_hda object. The firmware load control can also queue fw_load_work. Those controls are not removed on component unbind, and device remove only cancels fw_load_work through cs35l41_remove_dsp(). That helper is skipped when halo_initialized is false. With firmware_autostart disabled, a firmware load can be requested before the DSP has been initialized. If the component or device is removed before the queued work runs, the worker can run after teardown and dereference driver state that is no longer valid. Track the created controls and remove them on unbind so no new control callback can reach the driver data or queue more work. Then cancel fw_load_work to drain any request that was already queued. Also cancel the work unconditionally during device remove before runtime PM teardown. Fixes: 47ceabd99a28 ("ALSA: hda: cs35l41: Support Firmware switching and re= loading") Fixes: 4c870513fbb0 ("ALSA: hda: cs35l41: Add read-only ALSA control for fo= rced mute") Cc: stable@vger.kernel.org Signed-off-by: C=C3=A1ssio Gabriel Reviewed-by: Stefan Binding --- sound/hda/codecs/side-codecs/cs35l41_hda.c | 77 +++++++++++++++++++++-----= ---- sound/hda/codecs/side-codecs/cs35l41_hda.h | 5 ++ 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/= side-codecs/cs35l41_hda.c index b64890006bb7..7f18be0ccf5a 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda.c +++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c @@ -1325,6 +1325,43 @@ static int cs35l41_fw_type_ctl_info(struct snd_kcont= rol *kcontrol, struct snd_ct return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l4= 1_hda_fw_ids); } =20 +static void cs35l41_remove_controls(struct cs35l41_hda *cs35l41) +{ + if (!cs35l41->codec) + return; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->mute_override_ctl); + cs35l41->mute_override_ctl =3D NULL; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_load_ctl); + cs35l41->fw_load_ctl =3D NULL; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_type_ctl); + cs35l41->fw_type_ctl =3D NULL; +} + +static int cs35l41_add_control(struct cs35l41_hda *cs35l41, + struct snd_kcontrol_new *ctl, + struct snd_kcontrol **kctl) +{ + int ret; + + *kctl =3D snd_ctl_new1(ctl, cs35l41); + if (!*kctl) + return -ENOMEM; + + ret =3D snd_ctl_add(cs35l41->codec->card, *kctl); + if (ret) { + dev_err(cs35l41->dev, "Failed to add KControl %s =3D %d\n", ctl->name, r= et); + *kctl =3D NULL; + return ret; + } + + dev_dbg(cs35l41->dev, "Added Control %s\n", ctl->name); + + return 0; +} + static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) { char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -1360,32 +1397,23 @@ static int cs35l41_create_controls(struct cs35l41_h= da *cs35l41) scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forc= ed Mute Status", cs35l41->amp_name); =20 - ret =3D snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35= l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s =3D %d\n", fw_type_ctl.= name, ret); - return ret; - } - - dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name); - - ret =3D snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35= l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s =3D %d\n", fw_load_ctl.= name, ret); - return ret; - } - - dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name); + ret =3D cs35l41_add_control(cs35l41, &fw_type_ctl, &cs35l41->fw_type_ctl); + if (ret) + goto err; =20 - ret =3D snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl= , cs35l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s =3D %d\n", mute_overrid= e_ctl.name, - ret); - return ret; - } + ret =3D cs35l41_add_control(cs35l41, &fw_load_ctl, &cs35l41->fw_load_ctl); + if (ret) + goto err; =20 - dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name); + ret =3D cs35l41_add_control(cs35l41, &mute_override_ctl, &cs35l41->mute_o= verride_ctl); + if (ret) + goto err; =20 return 0; + +err: + cs35l41_remove_controls(cs35l41); + return ret; } =20 static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int command= s) @@ -1522,6 +1550,10 @@ static void cs35l41_hda_unbind(struct device *dev, s= truct device *master, void * device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev); unlock_system_sleep(sleep_flags); memset(comp, 0, sizeof(*comp)); + + cs35l41_remove_controls(cs35l41); + cancel_work_sync(&cs35l41->fw_load_work); + cs35l41->codec =3D NULL; } } =20 @@ -2058,6 +2090,7 @@ void cs35l41_hda_remove(struct device *dev) struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); =20 component_del(cs35l41->dev, &cs35l41_hda_comp_ops); + cancel_work_sync(&cs35l41->fw_load_work); =20 pm_runtime_get_sync(cs35l41->dev); pm_runtime_dont_use_autosuspend(cs35l41->dev); diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.h b/sound/hda/codecs/= side-codecs/cs35l41_hda.h index 7d003c598e93..56ec07c0bb74 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda.h +++ b/sound/hda/codecs/side-codecs/cs35l41_hda.h @@ -57,6 +57,8 @@ enum control_bus { SPI }; =20 +struct snd_kcontrol; + struct cs35l41_hda { struct device *dev; struct regmap *regmap; @@ -75,6 +77,9 @@ struct cs35l41_hda { int speaker_id; struct mutex fw_mutex; struct work_struct fw_load_work; + struct snd_kcontrol *fw_type_ctl; + struct snd_kcontrol *fw_load_ctl; + struct snd_kcontrol *mute_override_ctl; =20 struct regmap_irq_chip_data *irq_data; bool firmware_running; --- base-commit: 1bc46462f4c09f8d429ae8ec17f92886d604659f change-id: 20260421-alsa-hda-cs35l41-fw-work-teardown-48cdba14a9cd Best regards, -- C=C3=A1ssio Gabriel --=20 C=C3=A1ssio Gabriel