Commit ad330971 authored by Kai-Heng Feng's avatar Kai-Heng Feng Committed by Wen Zhiwei
Browse files

USB: core: Disable LPM only for non-suspended ports

stable inclusion
from stable-v6.6.72
commit 730016e0b963e86e5bd15b6c82402c3a32853eeb
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBQN9L

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=730016e0b963e86e5bd15b6c82402c3a32853eeb



--------------------------------

commit 59bfeaf5454b7e764288d84802577f4a99bf0819 upstream.

There's USB error when tegra board is shutting down:
[  180.919315] usb 2-3: Failed to set U1 timeout to 0x0,error code -113
[  180.919995] usb 2-3: Failed to set U1 timeout to 0xa,error code -113
[  180.920512] usb 2-3: Failed to set U2 timeout to 0x4,error code -113
[  186.157172] tegra-xusb 3610000.usb: xHCI host controller not responding, assume dead
[  186.157858] tegra-xusb 3610000.usb: HC died; cleaning up
[  186.317280] tegra-xusb 3610000.usb: Timeout while waiting for evaluate context command

The issue is caused by disabling LPM on already suspended ports.

For USB2 LPM, the LPM is already disabled during port suspend. For USB3
LPM, port won't transit to U1/U2 when it's already suspended in U3,
hence disabling LPM is only needed for ports that are not suspended.

Cc: Wayne Chang <waynec@nvidia.com>
Cc: stable <stable@kernel.org>
Fixes: d920a2ed8620 ("usb: Disable USB3 LPM at shutdown")
Signed-off-by: default avatarKai-Heng Feng <kaihengf@nvidia.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Tested-by: default avatarJon Hunter <jonathanh@nvidia.com>
Link: https://lore.kernel.org/r/20241206074817.89189-1-kaihengf@nvidia.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent a40ec7be
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -451,10 +451,11 @@ static int usb_port_runtime_suspend(struct device *dev)
static void usb_port_shutdown(struct device *dev)
{
	struct usb_port *port_dev = to_usb_port(dev);
	struct usb_device *udev = port_dev->child;

	if (port_dev->child) {
		usb_disable_usb2_hardware_lpm(port_dev->child);
		usb_unlocked_disable_lpm(port_dev->child);
	if (udev && !udev->port_is_suspended) {
		usb_disable_usb2_hardware_lpm(udev);
		usb_unlocked_disable_lpm(udev);
	}
}