]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ALSA: usb-audio: Fix deadlocks at resuming
authorTakashi Iwai <tiwai@suse.de>
Fri, 2 May 2014 16:17:06 +0000 (18:17 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 2 May 2014 16:17:06 +0000 (18:17 +0200)
The recent addition of the USB audio mixer suspend/resume may lead to
deadlocks when the driver tries to call usb_autopm_get_interface()
recursively, since the function tries to sync with the finish of the
other calls.  For avoiding it, introduce a flag indicating the resume
operation and avoids the recursive usb_autopm_get_interface() calls
during the resume.

Reported-and-tested-by: Bryan Quigley <gquigs@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/card.c
sound/usb/usbaudio.h

index e769d39777164f8d898991f3b3d7b005102c3bf8..c3b5b7dca1c3a8fd4b771512c841bb32e27b5554 100644 (file)
@@ -651,7 +651,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
        int err = -ENODEV;
 
        down_read(&chip->shutdown_rwsem);
-       if (chip->probing)
+       if (chip->probing && chip->in_pm)
                err = 0;
        else if (!chip->shutdown)
                err = usb_autopm_get_interface(chip->pm_intf);
@@ -663,7 +663,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
 void snd_usb_autosuspend(struct snd_usb_audio *chip)
 {
        down_read(&chip->shutdown_rwsem);
-       if (!chip->shutdown && !chip->probing)
+       if (!chip->shutdown && !chip->probing && !chip->in_pm)
                usb_autopm_put_interface(chip->pm_intf);
        up_read(&chip->shutdown_rwsem);
 }
@@ -712,6 +712,8 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
                return 0;
        if (--chip->num_suspended_intf)
                return 0;
+
+       chip->in_pm = 1;
        /*
         * ALSA leaves material resumption to user space
         * we just notify and restart the mixers
@@ -727,6 +729,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
        chip->autosuspended = 0;
 
 err_out:
+       chip->in_pm = 0;
        return err;
 }
 
index 25c4c7e217de603c1f02c5c714833e6f29d92c3b..91d0380431b4f79f1e209cd973b7f44152caa494 100644 (file)
@@ -40,6 +40,7 @@ struct snd_usb_audio {
        struct rw_semaphore shutdown_rwsem;
        unsigned int shutdown:1;
        unsigned int probing:1;
+       unsigned int in_pm:1;
        unsigned int autosuspended:1;   
        unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */