OSDN Git Service

ASoC: SOF: topology: Add kernel parameter for topology verification
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Mon, 27 Sep 2021 12:05:17 +0000 (15:05 +0300)
committerMark Brown <broonie@kernel.org>
Fri, 1 Oct 2021 19:48:31 +0000 (20:48 +0100)
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: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20210927120517.20505-13-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/pm.c
sound/soc/sof/sof-audio.c
sound/soc/sof/sof-audio.h
sound/soc/sof/sof-priv.h
sound/soc/sof/topology.c

index 891e8b9..77a3496 100644 (file)
@@ -157,7 +157,7 @@ static int sof_resume(struct device *dev, bool runtime_resume)
        }
 
        /* restore pipelines */
-       ret = sof_set_up_pipelines(sdev->dev);
+       ret = sof_set_up_pipelines(sdev->dev, false);
        if (ret < 0) {
                dev_err(sdev->dev,
                        "error: failed to restore pipeline after resume %d\n",
@@ -208,7 +208,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
        if (target_state == SOF_DSP_PM_D0)
                goto suspend;
 
-       sof_tear_down_pipelines(dev);
+       sof_tear_down_pipelines(dev, false);
 
        /* release trace */
        snd_sof_release_trace(sdev);
index 7b4dd64..c4cabe2 100644 (file)
@@ -589,7 +589,7 @@ const struct sof_ipc_pipe_new *snd_sof_pipeline_find(struct snd_sof_dev *sdev,
        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_widget *swidget;
@@ -599,7 +599,7 @@ int sof_set_up_pipelines(struct device *dev)
        /* restore pipeline components */
        list_for_each_entry_reverse(swidget, &sdev->widget_list, list) {
                /* only set up the widgets belonging to static pipelines */
-               if (swidget->dynamic_pipeline_widget)
+               if (!verify && swidget->dynamic_pipeline_widget)
                        continue;
 
                /* update DAI config. The IPC will be sent in sof_widget_setup() */
@@ -630,8 +630,8 @@ int sof_set_up_pipelines(struct device *dev)
        list_for_each_entry(sroute, &sdev->route_list, list) {
 
                /* only set up routes belonging to static pipelines */
-               if (sroute->src_widget->dynamic_pipeline_widget ||
-                   sroute->sink_widget->dynamic_pipeline_widget)
+               if (!verify && (sroute->src_widget->dynamic_pipeline_widget ||
+                               sroute->sink_widget->dynamic_pipeline_widget))
                        continue;
 
                ret = sof_route_setup_ipc(sdev, sroute);
@@ -646,7 +646,7 @@ int sof_set_up_pipelines(struct device *dev)
                switch (swidget->id) {
                case snd_soc_dapm_scheduler:
                        /* only complete static pipelines */
-                       if (swidget->dynamic_pipeline_widget)
+                       if (!verify && swidget->dynamic_pipeline_widget)
                                continue;
 
                        swidget->complete =
@@ -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
- * use_count for all widgets.
+ * This function doesn't free widgets during suspend. It only resets the set up status for all
+ * 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_widget *swidget;
        struct snd_sof_route *sroute;
+       int ret;
 
        /*
-        * No need to protect swidget->use_count and sroute->setup as this function is called only
-        * during the suspend callback and all streams should be suspended by then
+        * This function is called during suspend and for one-time topology verification during
+        * 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)
-               swidget->use_count = 0;
+       list_for_each_entry_reverse(swidget, &sdev->widget_list, list) {
+               if (!verify) {
+                       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)
                sroute->setup = false;
+
+       return 0;
 }
 
 /*
index 8d1fc6a..149b3db 100644 (file)
@@ -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);
 
 /* PM */
-int sof_set_up_pipelines(struct device *dev);
-void sof_tear_down_pipelines(struct device *dev);
+int sof_set_up_pipelines(struct device *dev, bool verify);
+int sof_tear_down_pipelines(struct device *dev, bool verify);
 int sof_set_hw_params_upon_resume(struct device *dev);
 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);
index a6ded5b..1289e2e 100644 (file)
@@ -23,6 +23,7 @@
 /* debug flags */
 #define SOF_DBG_ENABLE_TRACE   BIT(0)
 #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_MBOX              BIT(1)
index d8eb238..44d6008 100644 (file)
@@ -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 */
-       return sof_set_up_pipelines(scomp->dev);
+       return sof_set_up_pipelines(scomp->dev, false);
 }
 
 /* manifest - optional to inform component of manifest */