Skip to content

Commit b234c70

Browse files
matnymangregkh
authored andcommitted
xhci: Fix failure to detect ring expansion need.
Ring expansion checker may incorrectly assume a completely full ring is empty, missing the need for expansion. This is due to a special empty ring case where the dequeue ends up ahead of the enqueue pointer. This is seen when enqueued TRBs fill up exactly a segment, with enqueue then pointing to the end link TRB. Once those TRBs are handled the dequeue pointer will follow the link TRB and end up pointing to the first entry on the next segment, past the enqueue. This same enqueue - dequeue condition can be true if a ring is full, with enqueue ending on that last link TRB before the dequeue pointer on the next segment. This can be seen when queuing several ~510 small URBs via usbfs in one go before a single one is handled (i.e. dequeue not moved from first entry in segment). Expand the ring already when enqueue reaches the link TRB before the dequeue segment, instead of expanding it when enqueue moves into the dequeue segment. Reported-by: Chris Yokum <linux-usb@mail.totalphase.com> Closes: https://lore.kernel.org/all/949223224.833962.1709339266739.JavaMail.zimbra@totalphase.com Tested-by: Chris Yokum <linux-usb@mail.totalphase.com> Fixes: f5af638 ("xhci: Fix transfer ring expansion size calculation") Cc: stable@vger.kernel.org # v6.5+ Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20240305132312.955171-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 69c6335 commit b234c70

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,13 @@ static unsigned int xhci_ring_expansion_needed(struct xhci_hcd *xhci, struct xhc
326326
/* how many trbs will be queued past the enqueue segment? */
327327
trbs_past_seg = enq_used + num_trbs - (TRBS_PER_SEGMENT - 1);
328328

329-
if (trbs_past_seg <= 0)
329+
/*
330+
* Consider expanding the ring already if num_trbs fills the current
331+
* segment (i.e. trbs_past_seg == 0), not only when num_trbs goes into
332+
* the next segment. Avoids confusing full ring with special empty ring
333+
* case below
334+
*/
335+
if (trbs_past_seg < 0)
330336
return 0;
331337

332338
/* Empty ring special case, enqueue stuck on link trb while dequeue advanced */

0 commit comments

Comments
 (0)