Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: core: hub: Disable hub-initiated U1/U2

If the device rejects the control transfer to enable device-initiated
U1/U2 entry, then the device will not initiate U1/U2 transition. To
improve the performance, the downstream port should not initate
transition to U1/U2 to avoid the delay from the device link command
response (no packet can be transmitted while waiting for a response from
the device). If the device has some quirks and does not implement U1/U2,
it may reject all the link state change requests, and the downstream
port may resend and flood the bus with more requests. This will affect
the device performance even further. This patch disables the
hub-initated U1/U2 if the device-initiated U1/U2 entry fails.

Reference: USB 3.2 spec 7.2.4.2.3

Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Thinh Nguyen and committed by
Greg Kroah-Hartman
56175929 fea3af5e

+16 -12
+16 -12
drivers/usb/core/hub.c
··· 3999 3999 * control transfers to set the hub timeout or enable device-initiated U1/U2 4000 4000 * will be successful. 4001 4001 * 4002 + * If the control transfer to enable device-initiated U1/U2 entry fails, then 4003 + * hub-initiated U1/U2 will be disabled. 4004 + * 4002 4005 * If we cannot set the parent hub U1/U2 timeout, we attempt to let the xHCI 4003 4006 * driver know about it. If that call fails, it should be harmless, and just 4004 4007 * take up more slightly more bus bandwidth for unnecessary U1/U2 exit latency. ··· 4056 4053 * host know that this link state won't be enabled. 4057 4054 */ 4058 4055 hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); 4059 - } else { 4060 - /* Only a configured device will accept the Set Feature 4061 - * U1/U2_ENABLE 4062 - */ 4063 - if (udev->actconfig) 4064 - usb_set_device_initiated_lpm(udev, state, true); 4056 + return; 4057 + } 4065 4058 4066 - /* As soon as usb_set_lpm_timeout(timeout) returns 0, the 4067 - * hub-initiated LPM is enabled. Thus, LPM is enabled no 4068 - * matter the result of usb_set_device_initiated_lpm(). 4069 - * The only difference is whether device is able to initiate 4070 - * LPM. 4071 - */ 4059 + /* Only a configured device will accept the Set Feature 4060 + * U1/U2_ENABLE 4061 + */ 4062 + if (udev->actconfig && 4063 + usb_set_device_initiated_lpm(udev, state, true) == 0) { 4072 4064 if (state == USB3_LPM_U1) 4073 4065 udev->usb3_lpm_u1_enabled = 1; 4074 4066 else if (state == USB3_LPM_U2) 4075 4067 udev->usb3_lpm_u2_enabled = 1; 4068 + } else { 4069 + /* Don't request U1/U2 entry if the device 4070 + * cannot transition to U1/U2. 4071 + */ 4072 + usb_set_lpm_timeout(udev, state, 0); 4073 + hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); 4076 4074 } 4077 4075 } 4078 4076