mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe()
@ 2026-07-16 13:20 Richard Fitzgerald
  2026-07-16 13:20 ` [PATCH 1/2] ASoC: cs35l56: Fix potential probe() deadlock Richard Fitzgerald
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Richard Fitzgerald @ 2026-07-16 13:20 UTC (permalink / raw)
  To: broonie; +Cc: salman.abusaad, linux-sound, linux-kernel, patches

This series fixes two problems found in the probing process that
can cause a deadlock (patch #1) or a hang (patch #2) during
component_probe() until the wait for init_completion times out.

Richard Fitzgerald (2):
  ASoC: cs35l56: Fix potential probe() deadlock
  ASoC: cs35l56: Use complete_all() to signal init_completion

 sound/soc/codecs/cs35l56-i2c.c |  4 +---
 sound/soc/codecs/cs35l56-spi.c |  4 +---
 sound/soc/codecs/cs35l56.c     | 17 ++++++++++++++++-
 3 files changed, 18 insertions(+), 7 deletions(-)

-- 
2.47.3


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

* [PATCH 1/2] ASoC: cs35l56: Fix potential probe() deadlock
  2026-07-16 13:20 [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Richard Fitzgerald
@ 2026-07-16 13:20 ` Richard Fitzgerald
  2026-07-16 13:20 ` [PATCH 2/2] ASoC: cs35l56: Use complete_all() to signal init_completion Richard Fitzgerald
  2026-07-16 14:25 ` [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Mark Brown
  2 siblings, 0 replies; 4+ messages in thread
From: Richard Fitzgerald @ 2026-07-16 13:20 UTC (permalink / raw)
  To: broonie; +Cc: salman.abusaad, linux-sound, linux-kernel, patches

On I2C/SPI call cs35l56_init() before calling
snd_soc_register_component() to prevent the potential for a deadlock
on init_completion.

For most buses all the hardware would be ready when probe() returns,
but on SoundWire, probe() must return before the SoundWire bus driver
will enumerate the device. All access to the registers must be deferred
until the driver receives an ATTACHED notification. But anything that
could return -EPROBE_DEFER must be called during probe, and that includes
snd_soc_register_component(). Because of that, on SoundWire the ASoC
component can be created before the registers are accssible, so
cs35l56_component_probe() waits for init_completion to signal that the
registers are accessible.

On I2C/SPI this 2-stage startup isn't required so their probe()
functions simply called cs35l56_common_probe() and then cs35l56_init().
The problem with this was that snd_soc_register_component() was still
called early. If this triggered ASoC to create the card, ASoC would call
cs35l56_component_probe() which waits on init_completion - but this would
be running inside the cs35l56 driver probe() so blocking it from reaching
the code that signals init_completion, causing a deadlock.

Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56")
Reported-by: Salman S. Tahir <salman.abusaad@gmail.com>
Closes: https://lore.kernel.org/linux-sound/95c21574-97d5-4311-9263-9e174d22d22c@opensource.cirrus.com/T/#u
Tested-by: Salman S. Tahir <salman.abusaad@gmail.com>
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
 sound/soc/codecs/cs35l56-i2c.c |  4 +---
 sound/soc/codecs/cs35l56-spi.c |  4 +---
 sound/soc/codecs/cs35l56.c     | 15 +++++++++++++++
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c
index 0f64ab628b03b..4f6ddf1c5a3f6 100644
--- a/sound/soc/codecs/cs35l56-i2c.c
+++ b/sound/soc/codecs/cs35l56-i2c.c
@@ -55,9 +55,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
 	if (ret != 0)
 		return ret;
 
-	ret = cs35l56_init(cs35l56);
-	if (ret == 0)
-		ret = cs35l56_irq_request(&cs35l56->base, client->irq);
+	ret = cs35l56_irq_request(&cs35l56->base, client->irq);
 	if (ret < 0)
 		cs35l56_remove(cs35l56);
 
diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c
index 9bc9b7c98390d..b1eb924a5b6cc 100644
--- a/sound/soc/codecs/cs35l56-spi.c
+++ b/sound/soc/codecs/cs35l56-spi.c
@@ -44,9 +44,7 @@ static int cs35l56_spi_probe(struct spi_device *spi)
 	if (ret != 0)
 		return ret;
 
-	ret = cs35l56_init(cs35l56);
-	if (ret == 0)
-		ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
+	ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
 	if (ret < 0)
 		cs35l56_remove(cs35l56);
 
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index f365f76ce56c1..995e39645621e 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -2009,6 +2009,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
 		goto err;
 	}
 
