Skip to content

Commit

Permalink
ALSA: usb-audio: Fix deadlocks at resuming
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Takashi Iwai committed May 2, 2014
1 parent 1c53e72 commit 1ee23fe
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 2 deletions.
7 changes: 5 additions & 2 deletions sound/usb/card.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions sound/usb/usbaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down

0 comments on commit 1ee23fe

Please sign in to comment.