Commit c0e7969c authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown

ASoC: SOF: topology: Add kernel parameter for topology verification

Add a kernel debug flag to enable a one-shot topology
verification for all pipelines including the dynamic
ones. If the debug flag is set, all the topology
component loading will be verified during the complete
callback.
Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: default avatarDaniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20210927120517.20505-13-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 5fcdbb2d
...@@ -157,7 +157,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) ...@@ -157,7 +157,7 @@ static int sof_resume(struct device *dev, bool runtime_resume)
} }
/* restore pipelines */ /* restore pipelines */
ret = sof_set_up_pipelines(sdev->dev); ret = sof_set_up_pipelines(sdev->dev, false);
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, dev_err(sdev->dev,
"error: failed to restore pipeline after resume %d\n", "error: failed to restore pipeline after resume %d\n",
...@@ -208,7 +208,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ...@@ -208,7 +208,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
if (target_state == SOF_DSP_PM_D0) if (target_state == SOF_DSP_PM_D0)
goto suspend; goto suspend;
sof_tear_down_pipelines(dev); sof_tear_down_pipelines(dev, false);
/* release trace */ /* release trace */
snd_sof_release_trace(sdev); snd_sof_release_trace(sdev);
......
...@@ -589,7 +589,7 @@ const struct sof_ipc_pipe_new *snd_sof_pipeline_find(struct snd_sof_dev *sdev, ...@@ -589,7 +589,7 @@ const struct sof_ipc_pipe_new *snd_sof_pipeline_find(struct snd_sof_dev *sdev,
return NULL; return NULL;
} }
int sof_set_up_pipelines(struct device *dev) int sof_set_up_pipelines(struct device *dev, bool verify)
{ {
struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_sof_widget *swidget; struct snd_sof_widget *swidget;
...@@ -599,7 +599,7 @@ int sof_set_up_pipelines(struct device *dev) ...@@ -599,7 +599,7 @@ int sof_set_up_pipelines(struct device *dev)
/* restore pipeline components */ /* restore pipeline components */
list_for_each_entry_reverse(swidget, &sdev->widget_list, list) { list_for_each_entry_reverse(swidget, &sdev->widget_list, list) {
/* only set up the widgets belonging to static pipelines */ /* only set up the widgets belonging to static pipelines */
if (swidget->dynamic_pipeline_widget) if (!verify && swidget->dynamic_pipeline_widget)
continue; continue;
/* update DAI config. The IPC will be sent in sof_widget_setup() */ /* update DAI config. The IPC will be sent in sof_widget_setup() */
...@@ -630,8 +630,8 @@ int sof_set_up_pipelines(struct device *dev) ...@@ -630,8 +630,8 @@ int sof_set_up_pipelines(struct device *dev)
list_for_each_entry(sroute, &sdev->route_list, list) { list_for_each_entry(sroute, &sdev->route_list, list) {
/* only set up routes belonging to static pipelines */ /* only set up routes belonging to static pipelines */
if (sroute->src_widget->dynamic_pipeline_widget || if (!verify && (sroute->src_widget->dynamic_pipeline_widget ||
sroute->sink_widget->dynamic_pipeline_widget) sroute->sink_widget->dynamic_pipeline_widget))
continue; continue;
ret = sof_route_setup_ipc(sdev, sroute); ret = sof_route_setup_ipc(sdev, sroute);
...@@ -646,7 +646,7 @@ int sof_set_up_pipelines(struct device *dev) ...@@ -646,7 +646,7 @@ int sof_set_up_pipelines(struct device *dev)
switch (swidget->id) { switch (swidget->id) {
case snd_soc_dapm_scheduler: case snd_soc_dapm_scheduler:
/* only complete static pipelines */ /* only complete static pipelines */
if (swidget->dynamic_pipeline_widget) if (!verify && swidget->dynamic_pipeline_widget)
continue; continue;
swidget->complete = swidget->complete =
...@@ -661,24 +661,37 @@ int sof_set_up_pipelines(struct device *dev) ...@@ -661,24 +661,37 @@ int sof_set_up_pipelines(struct device *dev)
} }
/* /*
* This function doesn't free widgets. It only resets the set up status for all routes and * This function doesn't free widgets during suspend. It only resets the set up status for all
* use_count for all widgets. * routes and use_count for all widgets.
*/ */
void sof_tear_down_pipelines(struct device *dev) int sof_tear_down_pipelines(struct device *dev, bool verify)
{ {
struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_sof_widget *swidget; struct snd_sof_widget *swidget;
struct snd_sof_route *sroute; struct snd_sof_route *sroute;
int ret;
/* /*
* No need to protect swidget->use_count and sroute->setup as this function is called only * This function is called during suspend and for one-time topology verification during
* during the suspend callback and all streams should be suspended by then * first boot. In both cases, there is no need to protect swidget->use_count and
* sroute->setup because during suspend all streams are suspended and during topology
* loading the sound card unavailable to open PCMs.
*/ */
list_for_each_entry(swidget, &sdev->widget_list, list) list_for_each_entry_reverse(swidget, &sdev->widget_list, list) {
if (!verify) {
swidget->use_count = 0; swidget->use_count = 0;
continue;
}
ret = sof_widget_free(sdev, swidget);
if (ret < 0)
return ret;
}
list_for_each_entry(sroute, &sdev->route_list, list) list_for_each_entry(sroute, &sdev->route_list, list)
sroute->setup = false; sroute->setup = false;
return 0;
} }
/* /*
......
...@@ -246,8 +246,8 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, ...@@ -246,8 +246,8 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol,
int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
/* PM */ /* PM */
int sof_set_up_pipelines(struct device *dev); int sof_set_up_pipelines(struct device *dev, bool verify);
void sof_tear_down_pipelines(struct device *dev); int sof_tear_down_pipelines(struct device *dev, bool verify);
int sof_set_hw_params_upon_resume(struct device *dev); int sof_set_hw_params_upon_resume(struct device *dev);
bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev);
bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev); bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
/* debug flags */ /* debug flags */
#define SOF_DBG_ENABLE_TRACE BIT(0) #define SOF_DBG_ENABLE_TRACE BIT(0)
#define SOF_DBG_RETAIN_CTX BIT(1) /* prevent DSP D3 on FW exception */ #define SOF_DBG_RETAIN_CTX BIT(1) /* prevent DSP D3 on FW exception */
#define SOF_DBG_VERIFY_TPLG BIT(2) /* verify topology during load */
#define SOF_DBG_DUMP_REGS BIT(0) #define SOF_DBG_DUMP_REGS BIT(0)
#define SOF_DBG_DUMP_MBOX BIT(1) #define SOF_DBG_DUMP_MBOX BIT(1)
......
...@@ -3452,8 +3452,23 @@ static int sof_complete(struct snd_soc_component *scomp) ...@@ -3452,8 +3452,23 @@ static int sof_complete(struct snd_soc_component *scomp)
} }
} }
/* verify topology components loading including dynamic pipelines */
if (sof_core_debug & SOF_DBG_VERIFY_TPLG) {
ret = sof_set_up_pipelines(scomp->dev, true);
if (ret < 0) {
dev_err(sdev->dev, "error: topology verification failed %d\n", ret);
return ret;
}
ret = sof_tear_down_pipelines(scomp->dev, true);
if (ret < 0) {
dev_err(sdev->dev, "error: topology tear down pipelines failed %d\n", ret);
return ret;
}
}
/* set up static pipelines */ /* set up static pipelines */
return sof_set_up_pipelines(scomp->dev); return sof_set_up_pipelines(scomp->dev, false);
} }
/* manifest - optional to inform component of manifest */ /* manifest - optional to inform component of manifest */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment