aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIoan-Adrian Ratiu <adi@adirat.com>2017-01-04 17:37:46 -0500
committerTakashi Iwai <tiwai@suse.de>2017-01-05 01:35:00 -0500
commit1d0f953086f090a022f2c0e1448300c15372db46 (patch)
tree96e89154873d3b08b73e18d717e33631cb050f67
parentc7efff9284dfde95a11aaa811c9d8ec8167f0f6e (diff)
ALSA: usb-audio: Fix irq/process data synchronization
Commit 16200948d83 ("ALSA: usb-audio: Fix race at stopping the stream") was incomplete causing another more severe kernel panic, so it got reverted. This fixes both the original problem and its fallout kernel race/crash. The original fix is to move the endpoint member NULL clearing logic inside wait_clear_urbs() so the irq triggering the urb completion doesn't call retire_capture/playback_urb() after the NULL clearing and generate a panic. However this creates a new race between snd_usb_endpoint_start()'s call to wait_clear_urbs() and the irq urb completion handler which again calls retire_capture/playback_urb() leading to a new NULL dereference. We keep the EP deactivation code in snd_usb_endpoint_start() because removing it will break the EP reference counting (see [1] [2] for info), however we don't need the "can_sleep" mechanism anymore because a new function was introduced (snd_usb_endpoint_sync_pending_stop()) which synchronizes pending stops and gets called inside the pcm prepare callback. It also makes sense to remove can_sleep because it was also removed from deactivate_urbs() signature in [3] so we benefit from more simplification. [1] commit 015618b90 ("ALSA: snd-usb: Fix URB cancellation at stream start") [2] commit e9ba389c5 ("ALSA: usb-audio: Fix scheduling-while-atomic bug in PCM capture stream") [3] commit ccc1696d5 ("ALSA: usb-audio: simplify endpoint deactivation code") Fixes: f8114f8583bb ("Revert "ALSA: usb-audio: Fix race at stopping the stream"") Signed-off-by: Ioan-Adrian Ratiu <adi@adirat.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/endpoint.c17
-rw-r--r--sound/usb/endpoint.h2
-rw-r--r--sound/usb/pcm.c10
3 files changed, 13 insertions, 16 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 15d1d5c63c3c..2f0ea70a998c 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -534,6 +534,11 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
534 alive, ep->ep_num); 534 alive, ep->ep_num);
535 clear_bit(EP_FLAG_STOPPING, &ep->flags); 535 clear_bit(EP_FLAG_STOPPING, &ep->flags);
536 536
537 ep->data_subs = NULL;
538 ep->sync_slave = NULL;
539 ep->retire_data_urb = NULL;
540 ep->prepare_data_urb = NULL;
541
537 return 0; 542 return 0;
538} 543}
539 544
@@ -912,9 +917,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
912/** 917/**
913 * snd_usb_endpoint_start: start an snd_usb_endpoint 918 * snd_usb_endpoint_start: start an snd_usb_endpoint
914 * 919 *
915 * @ep: the endpoint to start 920 * @ep: the endpoint to start
916 * @can_sleep: flag indicating whether the operation is executed in
917 * non-atomic context
918 * 921 *
919 * A call to this function will increment the use count of the endpoint. 922 * A call to this function will increment the use count of the endpoint.
920 * In case it is not already running, the URBs for this endpoint will be 923 * In case it is not already running, the URBs for this endpoint will be
@@ -924,7 +927,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
924 * 927 *
925 * Returns an error if the URB submission failed, 0 in all other cases. 928 * Returns an error if the URB submission failed, 0 in all other cases.
926 */ 929 */
927int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) 930int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
928{ 931{
929 int err; 932 int err;
930 unsigned int i; 933 unsigned int i;
@@ -938,8 +941,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
938 941
939 /* just to be sure */ 942 /* just to be sure */
940 deactivate_urbs(ep, false); 943 deactivate_urbs(ep, false);
941 if (can_sleep)
942 wait_clear_urbs(ep);
943 944
944 ep->active_mask = 0; 945 ep->active_mask = 0;
945 ep->unlink_mask = 0; 946 ep->unlink_mask = 0;
@@ -1020,10 +1021,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
1020 1021
1021 if (--ep->use_count == 0) { 1022 if (--ep->use_count == 0) {
1022 deactivate_urbs(ep, false); 1023 deactivate_urbs(ep, false);
1023 ep->data_subs = NULL;
1024 ep->sync_slave = NULL;
1025 ep->retire_data_urb = NULL;
1026 ep->prepare_data_urb = NULL;
1027 set_bit(EP_FLAG_STOPPING, &ep->flags); 1024 set_bit(EP_FLAG_STOPPING, &ep->flags);
1028 } 1025 }
1029} 1026}
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 6428392d8f62..584f295d7c77 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -18,7 +18,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
18 struct audioformat *fmt, 18 struct audioformat *fmt,
19 struct snd_usb_endpoint *sync_ep); 19 struct snd_usb_endpoint *sync_ep);
20 20
21int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep); 21int snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
22void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); 22void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
23void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); 23void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
24int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); 24int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 34c6d4f2c0b6..9aa5b1855481 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -218,7 +218,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
218 } 218 }
219} 219}
220 220
221static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) 221static int start_endpoints(struct snd_usb_substream *subs)
222{ 222{
223 int err; 223 int err;
224 224
@@ -231,7 +231,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
231 dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep); 231 dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep);
232 232
233 ep->data_subs = subs; 233 ep->data_subs = subs;
234 err = snd_usb_endpoint_start(ep, can_sleep); 234 err = snd_usb_endpoint_start(ep);
235 if (err < 0) { 235 if (err < 0) {
236 clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); 236 clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
237 return err; 237 return err;
@@ -260,7 +260,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
260 dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep); 260 dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
261 261
262 ep->sync_slave = subs->data_endpoint; 262 ep->sync_slave = subs->data_endpoint;
263 err = snd_usb_endpoint_start(ep, can_sleep); 263 err = snd_usb_endpoint_start(ep);
264 if (err < 0) { 264 if (err < 0) {
265 clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); 265 clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
266 return err; 266 return err;
@@ -850,7 +850,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
850 /* for playback, submit the URBs now; otherwise, the first hwptr_done 850 /* for playback, submit the URBs now; otherwise, the first hwptr_done
851 * updates for all URBs would happen at the same time when starting */ 851 * updates for all URBs would happen at the same time when starting */
852 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) 852 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
853 ret = start_endpoints(subs, true); 853 ret = start_endpoints(subs);
854 854
855 unlock: 855 unlock:
856 snd_usb_unlock_shutdown(subs->stream->chip); 856 snd_usb_unlock_shutdown(subs->stream->chip);
@@ -1666,7 +1666,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
1666 1666
1667 switch (cmd) { 1667 switch (cmd) {
1668 case SNDRV_PCM_TRIGGER_START: 1668 case SNDRV_PCM_TRIGGER_START:
1669 err = start_endpoints(subs, false); 1669 err = start_endpoints(subs);
1670 if (err < 0) 1670 if (err < 0)
1671 return err; 1671 return err;
1672 1672