aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConstantin Musca <constantin.musca@intel.com>2016-01-07 17:45:19 +0200
committerConstantin Musca <constantin.musca@intel.com>2016-01-07 18:00:31 +0200
commit926e6cb62bc1c9af79cd0229a3abbb9617f9cbc1 (patch)
treea2c1dd5519168ca30bfbfc52099a43cd2e35e1cb
parent7f30bf9f9e7be3dc28dc2689c542ebc0486fed75 (diff)
downloadedison-v3.10-926e6cb62bc1c9af79cd0229a3abbb9617f9cbc1.tar.gz
xhci: xhci_configure_endpoint: use non-interruptible wait_for_completion
Trying to Ctrl-C the execution of a process (audio_hal_playback_test) which plays audio on USB puts the associated endpoint in a bad state. The *audio_hal_playback_test* application indirectly uses the *tinyalsa* pcm_write function to write the audio data. If one Ctrl-Cs the execution of *audio_hal_play_test* the application gets the SIGINT signal and gets terminated (default action of the SIGINT signal). Below you can see the backtrace of the chain of functions which are called by *do_signal*. The do_exit function releases all resources including the pcm ones (pcm_close is called to disable the endpoint). [<c19dbcf5>] dump_stack+0x16/0x18 [<c163254c>] xhci_configure_endpoint+0x60c/0x6a0 [<c1632cde>] xhci_check_bandwidth+0x15e/0x260 [<c160480e>] usb_hcd_alloc_bandwidth+0x17e/0x4e0 [<c19d9645>] ? printk+0x1c/0x1e [<c16085a7>] usb_set_interface+0x127/0x4a0 [<c131c17d>] ? __vunmap+0x7d/0xf0 [<c1798a1e>] snd_usb_pcm_close.isra.8+0x3e/0x70 [<c1798a62>] snd_usb_playback_close+0x12/0x20 [<c1776516>] snd_pcm_release_substream.part.30+0x36/0x80 [<c17765ef>] snd_pcm_release+0x8f/0xb0 [<c132bc78>] __fput+0xd8/0x220 [<c132bdfd>] ____fput+0xd/0x10 [<c1263c39>] task_work_run+0x89/0xb0 [<c1249658>] do_exit+0x2e8/0xa20 [<c12744cb>] ? get_parent_ip+0xb/0x40 [<c1255923>] ? recalc_sigpending+0x13/0x50 [<c12744cb>] ? get_parent_ip+0xb/0x40 [<c1249e07>] do_group_exit+0x37/0xa0 [<c125859c>] get_signal_to_deliver+0x22c/0x660 [<c1200fea>] do_signal+0x3a/0xb60 [<c1329ec1>] ? do_sync_read+0x61/0x90 [<c1778b57>] ? snd_pcm_playback_ioctl+0x27/0x40 [<c1493c91>] ? ioctl_has_perm+0xa1/0xc0 [<c1493d04>] ? selinux_file_ioctl+0x54/0x100 [<c133b090>] ? SyS_ioctl+0x60/0x90 [<c1201b65>] do_notify_resume+0x55/0x70 [<c19e35e1>] work_notifysig+0x29/0x30 xhci_configure_endpoint sends the *disable* command and waits for the ACK from the controller using wait_for_completion_interruptible_timeout. However, the xhci_configure_endpoint#wait_for_completion_interruptible_timeout call returns with -ERESTARTSYS because the SIGINT signal is pending (check wait_for_completion_interruptible_timeout -> wait_for_common -> __wait_for_common -> do_wait_for_common -> signal_pending_state for details). Due to -ERESTARTSYS xhci_check_bandwidth (which calls xhci_configure_endpoint) doesn't free all resources and next time when one tries to use the pcm the following errors will be thrown: dwc3-host dwc3-host.2: xHCI xhci_drop_endpoint called with disabled ep f51be840 dwc3-host dwc3-host.2: xHCI xhci_drop_endpoint called with disabled ep f51be86c dwc3-host dwc3-host.2: Trying to add endpoint 0x1 without dropping it. usb 1-1: Not enough bandwidth for altsetting 1 2:1:1: usb_set_interface failed (-22) Unable to open PCM device 0 (cannot set hw params: I/O error) The xhci_drop_endpoint fails because the endpoints are disabled (xhci_configure_endpoint's *disable* command worked even though it didn't wait for ACK due to the pending signal - the controller set the disable state). The impact is that I cannot play audio on USB anymore if I Ctrl-C the execution of audio_hal_playback_test. The device needs to be rebooted. The wait_for_completion_interruptible_timeout call in 3.10 was changed in 3.16 to wait_for_completion in a bigger command rework (see upstream commit c311e391a7efd101250c0e123286709b7e736249). The solution is to replace wait_for_completion_interruptible_timeout with wait_for_completion_timeout. XHCI_CMD_DEFAULT_TIMEOUT is 5 * HZ, but the call is unlikely to timeout. BUG=26296289 Change-Id: I81e778ec2f420aaace0acc1d99ab30c893acedba Signed-off-by: Constantin Musca <constantin.musca@intel.com>
-rw-r--r--drivers/usb/host/xhci.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index f9446d0dac5..7c02bf82ba4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2630,7 +2630,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
spin_unlock_irqrestore(&xhci->lock, flags);
/* Wait for the configure endpoint command to complete */
- timeleft = wait_for_completion_interruptible_timeout(
+ timeleft = wait_for_completion_timeout(
cmd_completion,
XHCI_CMD_DEFAULT_TIMEOUT);
if (timeleft <= 0) {