Module Name:    src
Committed By:   martin
Date:           Tue Aug  1 13:48:15 UTC 2023

Modified Files:
        src/sys/dev/usb [netbsd-8]: xhci.c xhcivar.h

Log Message:
Pull up following revision(s) (requested by riastradh in ticket #1869):

        sys/dev/usb/xhci.c: revision 1.176
        sys/dev/usb/xhcivar.h: revision 1.23

xhci(4): Defer root intr xfers while polling.

Root intr xfers require taking adaptive locks, which is forbidden
while polling.

This is not great -- any USB transfer completion callbacks might try
to take adaptive locks, not just uhub_intr, and that will always
causes trouble.  We get lucky with ukbd_intr because it's not
MP-safe, so it relies only on the kernel lock (a spin lock) anyway.
But this change brings xhci in line with ehci.

PR kern/57326


To generate a diff of this commit:
cvs rdiff -u -r1.72.2.14 -r1.72.2.15 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.7.6.2 -r1.7.6.3 src/sys/dev/usb/xhcivar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.72.2.14 src/sys/dev/usb/xhci.c:1.72.2.15
--- src/sys/dev/usb/xhci.c:1.72.2.14	Mon Jan 23 12:10:12 2023
+++ src/sys/dev/usb/xhci.c	Tue Aug  1 13:48:15 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.72.2.14 2023/01/23 12:10:12 martin Exp $	*/
+/*	$NetBSD: xhci.c,v 1.72.2.15 2023/08/01 13:48:15 martin Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.72.2.14 2023/01/23 12:10:12 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.72.2.15 2023/08/01 13:48:15 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -1893,11 +1893,15 @@ xhci_rhpsc(struct xhci_softc * const sc,
 		return;
 
 	uint8_t *p = xfer->ux_buf;
-	memset(p, 0, xfer->ux_length);
+	if (!xhci_polling_p(sc) || !sc->sc_intrxfer_deferred[bn])
+		memset(p, 0, xfer->ux_length);
 	p[rhp / NBBY] |= 1 << (rhp % NBBY);
 	xfer->ux_actlen = xfer->ux_length;
 	xfer->ux_status = USBD_NORMAL_COMPLETION;
-	usb_transfer_complete(xfer);
+	if (xhci_polling_p(sc))
+		sc->sc_intrxfer_deferred[bn] = true;
+	else
+		usb_transfer_complete(xfer);
 }
 
 /* Process Transfer Events */
@@ -2199,7 +2203,7 @@ xhci_softintr(void *v)
 	struct xhci_softc * const sc = XHCI_BUS2SC(bus);
 	struct xhci_ring * const er = &sc->sc_er;
 	struct xhci_trb *trb;
-	int i, j, k;
+	int i, j, k, bn;
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
@@ -2210,6 +2214,20 @@ xhci_softintr(void *v)
 
 	DPRINTFN(16, "er: xr_ep %jd xr_cs %jd", i, j, 0, 0);
 
+	/*
+	 * Handle deferred root intr xfer, in case we just switched off
+	 * polling.  It's not safe to complete root intr xfers while
+	 * polling -- too much kernel machinery gets involved.
+	 */
+	if (!xhci_polling_p(sc)) {
+		for (bn = 0; bn < 2; bn++) {
+			if (__predict_false(sc->sc_intrxfer_deferred[bn])) {
+				sc->sc_intrxfer_deferred[bn] = false;
+				usb_transfer_complete(sc->sc_intrxfer[bn]);
+			}
+		}
+	}
+
 	while (1) {
 		usb_syncmem(&er->xr_dma, XHCI_TRB_SIZE * i, XHCI_TRB_SIZE,
 		    BUS_DMASYNC_POSTREAD);

Index: src/sys/dev/usb/xhcivar.h
diff -u src/sys/dev/usb/xhcivar.h:1.7.6.2 src/sys/dev/usb/xhcivar.h:1.7.6.3
--- src/sys/dev/usb/xhcivar.h:1.7.6.2	Mon Jan 23 12:10:12 2023
+++ src/sys/dev/usb/xhcivar.h	Tue Aug  1 13:48:15 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhcivar.h,v 1.7.6.2 2023/01/23 12:10:12 martin Exp $	*/
+/*	$NetBSD: xhcivar.h,v 1.7.6.3 2023/08/01 13:48:15 martin Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -109,7 +109,7 @@ struct xhci_softc {
 	int *sc_rhportmap[2];
 	int sc_rhportcount[2];
 	struct usbd_xfer *sc_intrxfer[2];
-
+	bool sc_intrxfer_deferred[2];
 
 	struct xhci_slot * sc_slots;
 

Reply via email to