USB: Suspend functions before putting dev into U3.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Fri, 6 Jan 2012 23:48:30 +0000 (15:48 -0800)
committerSarah Sharp <sarah.a.sharp@linux.intel.com>
Tue, 14 Feb 2012 20:12:23 +0000 (12:12 -0800)
The USB 3.0 bus specification introduces a new type of power management
called function suspend.  The idea is to be able to suspend different
functions (i.e. a scanner or an SD card reader on a USB printer)
independently.  A device can be in U0, but have one or more functions
suspended.  Thus, signaling a function resume with the standard device
remote wake signaling was not possible.

Instead, a device will (without prompt from the host) send a "device
notification" for the function remote wake.  A new Set Feature Function
Remote Wake was developed to turn remote wake up on and off for each
function.

USB 3.0 devices can still go into device suspend (U3), and signal a
remote wakeup to bring the link back into U1.  However, they now use the
function remote wake device notification to allow the host to know which
function woke the device from U3.

The spec is a bit ambiguous about whether a function is allowed to
signal a remote wakeup if the function has been enabled for remote
wakeup, but not placed in function suspend before the device is placed
into U3.

Section 9.2.5.1 says "Suspending a device with more than one function
effectively suspends all the functions within the device."  I interpret
that to mean that putting a device in U3 suspends all functions, and
thus if the host has previously enabled remote wake for those functions,
it should be able to signal a remote wake up on port status changes.
However, hub vendors may have a different interpretation, and it can't
hurt to put the function into suspend before putting the device into U3.

I cannot get an answer out of the USB 3.0 spec architects about this
ambiguity, so I'm erring on the safe side and always suspending the
first function before placing the device in U3.  Note, this code should
be fixed if we ever find any USB 3.0 devices that have more than one
function.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
drivers/usb/core/hub.c

index 50411cd..70622d6 100644 (file)
@@ -2437,7 +2437,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                                        USB_REQ_SET_FEATURE,
                                        USB_RECIP_INTERFACE,
                                        USB_INTRF_FUNC_SUSPEND,
-                                       USB_INTRF_FUNC_SUSPEND_RW,
+                                       USB_INTRF_FUNC_SUSPEND_RW |
+                                       USB_INTRF_FUNC_SUSPEND_LP,
                                        NULL, 0,
                                        USB_CTRL_SET_TIMEOUT);
                }