• Sarah Sharp's avatar
    xhci: Clear stopped_td when Stop Endpoint command completes. · 0714a57c
    Sarah Sharp authored
    When an URB is cancelled, the xHCI driver issues a Stop Endpoint command
    so that it can manipulate the ring and remove the transfer.  The xHC
    hardware then places a transfer event with the completion code "Stopped"
    or "Stopped Invalid" to let the driver know what TD it was in the middle
    of processing.  This TD and TRB is stored in ep->stopped_td and
    ep->stopped_trb.  These pointers are also used in handling stalled
    endpoints.
    
    By design, the Stop Endpoint command can race with URB completion.  By
    the time the Stop Endpoint command is handled, the URBs to be cancelled
    may have been given back to the driver.  Unfortunately, the stopped_td
    and stopped_trb pointers were not getting cleared in this case.
    
    The USB core unconditionally tries to reset the toggle bits on any
    endpoints when a new alternate interface setting is installed.  When the
    xHCI driver saw that ep->stopped_td was still set from the Stop Endpoint
    command, xhci_reset_endpoint assumed the endpoint was actually stalled,
    and attempted to clean up the endpoint rings.  This would manifest
    itself in a failed Reset Endpoint command and failed Set TR dequeue
    Pointer command after a successful Configure Endpoint command.  It may
    have also been causing driver oops when the stopped_td was accessed.
    
    This patch should be backported to stable kernels since 2.6.31.  Before
    2.6.33, stopped_td was found in the xhci_endpoint_ring, not the
    xhci_virt_ep.
    Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
    0714a57c
xhci-ring.c 110 KB