• Mathias Nyman's avatar
    xhci: Fix perceived dead host due to runtime suspend race with event handler · 229bc19f
    Mathias Nyman authored
    Don't rely on event interrupt (EINT) bit alone to detect pending port
    change in resume. If no change event is detected the host may be suspended
    again, oterwise roothubs are resumed.
    
    There is a lag in xHC setting EINT. If we don't notice the pending change
    in resume, and the controller is runtime suspeded again, it causes the
    event handler to assume host is dead as it will fail to read xHC registers
    once PCI puts the controller to D3 state.
    
    [  268.520969] xhci_hcd: xhci_resume: starting port polling.
    [  268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling.
    [  268.521030] xhci_hcd: xhci_suspend: stopping port polling.
    [  268.521040] xhci_hcd: // Setting command ring address to 0x349bd001
    [  268.521139] xhci_hcd: Port Status Change Event for port 3
    [  268.521149] xhci_hcd: resume root hub
    [  268.521163] xhci_hcd: port resume event for port 3
    [  268.521168] xhci_hcd: xHC is not running.
    [  268.521174] xhci_hcd: handle_port_status: starting port polling.
    [  268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not responding, assume dead
    
    The EINT lag is described in a additional note in xhci specs 4.19.2:
    
    "Due to internal xHC scheduling and system delays, there will be a lag
    between a change bit being set and the Port Status Change Event that it
    generated being written to the Event Ring. If SW reads the PORTSC and
    sees a change bit set, there is no guarantee that the corresponding Port
    Status Change Event has already been written into the Event Ring."
    
    Cc: <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>
    229bc19f
xhci.c 152 KB