USB: add missing delay during remote wakeup

This patch (as1330) fixes a bug in khbud's handling of remote
wakeups. When a device sends a remote-wakeup request, the parent hub
(or the host controller driver, for directly attached devices) begins
the resume sequence and notifies khubd when the sequence finishes. At
this point the port's SUSPEND feature is automatically turned off.

However the device needs an additional 10-ms resume-recovery time
(TRSMRCY in the USB spec). Khubd does not wait for this delay if the
SUSPEND feature is off, and as a result some devices fail to behave
properly following a remote wakeup. This patch adds the missing
delay to the remote-wakeup path.

It also extends the resume-signalling delay used by ehci-hcd and
uhci-hcd from 20 ms (the value in the spec) to 25 ms (the value we use
for non-remote-wakeup resumes). The extra time appears to help some
devices.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: stable <stable@kernel.org>
Cc: Rickard Bellini <rickard.bellini@ericsson.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


authored by Alan Stern and committed by Greg Kroah-Hartman 49d0f078 cec3a53c

+7 -3
+3
drivers/usb/core/hub.c
··· 3347 USB_PORT_FEAT_C_SUSPEND); 3348 udev = hdev->children[i-1]; 3349 if (udev) { 3350 usb_lock_device(udev); 3351 ret = remote_wakeup(hdev-> 3352 children[i-1]);
··· 3347 USB_PORT_FEAT_C_SUSPEND); 3348 udev = hdev->children[i-1]; 3349 if (udev) { 3350 + /* TRSMRCY = 10 msec */ 3351 + msleep(10); 3352 + 3353 usb_lock_device(udev); 3354 ret = remote_wakeup(hdev-> 3355 children[i-1]);
+3 -2
drivers/usb/host/ehci-hcd.c
··· 787 788 /* start 20 msec resume signaling from this port, 789 * and make khubd collect PORT_STAT_C_SUSPEND to 790 - * stop that signaling. 791 */ 792 - ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 793 ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); 794 mod_timer(&hcd->rh_timer, ehci->reset_done[i]); 795 }
··· 787 788 /* start 20 msec resume signaling from this port, 789 * and make khubd collect PORT_STAT_C_SUSPEND to 790 + * stop that signaling. Use 5 ms extra for safety, 791 + * like usb_port_resume() does. 792 */ 793 + ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); 794 ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); 795 mod_timer(&hcd->rh_timer, ehci->reset_done[i]); 796 }
+1 -1
drivers/usb/host/uhci-hub.c
··· 167 /* Port received a wakeup request */ 168 set_bit(port, &uhci->resuming_ports); 169 uhci->ports_timeout = jiffies + 170 - msecs_to_jiffies(20); 171 172 /* Make sure we see the port again 173 * after the resuming period is over. */
··· 167 /* Port received a wakeup request */ 168 set_bit(port, &uhci->resuming_ports); 169 uhci->ports_timeout = jiffies + 170 + msecs_to_jiffies(25); 171 172 /* Make sure we see the port again 173 * after the resuming period is over. */