Linux Sound subsystem development
 help / color / mirror / Atom feed
* [BUG] ALSA: hda: cs35l41: stale cs_dsp.name after component unbind breaks firmware load
@ 2026-10-29  8:46 Mads
  2026-10-30 17:13 ` Stefan Binding (Opensource)
  0 siblings, 1 reply; 2+ messages in thread
From: Mads @ 2026-10-29  8:46 UTC (permalink / raw)
  To: David Rhodes, Richard Fitzgerald
  Cc: Takashi Iwai, linux-sound@vger.kernel.org,
	patches@opensource.cirrus.com


[-- Attachment #1.1: Type: text/plain, Size: 2367 bytes --]

Hi,

Same machine and kernel as my report "amp dead until reboot after one
failed system resume (shared reset)": HP Spectre x360 14-eu0xxx, SSID
103C8C15, 2x CS35L41 on I2C, kernel 7.2.5 (Omarchy distro kernel). The
code below is unchanged in mainline as of 75c1cb8178fe.

To recover the stuck right amp without a reboot, I unbound and rebound
only .1:

  echo i2c-CSC3551:00-cs35l41-hda.1 > /sys/bus/i2c/drivers/cs35l41-hda/unbind
  echo i2c-CSC3551:00-cs35l41-hda.1 > /sys/bus/i2c/drivers/cs35l41-hda/bind

.1 came back fine after a fresh probe. But .0, which was only unbound
and rebound as a component, could no longer load firmware:

  cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Falling back to default firmware.
  cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Unable to find firmware and tuning
  cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cannot Initialize Firmware. Error: -2
  cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cannot Run Firmware, reverting to dsp bypass...
  cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: CS35L41 Bound - SSID: 103C8C15, BST: 0, VSPK: 0, CH: L, FW EN: 0, SPKID: 0

The files exist, and .1 loaded the same .wmfw a moment later. Toggling
"L0 DSP1 Firmware Load" off and on gave the same -2. Only a reboot
fixed it.

From reading the code, I think it goes like this. With
firmware_autostart, the first cs35l41_hda_bind() calls
cs35l41_smart_amp() -> cs35l41_init_dsp() -> cs_dsp_halo_init(), and
cs_dsp_create_name() allocates dsp->name with
devm_kasprintf(dsp->dev, ...). Because that happens inside
component_bind(), the allocation lands in the component's devres group,
and component_unbind() releases that group. cs35l41_hda_unbind() does
not reset halo_initialized; only cs35l41_remove_dsp() does, and that
runs from remove. So the next bind skips cs_dsp_halo_init() and builds
the firmware file names from the freed dsp->name, which is a
use-after-free. The freed name also shows in .1's own messages during
its unbind ("DSP1:" becomes empty):

  cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: : Failed to read SCRATCH0: -16

I have not confirmed this with KASAN. Possible fixes: tear the DSP down
in cs35l41_hda_unbind() (cs35l41_remove_dsp(), or at least clear
halo_initialized and dsp->name), or keep the name allocation out of the
bind devres group.

I'm happy to test patches.

Thanks,
Mads

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 343 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-30 17:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29  8:46 [BUG] ALSA: hda: cs35l41: stale cs_dsp.name after component unbind breaks firmware load Mads
2026-10-30 17:13 ` Stefan Binding (Opensource)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox