[alsa-devel] [PATCH] ALSA: usb - prevent kernel panic on disconnect

Pierre-Louis Bossart bossart.nospam at gmail.com
Wed Feb 9 20:13:24 CET 2011


Fix 100% reproducible kernel panic when a USB audio device is
disconnected during playback. When the PCM substream is NULL, any
dereference causes a kernel panic. This isn't a recent problem, the crash
happened with a 2.6.35 kernel as well

Note that this is only a work-around, it does not address the
root cause of this inconsistency between urbs and PCM states. The
dmesg below shows two calls to snd_urb_complete, the substream is
NULL and the state is either running or stopped. This doesn't make
any sense.

Thanks to Sarah Sharp <sarah.a.sharp at linux.intel.com> for her
help.

usb 6-1: USB disconnect, address 16
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:492: frame 0 active: -84
ALSA urb.c:197: cannot submit urb (err = -19)
ALSA urb.c:186: NULL substream (subs->running 1) <- How is this possible?
ALSA urb.c:186: NULL substream (subs->running 0)

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at intel.com>
---
 usb/urb.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/usb/urb.c b/usb/urb.c
index e184349..1a264c2 100644
--- a/usb/urb.c
+++ b/usb/urb.c
@@ -170,6 +170,12 @@ static void snd_complete_urb(struct urb *urb)
 	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
 	int err = 0;
 
+        if (substream == NULL) {
+                snd_printd(KERN_ERR "NULL substream (subs->running %d)\n", subs->running);
+                clear_bit(ctx->index, &subs->active_mask);
+                return;
+        }
+
 	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
 	    !subs->running || /* can be stopped during retire callback */
 	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
@@ -193,6 +199,12 @@ static void snd_complete_sync_urb(struct urb *urb)
 	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
 	int err = 0;
 
+        if (substream == NULL) {
+                snd_printd(KERN_ERR "NULL substream (subs->running %d)\n", subs->running);
+                clear_bit(ctx->index + 16, &subs->active_mask);
+                return;
+        }
+
 	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
 	    !subs->running || /* can be stopped during retire callback */
 	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
-- 
1.7.4



More information about the Alsa-devel mailing list