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

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

 



On 01/18/2012 07:01 AM, Sarah Sharp wrote:
> 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.
> 

Thanks for the patch. I'll merge it. From my understanding, the enqueue
pointer may stay on the link TRB, while the dequeue pointer never does
so. Anyway, I'll add a check to make sure it does not fall into an
infinite loop.

Thanks,
Andiry

> 
>  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 =


--
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