Commit 132dcf65 authored by Niklas Neronin's avatar Niklas Neronin Committed by Greg Kroah-Hartman

usb: xhci: remove infinite loop prevention

If a buggy HW reports some unpredicted event (for example, an overrun event
following a MSE event while the EP ring is actually not empty), the driver
will never find the TD, and it will loop until the TD list is empty.

Before commits [1][2], the spin lock was released when giving back a URB in
the do-while loop. This could cause more TD to be added to TD list, causing
an infinite loop.

Because of commits [1][2] the spin lock is not released any more, thus the
infinite loop prevention is unnecessary and is removed.

[1], commit 0c03d89d ("xhci: Giveback urb in finish_td directly")
[2], commit 36dc0165 ("usb: host: xhci: Support running urb giveback in
			   tasklet context")
Signed-off-by: default avatarNiklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240626124835.1023046-18-mathias.nyman@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5ea8a885
......@@ -2611,7 +2611,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
int status = -EINPROGRESS;
struct xhci_ep_ctx *ep_ctx;
u32 trb_comp_code;
int td_num = 0;
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
......@@ -2637,10 +2636,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (!ep_ring)
return handle_transferless_tx_event(xhci, ep, trb_comp_code);
/* Count current td numbers if ep->skip is set */
if (ep->skip)
td_num += list_count_nodes(&ep_ring->td_list);
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
......@@ -2799,18 +2794,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
return 0;
}
/* We've skipped all the TDs on the ep ring when ep->skip set */
if (ep->skip && td_num == 0) {
ep->skip = false;
xhci_dbg(xhci, "All tds on the ep_ring skipped. Clear skip flag for slot %u ep %u.\n",
slot_id, ep_index);
return 0;
}
td = list_first_entry(&ep_ring->td_list, struct xhci_td,
td_list);
if (ep->skip)
td_num--;
/* Is this a TRB in the currently executing TD? */
ep_seg = trb_in_td(xhci, td, ep_trb_dma, false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment