[PATCH 3/3][SRU][OEM-5.10/U] UBUNTU: SAUCE: (no-up) USB: reset-resume the Realtek hub if suspend timeout

chris.chiu at canonical.com chris.chiu at canonical.com
Sun May 16 18:14:32 UTC 2021


From: Chris Chiu <chris.chiu at canonical.com>

BugLink: https://bugs.launchpad.net/bugs/1928242

In Dell WD19 dock, there're a super-speed hub and a high-speed hub.
When the high-speed hub hit the timeout problem when suspending the
port which has wakeup enabled descendants, the super-speed hub will
also hit the timeout when there's super-speed device connecting to
the exposed Type-A port for unknown reason. If the super speed device
connects to Type-C port, there's no such problem.

The port status of the super-speed hub doesn't indicate it's suspended.
However, if no ClearPortFeature invoked during resume for the port,
the hub will then fail to activate and all devices connected to the
super-speedhub will be lost.

This commit reset-resume the downstream hub of the superspeed hub
only if suspend timeout happens even the port is not suspended.
Since it only happens in particular circumstance, we do not like
RESET_RESUME quirk to reset-resume all the time which lose the
runtime pm capability. And it's unable to be upstream because no
good explanation for why the Type-A port with a super-speed device
connected cause the super-speed hub suspend timeout at the same
time when high-speed hub timeout during suspend.

Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
---
 drivers/usb/core/hub.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index e739f7b5991a..740d84028757 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3391,6 +3391,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 		if (status == -ETIMEDOUT) {
 			int ret;
 			u16 portstatus, portchange;
+			u16 vid = le16_to_cpu(udev->descriptor.idVendor);
 
 			portstatus = portchange = 0;
 			ret = hub_port_status(hub, port1, &portstatus,
@@ -3403,6 +3404,12 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 				status = 0;
 				goto suspend_done;
 			}
+
+			// reset_resume the downstream Realtek hub
+			if (vid == 0x0bda && usb_hub_to_struct_hub(udev)) {
+				udev->reset_resume = 1;
+				goto err_wakeup;
+			}
 		}
 
 		dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status);
-- 
2.20.1




More information about the kernel-team mailing list