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;