summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-05-02 18:17:06 +0200
committerJiri Slaby <jslaby@suse.cz>2015-08-04 16:51:53 +0200
commit8986a67aa7da0e7c6dc8e595f6aa8401b655d02d (patch)
tree797b1e087b1fd2c407eecc3f207037ea0b6b6552 /sound
parent708183150dad5f6a2bdde67e8292954012782171 (diff)
ALSA: usb-audio: Fix deadlocks at resuming
commit 1ee23fe07ee83a38ecee927e701f762888ada942 upstream. 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> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/card.c7
-rw-r--r--sound/usb/usbaudio.h1
2 files changed, 6 insertions, 2 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index ca55e033cf9d..bc5795f342a7 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -661,7 +661,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);
@@ -673,7 +673,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);
}
@@ -722,6 +722,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
@@ -737,6 +739,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
chip->autosuspended = 0;
err_out:
+ chip->in_pm = 0;
return err;
}
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index caabe9b3af49..58d4ef14ff31 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -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 */