• Alan Stern's avatar
    USB: global suspend and remote wakeup don't mix · 5deba4cf
    Alan Stern authored
    commit e583d9db upstream.
    
    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: default avatarAlan Stern <stern@rowland.harvard.edu>
    Reported-and-tested-by: default avatarToralf Förster <toralf.foerster@gmx.de>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    5deba4cf
hub.c 154 KB