• Julius Werner's avatar
    usb: xhci: Prefer endpoint context dequeue pointer over stopped_trb · b9c6d6da
    Julius Werner authored
    commit 1f81b6d2 upstream.
    
    We have observed a rare cycle state desync bug after Set TR Dequeue
    Pointer commands on Intel LynxPoint xHCs (resulting in an endpoint that
    doesn't fetch new TRBs and thus an unresponsive USB device). It always
    triggers when a previous Set TR Dequeue Pointer command has set the
    pointer to the final Link TRB of a segment, and then another URB gets
    enqueued and cancelled again before it can be completed. Further
    investigation showed that the xHC had returned the Link TRB in the TRB
    Pointer field of the Transfer Event (CC == Stopped -- Length Invalid),
    but when xhci_find_new_dequeue_state() later accesses the Endpoint
    Context's TR Dequeue Pointer field it is set to the first TRB of the
    next segment.
    
    The driver expects those two values to be the same in this situation,
    and uses the cycle state of the latter together with the address of the
    former. This should be fine according to the XHCI specification, since
    the endpoint ring should be stopped when returning the Transfer Event
    and thus should not advance over the Link TRB before it gets restarted.
    However, real-world XHCI implementations apparently don't really care
    that much about these details, so the driver should follow a more
    defensive approach to try to work around HC spec violations.
    
    This patch removes the stopped_trb variable that had been used to store
    the TRB Pointer from the last Transfer Event of a stopped TRB. Instead,
    xhci_find_new_dequeue_state() now relies only on the Endpoint Context,
    requiring a small amount of additional processing to find the virtual
    address corresponding to the TR Dequeue Pointer. Some other parts of the
    function were slightly rearranged to better fit into this model.
    
    This patch should be backported to kernels as old as 2.6.31 that contain
    the commit ae636747 "USB: xhci: URB
    cancellation support."
    Signed-off-by: default avatarJulius Werner <jwerner@chromium.org>
    Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    [bwh: Backported to 3.2: adjust context]
    Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
    b9c6d6da
xhci-ring.c 121 KB