[REGRESSION 7.2-rc3] ASoC: cs35l56: component p robe waits for an init_completion that cannot be signalled unti l the wait ends — whole sof_sdw card fails
"Salman S. Tahir" <[email protected]> Wed, 15 Jul 2026 18:08:09 +0300
| Newsgroups | org.alsa-project.alsa-devel,org.kernel.vger.linux-sound |
|---|---|
| Message-ID | <[email protected]> |
Hi, On a Lenovo Yoga 9 2-in-1 14ILL10 (83LC, Core Ultra 7 258V / Lunar Lake; CS42L43 plus two SPI-attached CS35L56 amps behind it) the machine has no sound card at all on 7.2-rc3. /proc/asound/cards is empty and PipeWire falls back to a null sink. The right-hand amp's ASoC component probe times out waiting for init_completion, returns -ENODEV, and ASoC then tears down the entire card -- so speakers, internal mics, headset and all three HDMI outputs die because of one failed component: [ 10.301...] cs35l56 spi-cs35l56-right: _cs35l56_component_probe: init_completion timed out [ 10.301...] cs35l56 spi-cs35l56-right: ASoC error (-19): at snd_soc_component_probe() on spi-cs35l56-right [ 10.302...] sof_sdw sof_sdw: ASoC: failed to instantiate card -19 This is 100% reproducible. Scanning my whole journal (151 boots, back to 2026-03-07): 11 failures in 11 boots on 7.2.0-rc3, against 0 failures in 138 boots on every kernel I ran before it -- 6.17.0-14 (1 boot), 6.19.4 (83), 7.0.0-15 (20), 7.0.0-22 (20), 7.0.0-27 (14). It breaks at the first 7.2-rc3 boot and has failed every one since. (A 12th 7.2-rc3 boot is clean, but only because of the workaround described below.) Those failures were all captured on an otherwise stock machine -- clean kernel cmdline, distro modprobe.d only, no out-of-tree modules (other than the timeout experiment below), no DSDT override, distro Cirrus firmware. I now run a local workaround (a snd_soc_sof_sdw blacklist plus a service that loads it late -- described below); I can drop it and reproduce the failure on demand. This is not a slow-firmware race -------------------------------- The obvious reading of that log is "the amp is a bit too slow and misses the 5s deadline". It isn't, and I want to save you from chasing that. I rebuilt snd-soc-cs35l56 for 7.2-rc3 with a single change -- the component-probe wait at sound/soc/codecs/cs35l56.c:1371, msecs_to_jiffies(5000) -> msecs_to_jiffies(30000) -- and booted it. It fails identically, just later: component-probe timeout | wait expires at | right amp's cs35l56_init() actually starts ------------------------+-----------------+------------------------------------------- 5000 ms (stock) | 10.301 s | 10.355 s -- 54 ms after the wait gave up 30000 ms (patched) | 35.901 s | 36.005 s -- 104 ms after the wait gave up During the entire 30-second wait the right amp emits nothing. It does not even reach the cs35l56_hw_init() identification print that the left amp produced at 5.29 s: [ 5.294911] cs35l56 spi-cs35l56-left: Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0) [ 5.603038] cs35l56 spi-cs35l56-left: DSP1: cirrus/cs35l56-b0-dsp1-misc-17aa3832-spkid0.wmfw: format 3 ... [ 7.681077] cs35l56 spi-cs35l56-left: DSP1: Firmware: 1a00d6 vendor: 0x2 v3.11.26, 41 algorithms [ 9.498049] cs35l56 spi-cs35l56-left: Calibration applied <-- 26 seconds of silence from the right amp --> [ 35.901035] cs35l56 spi-cs35l56-right: _cs35l56_component_probe: init_completion timed out [ 35.902534] sof_sdw sof_sdw: ASoC: failed to instantiate card -19 [ 36.005138] cs35l56 spi-cs35l56-right: Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0) So the right amp's init is not losing a race against the deadline -- it is blocked by the wait itself, and only proceeds once the waiter gives up. Increasing the timeout just increases the wait; a 300-second timeout would fail at 305 seconds. The amp is not slow: once released it completes cs35l56_init() normally. (It gets no firmware download at that point -- the timeout path returns -ENODEV well before the queue_work(&cs35l56->dsp_work) at the end of _cs35l56_component_probe(), so nothing ever queues one for it.) The hardware is fine -- the card is just built ~100 ms too early ---------------------------------------------------------------- After the failed instantiation, spi-cs35l56-right is bound to the driver, i.e. its probe returned 0 and complete(&cs35l56->init_completion) did run. Nothing about the hardware, the firmware download or the SPI-over-SoundWire path is broken; the card is simply instantiated before the right amp is ready, and nothing ever retries it. I confirmed that by keeping the deadlock from forming at all, rather than repairing it afterwards: blacklist snd_soc_sof_sdw, wait until both amps have signalled init, then load it. With no card probe in flight there is nothing to starve the right amp: both amps reach their identification print within ~260 ms of each other (4.744 s and 5.008 s), the component probe's wait returns immediately, no timeout fires, and the card registers first time. Both amps are still patched=0 at that point, so both take the full firmware-download path, and both calibrate: [ 19.770067] cs35l56 spi-cs35l56-left: Calibration applied [ 19.777038] cs35l56 spi-cs35l56-right: Calibration applied That boot has since suspended and resumed with the card intact, and contains no error or warning from cs35l56, cs42l43 or SOF at all. Hypothesis (unverified -- offered only as a starting point) ----------------------------------------------------------- Something in 7.2 appears to have changed the ordering such that the right amp's probe and the sof_sdw card probe end up on the same execution context (the deferred-probe worker would fit the ~100 ms lag), so the blocking wait in _cs35l56_component_probe() starves the very work it is waiting for. I have not confirmed that, and I have not bisected -- I am reporting the reproducible behaviour rather than guessing at the culprit commit, and I would rather not send you down a path I only inferred. Suggested direction ------------------- Regardless of what changed the ordering, blocking in a component probe on a completion that a different probe must signal looks fragile by construction. Returning -EPROBE_DEFER instead -- letting the driver core retry the card once the amp is bound -- would use the mechanism the kernel already has for this, and snd_soc_bind_card() already special-cases -EPROBE_DEFER from soc_probe_link_components(). Something along the lines of: if (!wait_for_completion_timeout(&cs35l56->init_completion, msecs_to_jiffies(5000))) return dev_err_probe(cs35l56->https://www.google.com/url?q=http://base.dev&source=gmail&ust=1784212475584000&sa=E, -EPROBE_DEFER, "init_completion not signalled, deferring\n"); I have not tested that; I did not want to submit a patch built on a mechanism I have only hypothesised. I have the hardware, I can reproduce this on every boot, and I am happy to test patches, run instrumented builds, or bisect if that would help. Just tell me what would be most useful. Environment ----------- - Lenovo Yoga 9 2-in-1 14ILL10 (83LC), Core Ultra 7 258V (Lunar Lake) - CS42L43 (SoundWire) + 2x CS35L56 Rev B0, SPI-attached via the CS42L43 - Firmware: cirrus/cs35l56-b0-dsp1-misc-17aa3832-spkid0.wmfw v3.11.26 (distro linux-firmware) - Bad: 7.2-rc3 (7.2.0-070200rc3-generic, mainline build) -- 11 failures / 11 boots - Good: 7.0.0-27 (14 boots), 7.0.0-22 (20), 7.0.0-15 (20), 6.19.4 (83), 6.17.0-14 (1) -- 138 boots, 0 failures - Only the 30 s-timeout boot above ran a rebuilt (out-of-tree, kernel-tainting) snd-soc-cs35l56; every stock-timeout failure was on the untainted distro module - Not bisected - Workaround currently in place: blacklist snd_soc_sof_sdw + a systemd unit that modprobes it once both amps have signalled init. Removable on request -- I can reproduce the failure on any boot. Thanks, Salman S. Tahir