• Keiya Nobuta's avatar
    usb: core: hub: Improved device recognition on remote wakeup · 9c06ac4c
    Keiya Nobuta authored
    If hub_activate() is called before D+ has stabilized after remote
    wakeup, the following situation might occur:
    
             __      ___________________
            /  \    /
    D+   __/    \__/
    
    Hub  _______________________________
              |  ^   ^           ^
              |  |   |           |
    Host _____v__|___|___________|______
              |  |   |           |
              |  |   |           \-- Interrupt Transfer (*3)
              |  |    \-- ClearPortFeature (*2)
              |   \-- GetPortStatus (*1)
              \-- Host detects remote wakeup
    
    - D+ goes high, Host starts running by remote wakeup
    - D+ is not stable, goes low
    - Host requests GetPortStatus at (*1) and gets the following hub status:
      - Current Connect Status bit is 0
      - Connect Status Change bit is 1
    - D+ stabilizes, goes high
    - Host requests ClearPortFeature and thus Connect Status Change bit is
      cleared at (*2)
    - After waiting 100 ms, Host starts the Interrupt Transfer at (*3)
    - Since the Connect Status Change bit is 0, Hub returns NAK.
    
    In this case, port_event() is not called in hub_event() and Host cannot
    recognize device. To solve this issue, flag change_bits even if only
    Connect Status Change bit is 1 when got in the first GetPortStatus.
    
    This issue occurs rarely because it only if D+ changes during a very
    short time between GetPortStatus and ClearPortFeature. However, it is
    fatal if it occurs in embedded system.
    Signed-off-by: default avatarKeiya Nobuta <nobuta.keiya@fujitsu.com>
    Cc: stable <stable@vger.kernel.org>
    Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
    Link: https://lore.kernel.org/r/20200109051448.28150-1-nobuta.keiya@fujitsu.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    9c06ac4c
hub.c 173 KB