From 1c53e7253ed8769a00afa0f06777d731dbe1ba6f Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 2 May 2014 18:14:42 +0200
Subject: ALSA: usb-audio: Save mixer status only once at suspend

The suspend callback of usb-audio driver may be called multiple times
per suspend when multiple USB interfaces are bound to a single sound
card instance.  In such a case, it's superfluous to save the mixer
values multiple times.  This patch fixes it by checking the counter.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'sound/usb/card.c')

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 893d5a1afc3c..e769d3977716 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -695,8 +695,9 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 			chip->autosuspended = 1;
 	}
 
-	list_for_each_entry(mixer, &chip->mixer_list, list)
-		snd_usb_mixer_suspend(mixer);
+	if (chip->num_suspended_intf == 1)
+		list_for_each_entry(mixer, &chip->mixer_list, list)
+			snd_usb_mixer_suspend(mixer);
 
 	return 0;
 }
-- 
cgit v1.2.1


From 1ee23fe07ee83a38ecee927e701f762888ada942 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 2 May 2014 18:17:06 +0200
Subject: ALSA: usb-audio: Fix deadlocks at resuming

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 | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'sound/usb/card.c')

diff --git a/sound/usb/card.c b/sound/usb/card.c
index e769d3977716..c3b5b7dca1c3 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -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;
 }
 
-- 
cgit v1.2.1