From 5a9a8eca7996d5947905f853ab0c6717b4f2b7a0 Mon Sep 17 00:00:00 2001 From: Stephen Barber Date: Thu, 17 Aug 2017 15:17:46 -0700 Subject: ALSA: usb-audio: don't retry snd_usb_ctl_msg after timeout A few calls to snd_usb_ctl_msg wrap the function in a retry loop. In the worst case, the timeout for snd_usb_ctl_msg is 5 seconds, which when retried 10 times (for example, if a device is removed) could cause a probe to hang for ~50 seconds. Example stack trace from 3.14 which triggered a hung task timeout: Call Trace: [] ? inet6_set_link_af.part.35+0x12/0x12 [] schedule+0x6e/0x70 [] schedule_timeout+0xfc/0x13c [] ? rcu_read_unlock_sched_notrace+0x17/0x17 [] __wait_for_common+0x153/0x190 [] ? __wait_for_common+0x153/0x190 [] ? wake_up_state+0x12/0x12 [] wait_for_completion_timeout+0x1d/0x1f [] usb_start_wait_urb+0x93/0xf1 [] usb_control_msg+0xe1/0x11d [] snd_usb_ctl_msg+0x9c/0xf1 [snd_usb_audio] [] snd_usb_mixer_set_ctl_value+0x124/0xab1 [snd_usb_audio] [] snd_usb_mixer_set_ctl_value+0x1c3/0xab1 [snd_usb_audio] [] snd_usb_mixer_set_ctl_value+0x521/0xab1 [snd_usb_audio] [] snd_usb_mixer_add_control+0x36a/0x1264 [snd_usb_audio] [] snd_usb_mixer_add_control+0x805/0x1264 [snd_usb_audio] [] ? usb_free_urb+0x1a/0x1c [] snd_usb_mixer_add_control+0x11d9/0x1264 [snd_usb_audio] [] snd_usb_create_mixer+0xbc/0x286 [snd_usb_audio] [] 0xffffffffc02cac17 [] usb_probe_interface+0x17c/0x21c [] driver_probe_device+0xae/0x1fa [] __device_attach_driver+0x5f/0x66 [] ? driver_probe_device+0x1fa/0x1fa [] bus_for_each_drv+0x87/0xaa [] __device_attach+0x9d/0x101 [] device_initial_probe+0x13/0x15 [] bus_probe_device+0x33/0x96 [] device_add+0x328/0x547 [] usb_set_configuration+0x624/0x674 [] generic_probe+0x45/0x77 [] usb_probe_device+0x2d/0x40 [] driver_probe_device+0xae/0x1fa [] __device_attach_driver+0x5f/0x66 [] ? driver_probe_device+0x1fa/0x1fa [] bus_for_each_drv+0x87/0xaa [] __device_attach+0x9d/0x101 [] device_initial_probe+0x13/0x15 [] bus_probe_device+0x33/0x96 [] device_add+0x328/0x547 [] ? add_device_randomness+0x111/0x130 [] usb_new_device+0x2a2/0x3c0 [] hub_thread+0xa3d/0xeed [] ? __schedule+0x41e/0x5ac [] ? finish_wait+0x62/0x62 [] ? usb_reset_device+0x16a/0x16a [] kthread+0x108/0x110 [] ? __kthread_parkme+0x67/0x67 [] ret_from_fork+0x7c/0xb0 [] ? __kthread_parkme+0x67/0x67 Signed-off-by: Stephen Barber Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 082736c539bc..253fc946db29 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -318,12 +318,15 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, while (timeout-- > 0) { idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); - if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, idx, buf, val_len) >= val_len) { + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx, idx, buf, val_len); + if (err >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); err = 0; goto out; + } else if (err == -ETIMEDOUT) { + goto out; } } usb_audio_dbg(chip, @@ -483,12 +486,15 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, while (timeout-- > 0) { idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); - if (snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), request, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, idx, buf, val_len) >= 0) { + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), request, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + validx, idx, buf, val_len); + if (err >= 0) { err = 0; goto out; + } else if (err == -ETIMEDOUT) { + goto out; } } usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", -- cgit v1.2.3