mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
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>
This commit is contained in:
parent
1c53e7253e
commit
1ee23fe07e
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user