Takashi Iwai de1225
From a122a116fc6d8fcf2f202dcd185173a54268f239 Mon Sep 17 00:00:00 2001
Takashi Iwai de1225
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Takashi Iwai de1225
Date: Thu, 8 Apr 2021 13:28:38 +0900
Takashi Iwai de1225
Subject: [PATCH] ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init()
Takashi Iwai de1225
Git-commit: a122a116fc6d8fcf2f202dcd185173a54268f239
Takashi Iwai de1225
Patch-mainline: v5.13-rc1
Takashi Iwai de1225
References: git-fixes
Takashi Iwai de1225
Takashi Iwai de1225
Current rsnd needs to call .prepare (P) for clock settings,
Takashi Iwai de1225
.trigger for playback start (S) and stop (E).
Takashi Iwai de1225
It should be called as below from SSI point of view.
Takashi Iwai de1225
Takashi Iwai de1225
	P -> S -> E -> P -> S -> E -> ...
Takashi Iwai de1225
Takashi Iwai de1225
But, if you used MIXer, below case might happen
Takashi Iwai de1225
Takashi Iwai de1225
	              (2)
Takashi Iwai de1225
	1: P -> S ---> E -> ...
Takashi Iwai de1225
	2:         P ----> S -> ...
Takashi Iwai de1225
	          (1)     (3)
Takashi Iwai de1225
Takashi Iwai de1225
P(1) setups clock, but E(2) resets it. and starts playback (3).
Takashi Iwai de1225
In such case, it will reports "SSI parent/child should use same rate".
Takashi Iwai de1225
Takashi Iwai de1225
rsnd_ssi_master_clk_start() which is the main function at (P)
Takashi Iwai de1225
was called from rsnd_ssi_init() (= S) before,
Takashi Iwai de1225
but was moved by below patch to rsnd_soc_dai_prepare() (= P) to avoid
Takashi Iwai de1225
using clk_get_rate() which shouldn't be used under atomic context.
Takashi Iwai de1225
Takashi Iwai de1225
	commit 4d230d1271064 ("ASoC: rsnd: fixup not to call clk_get/set
Takashi Iwai de1225
				under non-atomic")
Takashi Iwai de1225
Takashi Iwai de1225
Because of above patch, rsnd_ssi_master_clk_start() is now called at (P)
Takashi Iwai de1225
which is for non atomic context. But (P) is assuming that spin lock is
Takashi Iwai de1225
*not* used.
Takashi Iwai de1225
One issue now is rsnd_ssi_master_clk_start() is checking ssi->xxx
Takashi Iwai de1225
which should be protected by spin lock.
Takashi Iwai de1225
Takashi Iwai de1225
After above patch, adg.c had below patch for other reasons.
Takashi Iwai de1225
Takashi Iwai de1225
	commit 06e8f5c842f2d ("ASoC: rsnd: don't call clk_get_rate()
Takashi Iwai de1225
				under atomic context")
Takashi Iwai de1225
Takashi Iwai de1225
clk_get_rate() is used at probe() timing by this patch.
Takashi Iwai de1225
In other words, rsnd_ssi_master_clk_start() is no longer using
Takashi Iwai de1225
clk_get_rate() any more.
Takashi Iwai de1225
Takashi Iwai de1225
This means we can call it from rsnd_ssi_init() (= S) again which is
Takashi Iwai de1225
protected by spin lock.
Takashi Iwai de1225
This patch re-move it to under spin lock, and solves
Takashi Iwai de1225
1. checking ssi->xxx without spin lock issue.
Takashi Iwai de1225
2. clk setting / device start / device stop race condition.
Takashi Iwai de1225
Takashi Iwai de1225
Reported-by: Linh Phung T. Y. <linh.phung.jy@renesas.com>
Takashi Iwai de1225
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Takashi Iwai de1225
Link: https://lore.kernel.org/r/875z0x1jt5.wl-kuninori.morimoto.gx@renesas.com
Takashi Iwai de1225
Signed-off-by: Mark Brown <broonie@kernel.org>
Takashi Iwai de1225
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai de1225
Takashi Iwai de1225
---
Takashi Iwai de1225
 sound/soc/sh/rcar/ssi.c | 14 +++++---------
Takashi Iwai de1225
 1 file changed, 5 insertions(+), 9 deletions(-)
Takashi Iwai de1225
Takashi Iwai de1225
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
Takashi Iwai de1225
index d071cec25f71..048d53566127 100644
Takashi Iwai de1225
--- a/sound/soc/sh/rcar/ssi.c
Takashi Iwai de1225
+++ b/sound/soc/sh/rcar/ssi.c
Takashi Iwai de1225
@@ -506,10 +506,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
Takashi Iwai de1225
 			 struct rsnd_priv *priv)
Takashi Iwai de1225
 {
Takashi Iwai de1225
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
Takashi Iwai de1225
+	int ret;
Takashi Iwai de1225
 
Takashi Iwai de1225
 	if (!rsnd_ssi_is_run_mods(mod, io))
Takashi Iwai de1225
 		return 0;
Takashi Iwai de1225
 
Takashi Iwai de1225
+	ret = rsnd_ssi_master_clk_start(mod, io);
Takashi Iwai de1225
+	if (ret < 0)
Takashi Iwai de1225
+		return ret;
Takashi Iwai de1225
+
Takashi Iwai de1225
 	ssi->usrcnt++;
Takashi Iwai de1225
 
Takashi Iwai de1225
 	rsnd_mod_power_on(mod);
Takashi Iwai de1225
@@ -1060,13 +1065,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
Takashi Iwai de1225
 	return 0;
Takashi Iwai de1225
 }
Takashi Iwai de1225
 
Takashi Iwai de1225
-static int rsnd_ssi_prepare(struct rsnd_mod *mod,
Takashi Iwai de1225
-			    struct rsnd_dai_stream *io,
Takashi Iwai de1225
-			    struct rsnd_priv *priv)
Takashi Iwai de1225
-{
Takashi Iwai de1225
-	return rsnd_ssi_master_clk_start(mod, io);
Takashi Iwai de1225
-}
Takashi Iwai de1225
-
Takashi Iwai de1225
 static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
Takashi Iwai de1225
 	.name		= SSI_NAME,
Takashi Iwai de1225
 	.probe		= rsnd_ssi_common_probe,
Takashi Iwai de1225
@@ -1079,7 +1077,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
Takashi Iwai de1225
 	.pointer	= rsnd_ssi_pio_pointer,
Takashi Iwai de1225
 	.pcm_new	= rsnd_ssi_pcm_new,
Takashi Iwai de1225
 	.hw_params	= rsnd_ssi_hw_params,
Takashi Iwai de1225
-	.prepare	= rsnd_ssi_prepare,
Takashi Iwai de1225
 	.get_status	= rsnd_ssi_get_status,
Takashi Iwai de1225
 };
Takashi Iwai de1225
 
Takashi Iwai de1225
@@ -1166,7 +1163,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
Takashi Iwai de1225
 	.pcm_new	= rsnd_ssi_pcm_new,
Takashi Iwai de1225
 	.fallback	= rsnd_ssi_fallback,
Takashi Iwai de1225
 	.hw_params	= rsnd_ssi_hw_params,
Takashi Iwai de1225
-	.prepare	= rsnd_ssi_prepare,
Takashi Iwai de1225
 	.get_status	= rsnd_ssi_get_status,
Takashi Iwai de1225
 };
Takashi Iwai de1225
 
Takashi Iwai de1225
-- 
Takashi Iwai de1225
2.26.2
Takashi Iwai de1225