[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