4040634
At Thu, 08 Nov 2012 08:31:35 +0100,
4040634
Daniel Mack wrote:
4040634
(snip)
4040634
> >> We can't simply stop both endpoints in the prepare callback.
4040634
> > 
4040634
> > The new function doesn't stop the stream by itself but it just syncs
4040634
> > if the stream is being stopped beforehand.  So, it's safe to call it
4040634
> > there.
4040634
> > 
4040634
> > Maybe the name was confusing.  It should have been like
4040634
> > snd_usb_endpoint_sync_pending_stop() or such.
4040634
> 
4040634
> Ah, right. I was errornously looking closer to Alan's patch but then
4040634
> replied to yours. Alright then - thanks for explaining :)
4040634
4040634
OK, thanks for checking.
4040634
4040634
FWIW, below is the patch I applied now to for-linus branch.
4040634
Renamed the function, added the comment and put NULL check to the
4040634
function to simplify.
4040634
4040634
4040634
Takashi
4040634
4040634
---
4040634
From: Takashi Iwai <tiwai@suse.de>
4040634
Subject: [PATCH] ALSA: usb-audio: Fix crash at re-preparing the PCM stream
4040634
4040634
There are bug reports of a crash with USB-audio devices when PCM
4040634
prepare is performed immediately after the stream is stopped via
4040634
trigger callback.  It turned out that the problem is that we don't
4040634
wait until all URBs are killed.
4040634
4040634
This patch adds a new function to synchronize the pending stop
4040634
operation on an endpoint, and calls in the prepare callback for
4040634
avoiding the crash above.
4040634
4040634
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=49181
4040634
4040634
Reported-and-tested-by: Artem S. Tashkinov <t.artem@lycos.com>
4040634
Cc: <stable@vger.kernel.org> [v3.6]
4040634
Signed-off-by: Takashi Iwai <tiwai@suse.de>
4040634
---
4040634
 sound/usb/endpoint.c | 13 +++++++++++++
4040634
 sound/usb/endpoint.h |  1 +
4040634
 sound/usb/pcm.c      |  3 +++
4040634
 3 files changed, 17 insertions(+)
4040634
4040634
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
4040634
index 7f78c6d..34de6f2 100644
4040634
--- a/sound/usb/endpoint.c
4040634
+++ b/sound/usb/endpoint.c
4040634
@@ -35,6 +35,7 @@
4040634
 
4040634
 #define EP_FLAG_ACTIVATED	0
4040634
 #define EP_FLAG_RUNNING		1
4040634
+#define EP_FLAG_STOPPING	2
4040634
 
4040634
 /*
4040634
  * snd_usb_endpoint is a model that abstracts everything related to an
4040634
@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
4040634
 	if (alive)
4040634
 		snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
4040634
 					alive, ep->ep_num);
4040634
+	clear_bit(EP_FLAG_STOPPING, &ep->flags);
4040634
 
4040634
 	return 0;
4040634
 }
4040634
 
4040634
+/* sync the pending stop operation;
4040634
+ * this function itself doesn't trigger the stop operation
4040634
+ */
4040634
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
4040634
+{
4040634
+	if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags))
4040634
+		wait_clear_urbs(ep);
4040634
+}
4040634
+
4040634
 /*
4040634
  * unlink active urbs.
4040634
  */
4040634
@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
4040634
 
4040634
 		if (wait)
4040634
 			wait_clear_urbs(ep);
4040634
+		else
4040634
+			set_bit(EP_FLAG_STOPPING, &ep->flags);
4040634
 	}
4040634
 }
4040634
 
4040634
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
4040634
index 6376ccf..3d4c970 100644
4040634
--- a/sound/usb/endpoint.h
4040634
+++ b/sound/usb/endpoint.h
4040634
@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
4040634
 int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
4040634
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
4040634
 			   int force, int can_sleep, int wait);
4040634
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
4040634
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
4040634
 int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
4040634
 void snd_usb_endpoint_free(struct list_head *head);
4040634
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
4040634
index 37428f7..5c12a3f 100644
4040634
--- a/sound/usb/pcm.c
4040634
+++ b/sound/usb/pcm.c
4040634
@@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
4040634
	if (snd_BUG_ON(!subs->data_endpoint))
4040634
		return -EIO;
4040634
 
4040634
+	snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
4040634
+	snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
4040634
+
4040634
	/* some unit conversions in runtime */
4040634
	subs->data_endpoint->maxframesize =
4040634
		bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);
4040634
-- 
4040634
1.8.0
4040634
4040634
4040634
--
4040634
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
4040634
the body of a message to majordomo@vger.kernel.org
4040634
More majordomo info at  http://vger.kernel.org/majordomo-info.html
4040634
Please read the FAQ at  http://www.tux.org/lkml/