diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index db7683e2d34c..679b2ce01408 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3304,7 +3304,7 @@ static int finish_port_resume(struct usb_device *udev) /* * There are some SS USB devices which take longer time for link training. * XHCI specs 4.19.4 says that when Link training is successful, port - * sets CSC bit to 1. So if SW reads port status before successful link + * sets CCS bit to 1. So if SW reads port status before successful link * training, then it will not find device to be present. * USB Analyzer log with such buggy devices show that in some cases * device switch on the RX termination after long delay of host enabling @@ -3315,14 +3315,17 @@ static int finish_port_resume(struct usb_device *udev) * routine implements a 2000 ms timeout for link training. If in a case * link trains before timeout, loop will exit earlier. * + * There are also some 2.0 hard drive based devices and 3.0 thumb + * drives that, when plugged into a 2.0 only port, take a long + * time to set CCS after VBUS enable. + * * FIXME: If a device was connected before suspend, but was removed * while system was asleep, then the loop in the following routine will * only exit at timeout. * - * This routine should only be called when persist is enabled for a SS - * device. + * This routine should only be called when persist is enabled. */ -static int wait_for_ss_port_enable(struct usb_device *udev, +static int wait_for_connected(struct usb_device *udev, struct usb_hub *hub, int *port1, u16 *portchange, u16 *portstatus) { @@ -3335,6 +3338,7 @@ static int wait_for_ss_port_enable(struct usb_device *udev, delay_ms += 20; status = hub_port_status(hub, *port1, portstatus, portchange); } + dev_dbg(&udev->dev, "Waited %dms for CONNECT\n", delay_ms); return status; } @@ -3434,8 +3438,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) } } - if (udev->persist_enabled && hub_is_superspeed(hub->hdev)) - status = wait_for_ss_port_enable(udev, hub, &port1, &portchange, + if (udev->persist_enabled) + status = wait_for_connected(udev, hub, &port1, &portchange, &portstatus); status = check_port_resume_type(udev,