[PATCH] xhci: Fix bug in ring expansion free TRB counting.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux