The cancellation and stall endpoint handlers will use a Set TR Dequeue Pointer command to move the dequeue pointers past the offending TD. Since link TRBs are not given to the hardware until a new TD is enqueued to the top of the next segment, the command may set the new dequeue pointer to point to the link TRB. This would cause the old code in handle_set_deq_completion() to skip over the link TRB without checking to see if it matched the new dequeue pointer. It would then go into an infinite loop, looking for the new dequeue pointer in every TRB in the ring, except for the link TRB. Andiry, perhaps you want to add a bit of code to store the initial ring dequeue pointer, and break out of this loop if we come back to it without finding the correct dequeue pointer? You could store the current number of freed TRB and restore it if that happens. Also, this particular chunk of code is indented way too far, so you should refactor it into a new function. I don't think you need a while loop for checking the last_trb(), since it's against the xHCI rules to have two link TRBs in a row. The USB 3.0 card reader I have will stall every SCSI command while it is empty, so it was only a matter of time before a TD was queued just before the link TRB. That's why my box would always hang with the ring expansion patchset and that device. Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> Cc: Andiry Xu <andiry.xu@xxxxxxx> --- Hi Andiry, I didn't get around to applying your revert patch because I looked at the new Set TR dequeue pointer command code and found the bug. Feel free to integrate this fix into your next patchset version. Sarah Sharp drivers/usb/host/xhci-ring.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4163de7..ccfbec2 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1080,8 +1080,11 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, /* We have more usable TRBs */ ep_ring->num_trbs_free++; ep_ring->dequeue++; - while (last_trb(xhci, ep_ring, ep_ring->deq_seg, + if (last_trb(xhci, ep_ring, ep_ring->deq_seg, ep_ring->dequeue)) { + if (ep_ring->dequeue == + dev->eps[ep_index].queued_deq_ptr) + break; ep_ring->deq_seg = ep_ring->deq_seg->next; ep_ring->dequeue = -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html