Module Name: src
Committed By: martin
Date: Tue Aug 1 13:46:18 UTC 2023
Modified Files:
src/sys/dev/usb [netbsd-9]: xhci.c xhcivar.h
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #1687):
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.107.2.11 -r1.107.2.12 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.11.4.3 -r1.11.4.4 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.107.2.11 src/sys/dev/usb/xhci.c:1.107.2.12
--- src/sys/dev/usb/xhci.c:1.107.2.11 Mon Jan 23 12:05:36 2023
+++ src/sys/dev/usb/xhci.c Tue Aug 1 13:46:18 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: xhci.c,v 1.107.2.11 2023/01/23 12:05:36 martin Exp $ */
+/* $NetBSD: xhci.c,v 1.107.2.12 2023/08/01 13:46:18 martin Exp $ */
/*
* Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.107.2.11 2023/01/23 12:05:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.107.2.12 2023/08/01 13:46:18 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -2295,11 +2295,15 @@ xhci_rhpsc(struct xhci_softc * const sc,
KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
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 */
@@ -2576,7 +2580,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();
@@ -2587,6 +2591,20 @@ xhci_softintr(void *v)
XHCIHIST_CALLARGS("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.11.4.3 src/sys/dev/usb/xhcivar.h:1.11.4.4
--- src/sys/dev/usb/xhcivar.h:1.11.4.3 Mon Jan 23 12:05:36 2023
+++ src/sys/dev/usb/xhcivar.h Tue Aug 1 13:46:18 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: xhcivar.h,v 1.11.4.3 2023/01/23 12:05:36 martin Exp $ */
+/* $NetBSD: xhcivar.h,v 1.11.4.4 2023/08/01 13:46:18 martin Exp $ */
/*
* Copyright (c) 2013 Jonathan A. Kollasch
@@ -112,7 +112,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;