• Michal Pecio's avatar
    usb: xhci: Fix handling errors mid TD followed by other errors · f42a36ba
    Michal Pecio authored
    Some host controllers fail to produce the final completion event on an
    isochronous TD which experienced an error mid TD. We deal with it by
    flagging such TDs and checking if the next event points at the flagged
    TD or at the next one, and giving back the flagged TD if the latter.
    
    This is not enough, because the next TD may be missed by the xHC. Or
    there may be no next TD but a ring underrun. We also need to get such
    TD quickly out of the way, or errors on later TDs may be handled wrong.
    
    If the next TD experiences a Missed Service Error, we will set the skip
    flag on the endpoint and then attempt skipping TDs when yet another
    event arrives. In such scenario, we ought to report the 'error mid TD'
    transfer as such rather than skip it.
    
    Another problem case are Stopped events. If we see one after an error
    mid TD, we naively assume that it's a Force Stopped Event because it
    doesn't match the pending TD, but in reality it might be an ordinary
    Stopped event for the next TD, which we fail to recognize and handle.
    
    Fix this by moving error mid TD handling before the whole TD skipping
    loop. Remove unnecessary conditions, always give back the TD if the new
    event points to any TRB outside it or if the pointer is NULL, as may be
    the case in Ring Underrun and Overrun events on 1st gen hardware. Only
    if the pending TD isn't flagged, consider other actions like skipping.
    
    As a side effect of reordering with skip and FSE cases, error mid TD is
    reordered with last_td_was_short check. This is harmless, because the
    two cases are mutually exclusive - only one can happen in any given run
    of handle_tx_event().
    
    Tested on the NEC host and a USB camera with flaky cable. Dynamic debug
    confirmed that Transaction Errors are sometimes seen, sometimes mid-TD,
    sometimes followed by Missed Service. In such cases, they were finished
    properly before skipping began.
    
    [Rebase on 6.12-rc1 -Mathias]
    Signed-off-by: default avatarMichal Pecio <michal.pecio@gmail.com>
    Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
    Link: https://lore.kernel.org/r/20241016140000.783905-4-mathias.nyman@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    f42a36ba
xhci-ring.c 130 KB