summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/hdac_hda.c
diff options
context:
space:
mode:
authorKai Vehmanen <kai.vehmanen@linux.intel.com>2020-07-17 13:19:50 +0300
committerMark Brown <broonie@kernel.org>2020-07-22 14:31:58 +0100
commit06f07e2365378d51eddd0b5bf23506e1237662b0 (patch)
tree4cb9185ad4aed7ad876ed5cefbc806848f4f0068 /sound/soc/codecs/hdac_hda.c
parentc3ec8ac82105e9589dcd72636b6fd114db690d55 (diff)
downloadlinux-06f07e2365378d51eddd0b5bf23506e1237662b0.tar.bz2
ASoC: hdac_hda: fix deadlock after PCM open error
Commit 5bd70440cb0a ("ASoC: soc-dai: revert all changes to DAI startup/shutdown sequence"), introduced a slight change of semantics to DAI startup/shutdown. If startup() returns an error, shutdown() is now called for the DAI. This causes a deadlock in hdac_hda which issues a call to snd_hda_codec_pcm_put() in case open fails. Upon error, soc_pcm_open() will call shutdown(), and pcm_put() ends up getting called twice. Result is a deadlock on pcm->open_mutex, as snd_device_free() gets called from within snd_pcm_open(). Typical task backtrace looks like this: [ 334.244627] snd_pcm_dev_disconnect+0x49/0x340 [snd_pcm] [ 334.244634] __snd_device_disconnect.part.0+0x2c/0x50 [snd] [ 334.244640] __snd_device_free+0x7f/0xc0 [snd] [ 334.244650] snd_hda_codec_pcm_put+0x87/0x120 [snd_hda_codec] [ 334.244660] soc_pcm_open+0x6a0/0xbe0 [snd_soc_core] [ 334.244676] ? dpcm_add_paths.isra.0+0x491/0x590 [snd_soc_core] [ 334.244679] ? kfree+0x9a/0x230 [ 334.244686] dpcm_be_dai_startup+0x255/0x300 [snd_soc_core] [ 334.244695] dpcm_fe_dai_open+0x20e/0xf30 [snd_soc_core] [ 334.244701] ? snd_pcm_hw_rule_muldivk+0x110/0x110 [snd_pcm] [ 334.244709] ? dpcm_be_dai_startup+0x300/0x300 [snd_soc_core] [ 334.244714] ? snd_pcm_attach_substream+0x3c4/0x540 [snd_pcm] [ 334.244719] snd_pcm_open_substream+0x69a/0xb60 [snd_pcm] [ 334.244729] ? snd_pcm_release_substream+0x30/0x30 [snd_pcm] [ 334.244732] ? __mutex_lock_slowpath+0x10/0x10 [ 334.244736] snd_pcm_open+0x1b3/0x3c0 [snd_pcm] Fixes: 5bd70440cb0a ("ASoC: soc-dai: revert all changes to DAI startup/shutdown sequence") Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@linux.intel.com> BugLink: https://github.com/thesofproject/linux/issues/2159 Link: https://lore.kernel.org/r/20200717101950.3885187-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/hdac_hda.c')
-rw-r--r--sound/soc/codecs/hdac_hda.c7
1 files changed, 1 insertions, 6 deletions
diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c
index 74574b9180a5..49e6f23fc766 100644
--- a/sound/soc/codecs/hdac_hda.c
+++ b/sound/soc/codecs/hdac_hda.c
@@ -289,7 +289,6 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
struct hdac_hda_priv *hda_pvt;
struct hda_pcm_stream *hda_stream;
struct hda_pcm *pcm;
- int ret;
hda_pvt = snd_soc_component_get_drvdata(component);
pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
@@ -300,11 +299,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
hda_stream = &pcm->stream[substream->stream];
- ret = hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream);
- if (ret < 0)
- snd_hda_codec_pcm_put(pcm);
-
- return ret;
+ return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream);
}
static void hdac_hda_dai_close(struct snd_pcm_substream *substream,