xhci: Prevent infinite loop in transaction errors recovery for streams
[platform/kernel/linux-rpi.git] / drivers / usb / host / xhci-ring.c
index f6af479..039ec97 100644 (file)
@@ -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");
@@ -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;
 
@@ -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: