• Mathias Nyman's avatar
    xhci: Fix a race in usb2 LPM resume, blocking U3 for usb2 devices · dad67d5f
    Mathias Nyman authored
    Clear device initiated resume variables once device is fully up and running
    in U0 state.
    Resume needs to be signaled for 20ms for usb2 devices before they can be
    moved to U0 state.
    An interrupt is triggered if a device initiates resume. As we handle the
    event in interrupt context we can not sleep for 20ms, so we instead set
    a resume flag, a timestamp, and start the roothub polling.
    The roothub code will later move the port to U0 when it finds a port in
    resume state with the resume flag set, and timestamp passed by 20ms.
    A host initiated resume is however not done in interrupt context, and
    host initiated resume code will directly signal resume, wait 20ms and then
    move the port to U0.
    These two codepaths can race, if we are in the middle of a host initated
    resume, while sleeping for 20ms, we may handle a port event and find the
    port in resume state. The port event handling code will assume the resume
    was device initiated and set the resume flag and timestamp.
    Root hub code will however not catch the port in resume state again as the
    host initated resume code has already moved the port to U0.
    The resume flag and timestamp will remain set for this port preventing port
    from suspending again  (LPM setting port to U3)
    Fix this for now by always clearing the device initated resume parameters
    once port is in U0
    Cc: stable <stable@vger.kernel.org>
    Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
xhci-hub.c 40.5 KB