ASoC: cs35l56: Fixes for deadlock/hang during component_probe()

Richard Fitzgerald <rf@opensource.cirrus.com> says:

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.

Link: https://patch.msgid.link/20260716132045.1469156-1-rf@opensource.cirrus.com
This commit is contained in:
Mark Brown 2026-07-16 15:25:13 +01:00
commit 1d3302efe6
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 18 additions and 7 deletions

View File

@ -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);

View File

@ -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);

View File

@ -2008,6 +2008,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));
@ -2022,6 +2032,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);
@ -2108,7 +2123,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;
}