summary refs log tree commit diff
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2023-03-20 15:28:38 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-04-06 12:10:43 +0200
commite39afd6095a59ddecfd44422241db7605c8846e7 (patch)
treecd4d29fb07621c8202f95aea962f7aa31f64da76 /sound/core
parent2cdbcff99f15db86a10672fb220379a1ae46ccae (diff)
downloadlinux-e39afd6095a59ddecfd44422241db7605c8846e7.tar.gz
ALSA: usb-audio: Fix recursive locking at XRUN during syncing
[ Upstream commit 8c721c53dda512fdd48eb24d6d99e56deee57898 ]

The recent support of low latency playback in USB-audio driver made
the snd_usb_queue_pending_output_urbs() function to be called via PCM
ack ops.  In the new code path, the function is performed already in
the PCM stream lock.  The problem is that, when an XRUN is detected,
the function calls snd_pcm_xrun() to notify, but snd_pcm_xrun() is
supposed to be called only outside the stream lock.  As a result, it
leads to a deadlock of PCM stream locking.

For avoiding such a recursive locking, this patch adds an additional
check to the code paths in PCM core that call the ack callback; now it
checks the error code from the callback, and if it's -EPIPE, the XRUN
is handled in the PCM core side gracefully.  Along with it, the
USB-audio driver code is changed to follow that, i.e. -EPIPE is
returned instead of the explicit snd_pcm_xrun() call when the function
is performed already in the stream lock.

Fixes: d5f871f89e21 ("ALSA: usb-audio: Improved lowlatency playback support")
Reported-and-tested-by: John Keeping <john@metanate.com>
Link: https://lore.kernel.org/r/20230317195128.3911155-1-john@metanate.com
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Reviewed-by; Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20230320142838.494-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 8b6aeb8a78f7..02fd65993e7e 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2155,6 +2155,8 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
 		ret = substream->ops->ack(substream);
 		if (ret < 0) {
 			runtime->control->appl_ptr = old_appl_ptr;
+			if (ret == -EPIPE)
+				__snd_pcm_xrun(substream);
 			return ret;
 		}
 	}