[PATCH 3.12 020/123] ALSA: usb-audio: Fix deadlocks at resuming

From: Jiri Slaby
Date: Tue Aug 04 2015 - 11:18:43 EST


From: Takashi Iwai <tiwai@xxxxxxx>

3.12-stable review patch. If anyone has any objections, please let me know.

===============

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@xxxxxxxxx>
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>
---
sound/usb/card.c | 7 +++++--
sound/usb/usbaudio.h | 1 +
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 */

--
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/