Skip to content

Commit

Permalink
xhci: Prevent infinite loop in transaction errors recovery for streams
Browse files Browse the repository at this point in the history
commit a157512 upstream.

Make sure to also limit the amount of soft reset retries for transaction
errors on streams in cases where the transaction error event doesn't point
to any specific TRB.

In these cases we don't know the TRB or stream ring, but we do know which
endpoint had the error.

To keep error counting simple and functional, move the current err_count
from ring structure to endpoint structure.

Cc: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20221130091944.2171610-6-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
matnyman authored and gregkh committed Dec 31, 2022
1 parent 2f3b511 commit c3c1153
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
14 changes: 10 additions & 4 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -2458,7 +2458,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,

switch (trb_comp_code) {
case COMP_SUCCESS:
ep_ring->err_count = 0;
ep->err_count = 0;
/* handle success with untransferred data as short packet */
if (ep_trb != td->last_trb || remaining) {
xhci_warn(xhci, "WARN Successful completion on short TX\n");
Expand All @@ -2484,7 +2484,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
break;
case COMP_USB_TRANSACTION_ERROR:
if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
(ep_ring->err_count++ > MAX_SOFT_RETRY) ||
(ep->err_count++ > MAX_SOFT_RETRY) ||
le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
break;

Expand Down Expand Up @@ -2565,8 +2565,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
case COMP_USB_TRANSACTION_ERROR:
case COMP_INVALID_STREAM_TYPE_ERROR:
case COMP_INVALID_STREAM_ID_ERROR:
xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
EP_SOFT_RESET);
xhci_dbg(xhci, "Stream transaction error ep %u no id\n",
ep_index);
if (ep->err_count++ > MAX_SOFT_RETRY)
xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
EP_HARD_RESET);
else
xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
EP_SOFT_RESET);
goto cleanup;
case COMP_RING_UNDERRUN:
case COMP_RING_OVERRUN:
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/xhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,7 @@ struct xhci_virt_ep {
* have to restore the device state to the previous state
*/
struct xhci_ring *new_ring;
unsigned int err_count;
unsigned int ep_state;
#define SET_DEQ_PENDING (1 << 0)
#define EP_HALTED (1 << 1) /* For stall handling */
Expand Down Expand Up @@ -1627,7 +1628,6 @@ struct xhci_ring {
* if we own the TRB (if we are the consumer). See section 4.9.1.
*/
u32 cycle_state;
unsigned int err_count;
unsigned int stream_id;
unsigned int num_segs;
unsigned int num_trbs_free;
Expand Down

0 comments on commit c3c1153

Please sign in to comment.