ASoC: cs35l56: Fix probe deadlock waiting for SoundWire enumeration

On SoundWire, don't call snd_soc_register_component() from driver probe().
Instead, queue a work item after first SoundWire attach to call
snd_soc_register_component(). This prevents a deadlock if
snd_soc_register_component() directly calls cs35l56_component_probe().

On SoundWire, the registers are not accessible during driver probe().
Drivers must return from their probe() and wait for the SoundWire core
to call their update_status() callback to report an ATTACHED status. The
cs35l56 driver handled this by calling snd_soc_register_component() from
driver probe() as usual, and cs35l56_component_probe() waited for
init_completion to be signalled. A SoundWire attach calls cs35l56_init()
which then signals init_completion.

This created a deadlock if this was the last component needed to complete
a card. In that case, snd_soc_register_component() directly called
cs35l56_component_probe() which led to this:

    driver probe()
        calls snd_soc_register_component()
            calls cs35l56_component_probe()
                waits for init_completion

In this case the driver probe() has not returned, so the SoundWire core
would not call update_status() and init_completion would not be signalled.

Fortunately, snd_soc_register_component() never returns -EPROBE_DEFER, so
it doesn't need to be called from a driver probe(). It can be deferred to
a work item. This work is queued after the first completed pass through
cs35l56_init(), so there is no need for it to wait for init_completion.
snd_soc_register_component() isn't called directly from cs35l56_init()
because cs35l56_init() runs in the SoundWire bus driver thread, and there
would be a risk of nested locking or lock inversion.

The work item is queued on a freezable workqueue to prevent a race between
the work item and system_suspend of another instance. If the workqueue
were not frozen it would be possible for the work item of one driver
instance to call snd_soc_register_component() which then calls
cs35l56_component_probe() of another instance while that instance is
already executing its system suspend functions.

The non-SoundWire case still calls snd_soc_register_component() from
cs35l56_common_probe() so that it is the last initialization action.
There's no need defer the call for I2S/SPI buses so we can also leave it
able to return errors during probe.

Fixes: 440c2d3895 ("ASoC: cs35l56: Wait for init_complete in cs35l56_component_probe()")
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260901122644.634494-1-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Richard Fitzgerald 2026-09-01 13:26:44 +01:00 • committed by Mark Brown
commit 1d80a4792f
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
2 changed files with 60 additions and 13 deletions