[PATCH RFC] xHCI: Non-chained TRB prior to link TRB causes segment overrun

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

 



Hi,

I believe I may have found a bug in the xHCI driver, specifically in
xhci-ring's inc_enq(). If you insert a non-chained TRB immediately
prior to a link TRB, some logic kicks in to avoid having chained link
TRBs (which are not allowed in xHCI 0.95). However, I think this logic
may be faulty- it actually causes inc_enq() to ignore the link TRB
entirely.

The ring's enqueue pointer remains pointing to the link TRB, and the
next enqueued TRB on this ring overwrites it. Then, subsequent TRBs
write past the bounds of the ring. At best, this will cause "suspect
DMA" errors when handling completions. At worst, it's a kernel panic.

I'm not sure what the proper solution is to this, since I'm not
familiar with the way link TRBs and chain bits were defined in version
0.95 of the spec. But I've been using a very simple patch for my own
testing, and it seems to successfully fix this problem.

Thank you in advance for any comments on this problem or the patch :)

Signed-off-by: Micah Dowty <micah@xxxxxxxxxx>
---
 drivers/usb/host/xhci-ring.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b03b0f1..88c3d5b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -194,14 +194,12 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
 		if (!consumer) {
 			if (ring != xhci->event_ring) {
 				if (chain) {
-					next->link.control |= TRB_CHAIN;
-
-					/* Give this link TRB to the hardware */
-					wmb();
-					next->link.control ^= TRB_CYCLE;
-				} else {
-					break;
+				        next->link.control |= TRB_CHAIN;
 				}
+
+				/* Give this link TRB to the hardware */
+				wmb();
+				next->link.control ^= TRB_CYCLE;
 			}
 			/* Toggle the cycle bit after the last ring segment. */
 			if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
-- 
1.6.3.3

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