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

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

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
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.


Change-Id: I81e778ec2f420aaace0acc1d99ab30c893acedba
Signed-off-by: Constantin Musca <constantin.musca@intel.com>
1 file changed