+	/*
+	 * On SoundWire the cs35l56_init() cannot be run until after the
+	 * device has been enumerated by the SoundWire core.
+	 */
+	if (!cs35l56->sdw_peripheral) {
+		ret = cs35l56_init(cs35l56);
+		if (ret)
+			goto err_remove_wm_adsp;
+	}
+
 	ret = snd_soc_register_component(cs35l56->base.dev,
 					 &soc_component_dev_cs35l56,
 					 cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
@@ -2023,6 +2033,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
 	wm_adsp2_remove(&cs35l56->dsp);
 
 err:
+	if (pm_runtime_enabled(cs35l56->base.dev)) {
+		pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
+		pm_runtime_disable(cs35l56->base.dev);
+	}
+
 	gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
 	regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
 
-- 
2.47.3


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

* [PATCH 2/2] ASoC: cs35l56: Use complete_all() to signal init_completion
  2026-07-16 13:20 [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Richard Fitzgerald
  2026-07-16 13:20 ` [PATCH 1/2] ASoC: cs35l56: Fix potential probe() deadlock Richard Fitzgerald
@ 2026-07-16 13:20 ` Richard Fitzgerald
  2026-07-16 14:25 ` [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Mark Brown
  2 siblings, 0 replies; 4+ messages in thread
From: Richard Fitzgerald @ 2026-07-16 13:20 UTC (permalink / raw)
  To: broonie; +Cc: salman.abusaad, linux-sound, linux-kernel, patches

In cs35l56_init() use complete_all() to signal init_completion instead
of complete().

cs35l56_init() was signaling init_completion using the complete() function.
This only releases ONE waiter.

If cs35l56_component_probe() was called multiple times the first time
would consume that one signal, then future calls would timeout waiting for
the completion. This could happen if:

 - The component is probed, removed, then probed again without the cs35l56
   module being removed.

 - A call to component_probe() returns an error and ASoC calls it again
   later.

It should use complete_all() so that after it has been signaled it will
allow any code that waits on it to continue immediately.

The one case where the driver must wait for initialization to run again is
when waiting for a reboot after firmware download, and here the code
correctly calls reinit_completion() first.

Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56")
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
 sound/soc/codecs/cs35l56.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index 995e39645621e..0b7b080939a18 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -2124,7 +2124,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
 		return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n");
 
 	cs35l56->base.init_done = true;
-	complete(&cs35l56->init_completion);
+	complete_all(&cs35l56->init_completion);
 
 	return 0;
 }
-- 
2.47.3


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

* Re: [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe()
  2026-07-16 13:20 [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Richard Fitzgerald
  2026-07-16 13:20 ` [PATCH 1/2] ASoC: cs35l56: Fix potential probe() deadlock Richard Fitzgerald
  2026-07-16 13:20 ` [PATCH 2/2] ASoC: cs35l56: Use complete_all() to signal init_completion Richard Fitzgerald
@ 2026-07-16 14:25 ` Mark Brown
  2 siblings, 0 replies; 4+ messages in thread
From: Mark Brown @ 2026-07-16 14:25 UTC (permalink / raw)
  To: Richard Fitzgerald; +Cc: salman.abusaad, linux-sound, linux-kernel, patches

On Thu, 16 Jul 2026 14:20:43 +0100, Richard Fitzgerald wrote:
> ASoC: cs35l56: Fixes for deadlock/hang during component_probe()
> 
> This series fixes two problems found in the probing process that
> can cause a deadlock (patch #1) or a hang (patch #2) during
> component_probe() until the wait for init_completion times out.
> 
> Richard Fitzgerald (2):
>   ASoC: cs35l56: Fix potential probe() deadlock
>   ASoC: cs35l56: Use complete_all() to signal init_completion
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2

Thanks!

[1/2] ASoC: cs35l56: Fix potential probe() deadlock
      https://git.kernel.org/broonie/sound/c/93c2a8ea2454
[2/2] ASoC: cs35l56: Use complete_all() to signal init_completion
      https://git.kernel.org/broonie/sound/c/e0bffb63a2ed

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


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

end of thread, other threads:[~2026-07-18  0:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-16 13:20 [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Richard Fitzgerald
2026-07-16 13:20 ` [PATCH 1/2] ASoC: cs35l56: Fix potential probe() deadlock Richard Fitzgerald
2026-07-16 13:20 ` [PATCH 2/2] ASoC: cs35l56: Use complete_all() to signal init_completion Richard Fitzgerald
2026-07-16 14:25 ` [PATCH 0/2] ASoC: cs35l56: Fixes for deadlock/hang during component_probe() Mark Brown

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

Powered by JetHome