[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