Skip to content

Commit 56e4563

Browse files
committed
ASoC: hdac_hda: fix deadlock after PCM open error
Commit 202bac2 ("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: 202bac2 ("ASoC: soc-dai: revert all changes to DAI startup/shutdown sequence") BugLink: #2159 Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 01ec165 commit 56e4563

1 file changed

Lines changed: 1 addition & 6 deletions

File tree

sound/soc/codecs/hdac_hda.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
289289
struct hdac_hda_priv *hda_pvt;
290290
struct hda_pcm_stream *hda_stream;
291291
struct hda_pcm *pcm;
292-
int ret;
293292

294293
hda_pvt = snd_soc_component_get_drvdata(component);
295294
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,
300299

301300
hda_stream = &pcm->stream[substream->stream];
302301

303-
ret = hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream);
304-
if (ret < 0)
305-
snd_hda_codec_pcm_put(pcm);
306-
307-
return ret;
302+
return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream);
308303
}
309304

310305
static void hdac_hda_dai_close(struct snd_pcm_substream *substream,

0 commit comments

Comments
 (0)