[3.5.y.z,extended,stable] Patch "ALSA: usb-audio: Fix mutex deadlock at disconnection" has been added to staging queue

Submitted by Herton Ronaldo Krzesinski on Dec. 7, 2012, 4:05 p.m.


Message ID 1354896345-22832-1-git-send-email-herton.krzesinski@canonical.com
State New
Headers show

Commit Message

Herton Ronaldo Krzesinski Dec. 7, 2012, 4:05 p.m.
This is a note to let you know that I have just added a patch titled

    ALSA: usb-audio: Fix mutex deadlock at disconnection

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:


If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From d3418cabb47e8c754ac2f199d6e9f3efc7b03117 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 13 Nov 2012 11:22:48 +0100
Subject: [PATCH] ALSA: usb-audio: Fix mutex deadlock at disconnection

commit 10e44239f67d0b6fb74006e61a7e883b8075247a upstream.

The recent change for USB-audio disconnection race fixes introduced a
mutex deadlock again.  There is a circular dependency between
chip->shutdown_rwsem and pcm->open_mutex, depicted like below, when a
device is opened during the disconnection operation:

A. snd_usb_audio_disconnect() ->
     card.c::register_mutex ->
       chip->shutdown_rwsem (write) ->
         snd_card_disconnect() ->
           pcm.c::register_mutex ->

B. snd_pcm_open() ->
     pcm->open_mutex ->
       snd_usb_pcm_open() ->
         chip->shutdown_rwsem (read)

Since the chip->shutdown_rwsem protection in the case A is required
only for turning on the chip->shutdown flag and it doesn't have to be
taken for the whole operation, we can reduce its window in

Reported-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
 sound/usb/card.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)


Patch hide | download patch | download mbox

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 486b4a6..b3f5ad4 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -559,9 +559,11 @@  static void snd_usb_audio_disconnect(struct usb_device *dev,

 	card = chip->card;
-	mutex_lock(&register_mutex);
 	chip->shutdown = 1;
+	up_write(&chip->shutdown_rwsem);
+	mutex_lock(&register_mutex);
 	if (chip->num_interfaces <= 0) {
@@ -582,11 +584,9 @@  static void snd_usb_audio_disconnect(struct usb_device *dev,
 		usb_chip[chip->index] = NULL;
-		up_write(&chip->shutdown_rwsem);
 	} else {
-		up_write(&chip->shutdown_rwsem);