Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ee23fe0 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarBryan Quigley <gquigs@gmail.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1c53e725
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -651,7 +651,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
	int err = -ENODEV;
	int err = -ENODEV;


	down_read(&chip->shutdown_rwsem);
	down_read(&chip->shutdown_rwsem);
	if (chip->probing)
	if (chip->probing && chip->in_pm)
		err = 0;
		err = 0;
	else if (!chip->shutdown)
	else if (!chip->shutdown)
		err = usb_autopm_get_interface(chip->pm_intf);
		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)
void snd_usb_autosuspend(struct snd_usb_audio *chip)
{
{
	down_read(&chip->shutdown_rwsem);
	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);
		usb_autopm_put_interface(chip->pm_intf);
	up_read(&chip->shutdown_rwsem);
	up_read(&chip->shutdown_rwsem);
}
}
@@ -712,6 +712,8 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
		return 0;
		return 0;
	if (--chip->num_suspended_intf)
	if (--chip->num_suspended_intf)
		return 0;
		return 0;

	chip->in_pm = 1;
	/*
	/*
	 * ALSA leaves material resumption to user space
	 * ALSA leaves material resumption to user space
	 * we just notify and restart the mixers
	 * 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;
	chip->autosuspended = 0;


err_out:
err_out:
	chip->in_pm = 0;
	return err;
	return err;
}
}


+1 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ struct snd_usb_audio {
	struct rw_semaphore shutdown_rwsem;
	struct rw_semaphore shutdown_rwsem;
	unsigned int shutdown:1;
	unsigned int shutdown:1;
	unsigned int probing:1;
	unsigned int probing:1;
	unsigned int in_pm:1;
	unsigned int autosuspended:1;	
	unsigned int autosuspended:1;	
	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */