ASoC: SOF/soundwire: use resume_and_get on component probe

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

While testing driver bind/unbind sequences, I stumbled on a corner
case where the SoundWire bus can be suspended before the ASoC card
registration happens. During the registration, register accesses would
then lead to timeouts. This does not happen in regular usages where
the card registration happens within the 3-second time window before
suspend.

Adding a simple pm_runtime_resume_and_get() on component probe solves
the issue, but experiments showed it was too invasive to add at the
ASoC core level, with multiple regressions reported by our CI.

This patchset limits the additional resume to the SOF and SoundWire
codec drivers. An additional patch for the soundwire/intel component
will be sent separately.
This commit is contained in:
Mark Brown 2022-06-18 01:46:19 +01:00
commit 87a36978b2
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
9 changed files with 87 additions and 1 deletions

View File

@ -5,6 +5,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/cdev.h>
@ -440,8 +441,19 @@ const struct snd_soc_component_driver soc_codec_dev_max98373 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_max98373);
static int max98373_sdw_probe(struct snd_soc_component *component)
{
int ret;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}
const struct snd_soc_component_driver soc_codec_dev_max98373_sdw = {
.probe = NULL,
.probe = max98373_sdw_probe,
.controls = max98373_snd_controls,
.num_controls = ARRAY_SIZE(max98373_snd_controls),
.dapm_widgets = max98373_dapm_widgets,

View File

@ -608,7 +608,19 @@ static const struct sdw_slave_ops rt1308_slave_ops = {
.bus_config = rt1308_bus_config,
};
static int rt1308_sdw_component_probe(struct snd_soc_component *component)
{
int ret;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}
static const struct snd_soc_component_driver soc_component_sdw_rt1308 = {
.probe = rt1308_sdw_component_probe,
.controls = rt1308_snd_controls,
.num_controls = ARRAY_SIZE(rt1308_snd_controls),
.dapm_widgets = rt1308_dapm_widgets,

View File

@ -590,7 +590,19 @@ static struct sdw_slave_ops rt1316_slave_ops = {
.update_status = rt1316_update_status,
};
static int rt1316_sdw_component_probe(struct snd_soc_component *component)
{
int ret;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}
static const struct snd_soc_component_driver soc_component_sdw_rt1316 = {
.probe = rt1316_sdw_component_probe,
.controls = rt1316_snd_controls,
.num_controls = ARRAY_SIZE(rt1316_snd_controls),
.dapm_widgets = rt1316_dapm_widgets,

View File

@ -818,9 +818,14 @@ static const struct snd_soc_dapm_route rt700_audio_map[] = {
static int rt700_probe(struct snd_soc_component *component)
{
struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
int ret;
rt700->component = component;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}

View File

@ -1194,10 +1194,15 @@ static int rt711_sdca_parse_dt(struct rt711_sdca_priv *rt711, struct device *dev
static int rt711_sdca_probe(struct snd_soc_component *component)
{
struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
int ret;
rt711_sdca_parse_dt(rt711, &rt711->slave->dev);
rt711->component = component;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}

View File

@ -935,10 +935,15 @@ static int rt711_parse_dt(struct rt711_priv *rt711, struct device *dev)
static int rt711_probe(struct snd_soc_component *component)
{
struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
int ret;
rt711_parse_dt(rt711, &rt711->slave->dev);
rt711->component = component;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}

View File

@ -758,7 +758,19 @@ static const struct snd_soc_dapm_route rt715_sdca_audio_map[] = {
{"ADC 25 Mux", "DMIC4", "DMIC4"},
};
static int rt715_sdca_probe(struct snd_soc_component *component)
{
int ret;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}
static const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = {
.probe = rt715_sdca_probe,
.controls = rt715_sdca_snd_controls,
.num_controls = ARRAY_SIZE(rt715_sdca_snd_controls),
.dapm_widgets = rt715_sdca_dapm_widgets,

View File

@ -737,7 +737,19 @@ static int rt715_set_bias_level(struct snd_soc_component *component,
return 0;
}
static int rt715_probe(struct snd_soc_component *component)
{
int ret;
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}
static const struct snd_soc_component_driver soc_codec_dev_rt715 = {
.probe = rt715_probe,
.set_bias_level = rt715_set_bias_level,
.controls = rt715_snd_controls,
.num_controls = ARRAY_SIZE(rt715_snd_controls),

View File

@ -604,6 +604,14 @@ static int sof_pcm_probe(struct snd_soc_component *component)
const char *tplg_filename;
int ret;
/*
* make sure the device is pm_runtime_active before loading the
* topology and initiating IPC or bus transactions
*/
ret = pm_runtime_resume_and_get(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
/* load the default topology */
sdev->component = component;
@ -621,6 +629,9 @@ static int sof_pcm_probe(struct snd_soc_component *component)
return ret;
}
pm_runtime_mark_last_busy(component->dev);
pm_runtime_put_autosuspend(component->dev);
return ret;
}