summaryrefslogtreecommitdiff
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2023-03-20 15:28:38 +0100
committerTakashi Iwai <tiwai@suse.de>2023-03-21 07:10:43 +0100
commit8c721c53dda512fdd48eb24d6d99e56deee57898 (patch)
tree90459ca3b092f0fbd4d0051b53b028b54bead5b8 /sound/usb/pcm.c
parentb871cb971c683f7f212e7ca3c9a6709a75785116 (diff)
ALSA: usb-audio: Fix recursive locking at XRUN during syncing
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>
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index d959da7a1afb..eec5232f9fb2 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1639,7 +1639,7 @@ static int snd_usb_pcm_playback_ack(struct snd_pcm_substream *substream)
* outputs here
*/
if (!ep->active_mask)
- snd_usb_queue_pending_output_urbs(ep, true);
+ return snd_usb_queue_pending_output_urbs(ep, true);
return 0;
}