aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/card.h
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2021-09-29 10:08:37 +0200
committerTakashi Iwai <tiwai@suse.de>2021-09-30 13:55:19 +0200
commit86a42ad07905110f82648853c0ea3434b4eab173 (patch)
tree4803a5fb707e50d2a269ae9efc74703fa9e95e94 /sound/usb/card.h
parentALSA: usb-audio: Restrict rates for the shared clocks (diff)
downloadlinux-dev-86a42ad07905110f82648853c0ea3434b4eab173.tar.xz
linux-dev-86a42ad07905110f82648853c0ea3434b4eab173.zip
ALSA: usb-audio: Fix possible race at sync of urb completions
USB-audio driver tries to sync with the clear of all pending URBs in wait_clear_urbs(), and it waits for all bits in active_mask getting cleared. This works fine for the normal operations, but when a stream is managed in the implicit feedback mode, there is still a very thin race window: namely, in snd_complete_usb(), the active_mask bit for the current URB is once cleared before re-submitted in queue_pending_output_urbs(). If wait_clear_urbs() is called during that period, it may pass the test and go forward even though there may be a still pending URB. For covering it, this patch adds a new counter to each endpoint to keep the number of in-flight URBs, and changes wait_clear_urbs() checking this number instead. The counter is decremented at the end of URB complete, hence the reference is kept as long as the URB complete is in process. Link: https://lore.kernel.org/r/20210929080844.11583-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/card.h')
-rw-r--r--sound/usb/card.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 3329ce710cb9..746a765b2437 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -97,6 +97,7 @@ struct snd_usb_endpoint {
unsigned int nominal_queue_size; /* total buffer sizes in URBs */
unsigned long active_mask; /* bitmask of active urbs */
unsigned long unlink_mask; /* bitmask of unlinked urbs */
+ atomic_t submitted_urbs; /* currently submitted urbs */
char *syncbuf; /* sync buffer for all sync URBs */
dma_addr_t sync_dma; /* DMA address of syncbuf */