[PATCH AUTOSEL 5.15 13/25] ASoC: soc-compress: Reposition and add pcm_mutex

From: Sasha Levin
Date: Sun Feb 26 2023 - 21:44:22 EST


From: 강신형 <s47.kang@xxxxxxxxxxx>

[ Upstream commit aa9ff6a4955fdba02b54fbc4386db876603703b7 ]

If panic_on_warn is set and compress stream(DPCM) is started,
then kernel panic occurred because card->pcm_mutex isn't held appropriately.
In the following functions, warning were issued at this line
"snd_soc_dpcm_mutex_assert_held".

static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream)
{
...
snd_soc_dpcm_mutex_assert_held(fe);
...
}

void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
{
...
snd_soc_dpcm_mutex_assert_held(fe);
...
}

void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
int stream, int action)
{
...
snd_soc_dpcm_mutex_assert_held(rtd);
...
}

int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
int event)
{
...
snd_soc_dpcm_mutex_assert_held(fe);
...
}

These functions are called by soc_compr_set_params_fe, soc_compr_open_fe
and soc_compr_free_fe
without pcm_mutex locking. And this is call stack.

[ 414.527841][ T2179] pc : dpcm_process_paths+0x5a4/0x750
[ 414.527848][ T2179] lr : dpcm_process_paths+0x37c/0x750
[ 414.527945][ T2179] Call trace:
[ 414.527949][ T2179] dpcm_process_paths+0x5a4/0x750
[ 414.527955][ T2179] soc_compr_open_fe+0xb0/0x2cc
[ 414.527972][ T2179] snd_compr_open+0x180/0x248
[ 414.527981][ T2179] snd_open+0x15c/0x194
[ 414.528003][ T2179] chrdev_open+0x1b0/0x220
[ 414.528023][ T2179] do_dentry_open+0x30c/0x594
[ 414.528045][ T2179] vfs_open+0x34/0x44
[ 414.528053][ T2179] path_openat+0x914/0xb08
[ 414.528062][ T2179] do_filp_open+0xc0/0x170
[ 414.528068][ T2179] do_sys_openat2+0x94/0x18c
[ 414.528076][ T2179] __arm64_sys_openat+0x78/0xa4
[ 414.528084][ T2179] invoke_syscall+0x48/0x10c
[ 414.528094][ T2179] el0_svc_common+0xbc/0x104
[ 414.528099][ T2179] do_el0_svc+0x34/0xd8
[ 414.528103][ T2179] el0_svc+0x34/0xc4
[ 414.528125][ T2179] el0t_64_sync_handler+0x8c/0xfc
[ 414.528133][ T2179] el0t_64_sync+0x1a0/0x1a4
[ 414.528142][ T2179] Kernel panic - not syncing: panic_on_warn set ...

So, I reposition and add pcm_mutex to resolve lockdep error.

Signed-off-by: Shinhyung Kang <s47.kang@xxxxxxxxxxx>
Link: https://lore.kernel.org/r/016401d90ac4$7b6848c0$7238da40$@samsung.com
Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
sound/soc/soc-compress.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 2050728063a15..9146bec146c1e 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -116,6 +116,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
if (ret < 0)
goto be_err;

+ mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass);
+
/* calculate valid and active FE <-> BE dpcms */
dpcm_process_paths(fe, stream, &list, 1);
fe->dpcm[stream].runtime = fe_substream->runtime;
@@ -151,7 +153,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;

- mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass);
snd_soc_runtime_activate(fe, stream);
mutex_unlock(&fe->card->pcm_mutex);

@@ -182,7 +183,6 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)

mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass);
snd_soc_runtime_deactivate(fe, stream);
- mutex_unlock(&fe->card->pcm_mutex);

fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;

@@ -201,6 +201,8 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)

dpcm_be_disconnect(fe, stream);

+ mutex_unlock(&fe->card->pcm_mutex);
+
fe->dpcm[stream].runtime = NULL;

snd_soc_link_compr_shutdown(cstream, 0);
@@ -376,8 +378,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
ret = snd_soc_link_compr_set_params(cstream);
if (ret < 0)
goto out;
-
+ mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass);
dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
+ mutex_unlock(&fe->card->pcm_mutex);
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;

out:
--
2.39.0