USB: global suspend and remote wakeup don't mix
authorAlan Stern <stern@rowland.harvard.edu>
Thu, 11 Jul 2013 18:58:04 +0000 (14:58 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 Jul 2013 22:33:02 +0000 (15:33 -0700)
commite583d9db9960cf40e0bc8afee4946baa9d71596e
treeaf009cc8155cc5d751589909bcbaa723857cf96c
parent36ff66db3fb5642906e46e73ca9cf92f1c5974ff
USB: global suspend and remote wakeup don't mix

The hub driver was recently changed to use "global" suspend for system
suspend transitions on non-SuperSpeed buses.  This means that we don't
suspend devices individually by setting the suspend feature on the
upstream hub port; instead devices all go into suspend automatically
when the root hub stops transmitting packets.  The idea was to save
time and to avoid certain kinds of wakeup races.

Now it turns out that many hubs are buggy; they don't relay wakeup
requests from a downstream port to their upstream port if the
downstream port's suspend feature is not set (depending on the speed
of the downstream port, whether or not the hub is enabled for remote
wakeup, and possibly other factors).

We can't have hubs dropping wakeup requests.  Therefore this patch
goes partway back to the old policy: It sets the suspend feature for a
port if the device attached to that port or any of its descendants is
enabled for wakeup.  People will still be able to benefit from the
time savings if they don't care about wakeup and leave it disabled on
all their devices.

In order to accomplish this, the patch adds a new field to the usb_hub
structure: wakeup_enabled_descendants is a count of how many devices
below a suspended hub are enabled for remote wakeup.  A corresponding
new subroutine determines the number of wakeup-enabled devices at or
below an arbitrary suspended USB device.

This should be applied to the 3.10 stable kernel.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-and-tested-by: Toralf Förster <toralf.foerster@gmx.de>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/core/hub.c
drivers/usb/core/hub.h