Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95926035 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: emu10k1: Fix deadlock in synth voice lookup



The emu10k1 voice allocator takes voice_lock spinlock.  When there is
no empty stream available, it tries to release a voice used by synth,
and calls get_synth_voice.  The callback function,
snd_emu10k1_synth_get_voice(), however, also takes the voice_lock,
thus it deadlocks.

The fix is simply removing the voice_lock holds in
snd_emu10k1_synth_get_voice(), as this is always called in the
spinlock context.

Reported-and-tested-by: default avatarArthur Marsh <arthur.marsh@internode.on.net>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 811deede
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ snd_emu10k1_ops_setup(struct snd_emux *emux)
 * get more voice for pcm
 *
 * terminate most inactive voice and give it as a pcm voice.
 *
 * voice_lock is already held.
 */
int
snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
@@ -92,12 +94,10 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
	struct snd_emux *emu;
	struct snd_emux_voice *vp;
	struct best_voice best[V_END];
	unsigned long flags;
	int i;

	emu = hw->synth;

	spin_lock_irqsave(&emu->voice_lock, flags);
	lookup_voices(emu, hw, best, 1); /* no OFF voices */
	for (i = 0; i < V_END; i++) {
		if (best[i].voice >= 0) {
@@ -113,11 +113,9 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
			vp->emu->num_voices--;
			vp->ch = -1;
			vp->state = SNDRV_EMUX_ST_OFF;
			spin_unlock_irqrestore(&emu->voice_lock, flags);
			return ch;
		}
	}
	spin_unlock_irqrestore(&emu->voice_lock, flags);

	/* not found */
	return -ENOMEM;