From bf78e1c721944083c2de41f510cd60bd00c00ab4 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Wed, 11 May 2022 21:11:00 +0000
Subject: [PATCH] xhci(4): Fix edge case in simultaneous xfer abort and
 failure.

On successful usbd_xfer_trycomplete, caller must set ux_status and
call usb_transfer_complete before releasing the pipe (bus) lock.
Failing to call usb_transfer_complete is a mistake.  Presumably this
was intended to claim the xfer to complete it only on the last
packet.
---
 sys/dev/usb/xhci.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 0e51a78891ab..bea067c3b4b5 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -2473,18 +2473,18 @@ xhci_event_transfer(struct xhci_softc * const sc,
 		break;
 	}
 
-	/*
-	 * Try to claim this xfer for completion.  If it has already
-	 * completed or aborted, drop it on the floor.
-	 */
-	if (!usbd_xfer_trycomplete(xfer))
-		return;
-
-	/* Set the status.  */
-	xfer->ux_status = err;
-
 	if ((trb_3 & XHCI_TRB_3_ED_BIT) == 0 ||
 	    (trb_0 & 0x3) == 0x0) {
+		/*
+		 * Try to claim this xfer for completion.  If it has
+		 * already completed or aborted, drop it on the floor.
+		 */
+		if (!usbd_xfer_trycomplete(xfer))
+			return;
+
+		/* Set the status.  */
+		xfer->ux_status = err;
+
 		usb_transfer_complete(xfer);
 	}
 }