[PATCH] ASoC: soc-core: move snd_soc_dai_link_set_capabilities() to soc-core.c

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Tue Aug 18 06:29:23 CEST 2020


From: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>

commit 25612477d20b52 ("ASoC: soc-dai: set dai_link dpcm_ flags with a helper")
added snd_soc_dai_link_set_capabilities().
But it is using snd_soc_find_dai() (A) which is required client_mutex (B).
And client_mutex is soc-core.c local.

	struct snd_soc_dai *snd_soc_find_dai(xxx)
	{
		...
(B)		lockdep_assert_held(&client_mutex);
		...
	}

	void snd_soc_dai_link_set_capabilities(xxx)
	{
		...
		for_each_pcm_streams(direction) {
			...
			for_each_link_cpus(dai_link, i, cpu) {
(A)				dai = snd_soc_find_dai(cpu);
				...
			}
			...
			for_each_link_codecs(dai_link, i, codec) {
(A)				dai = snd_soc_find_dai(codec);
				...
			}
		}
		...
	}

Because of this, we will get WARNING.

	WARNING: CPU: 2 PID: 53 at sound/soc/soc-core.c:814 snd_soc_find_dai+0xf8/0x100
	CPU: 2 PID: 53 Comm: kworker/2:1 Not tainted 5.7.0-rc1+ #328
	Hardware name: Renesas H3ULCB Kingfisher board based on r8a77951 (DT)
	Workqueue: events deferred_probe_work_func
	pstate: 60000005 (nZCv daif -PAN -UAO)
	pc : snd_soc_find_dai+0xf8/0x100
	lr : snd_soc_find_dai+0xf4/0x100
	...
	Call trace:
	 snd_soc_find_dai+0xf8/0x100
	 snd_soc_dai_link_set_capabilities+0xa0/0x16c
	 graph_dai_link_of_dpcm+0x390/0x3c0
	 graph_for_each_link+0x134/0x200
	 graph_probe+0x144/0x230
	 platform_drv_probe+0x5c/0xb0
	 really_probe+0xe4/0x430
	 driver_probe_device+0x60/0xf4

Because not only snd_soc_dai_link_set_capabilities() but many drivers
are already using snd_soc_find_dai(),
1st idea for this issue was creating snd_soc_find_dai() of
_with_mutex / _without_mutex, but it was not enough and/or confusable.

soc-dai.c which is implemented snd_soc_dai_link_set_capabilities() currently is
mainly for snd_soc_dai related functions, not for snd_soc_dai_link.
Thus as 2nd idea, this patch moves snd_soc_dai_link_set_capabilities()
from soc-dai.c to soc-core.c, and use mutex_lock().

Fixes: 25612477d20b52 ("ASoC: soc-dai: set dai_link dpcm_ flags with a helper")
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 sound/soc/soc-core.c | 41 +++++++++++++++++++++++++++++++++++++++++
 sound/soc/soc-dai.c  | 38 --------------------------------------
 2 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index fe23e936e2d1..f46979f8d965 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -344,6 +344,47 @@ struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(snd_soc_lookup_component);
 
+/*
+ * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs
+ */
+void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
+{
+	struct snd_soc_dai_link_component *cpu;
+	struct snd_soc_dai_link_component *codec;
+	struct snd_soc_dai *dai;
+	bool supported[SNDRV_PCM_STREAM_LAST + 1];
+	int direction;
+	int i;
+
+	mutex_lock(&client_mutex);
+
+	for_each_pcm_streams(direction) {
+		supported[direction] = true;
+
+		for_each_link_cpus(dai_link, i, cpu) {
+			dai = snd_soc_find_dai(cpu);
+			if (!dai || !snd_soc_dai_stream_valid(dai, direction)) {
+				supported[direction] = false;
+				break;
+			}
+		}
+		if (!supported[direction])
+			continue;
+		for_each_link_codecs(dai_link, i, codec) {
+			dai = snd_soc_find_dai(codec);
+			if (!dai || !snd_soc_dai_stream_valid(dai, direction)) {
+				supported[direction] = false;
+				break;
+			}
+		}
+	}
+	mutex_unlock(&client_mutex);
+
+	dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
+	dai_link->dpcm_capture  = supported[SNDRV_PCM_STREAM_CAPTURE];
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
+
 struct snd_soc_pcm_runtime
 *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
 			 struct snd_soc_dai_link *dai_link)
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index 693893420bf0..783b7928205e 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -393,44 +393,6 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
 	return stream->channels_min;
 }
 
-/*
- * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs
- */
-void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
-{
-	struct snd_soc_dai_link_component *cpu;
-	struct snd_soc_dai_link_component *codec;
-	struct snd_soc_dai *dai;
-	bool supported[SNDRV_PCM_STREAM_LAST + 1];
-	int direction;
-	int i;
-
-	for_each_pcm_streams(direction) {
-		supported[direction] = true;
-
-		for_each_link_cpus(dai_link, i, cpu) {
-			dai = snd_soc_find_dai(cpu);
-			if (!dai || !snd_soc_dai_stream_valid(dai, direction)) {
-				supported[direction] = false;
-				break;
-			}
-		}
-		if (!supported[direction])
-			continue;
-		for_each_link_codecs(dai_link, i, codec) {
-			dai = snd_soc_find_dai(codec);
-			if (!dai || !snd_soc_dai_stream_valid(dai, direction)) {
-				supported[direction] = false;
-				break;
-			}
-		}
-	}
-
-	dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
-	dai_link->dpcm_capture  = supported[SNDRV_PCM_STREAM_CAPTURE];
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
-
 void snd_soc_dai_action(struct snd_soc_dai *dai,
 			int stream, int action)
 {
-- 
2.25.1



More information about the Alsa-devel mailing list