From: 강신형 s47.kang@samsung.com
[ 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@samsung.com Link: https://lore.kernel.org/r/016401d90ac4$7b6848c0$7238da40$@samsung.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- 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 870f13e1d389c..7bce5088b4554 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -149,6 +149,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; @@ -184,7 +186,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);
@@ -215,7 +216,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;
@@ -234,6 +234,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); @@ -409,8 +411,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: