Skip to content
  • Mathias Nyman's avatar
    xhci: fix USB3 device initiated resume race with roothub autosuspend · 6c18dd40
    Mathias Nyman authored
    commit 057d476f
    
     upstream.
    
    A race in xhci USB3 remote wake handling may force device back to suspend
    after it initiated resume siganaling, causing a missed resume event or warm
    reset of device.
    
    When a USB3 link completes resume signaling and goes to enabled (UO)
    state a interrupt is issued and the interrupt handler will clear the
    bus_state->port_remote_wakeup resume flag, allowing bus suspend.
    
    If the USB3 roothub thread just finished reading port status before
    the interrupt, finding ports still in suspended (U3) state, but hasn't
    yet started suspending the hub, then the xhci interrupt handler will clear
    the flag that prevented roothub suspend and allow bus to suspend, forcing
    all port links back to suspended (U3) state.
    
    Example case:
    usb_runtime_suspend() # because all ports still show suspended U3
      usb_suspend_both()
        hub_suspend();   # successful as hub->wakeup_bits not set yet
    ==> INTERRUPT
    xhci_irq()
      handle_port_status()
        clear bus_state->port_remote_wakeup
        usb_wakeup_notification()
          sets hub->wakeup_bits;
            kick_hub_wq()
    <== END INTERRUPT
          hcd_bus_suspend()
            xhci_bus_suspend() # success as port_remote_wakeup bits cleared
    
    Fix this by increasing roothub usage count during port resume to prevent
    roothub autosuspend, and by making sure bus_state->port_remote_wakeup
    flag is only cleared after resume completion is visible, i.e.
    after xhci roothub returned U0 or other non-U3 link state link on a
    get port status request.
    
    Issue rootcaused by Chiasheng Lee
    
    Cc: <stable@vger.kernel.org>
    Cc: Lee, Hou-hsun <hou-hsun.lee@intel.com>
    Reported-by: default avatarLee, Chiasheng <chiasheng.lee@intel.com>
    Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
    Link: https://lore.kernel.org/r/20191211142007.8847-3-mathias.nyman@linux.intel.com
    
    
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    6c18dd40