Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb xhci(4): Defer root intr xfers while polling.



details:   https://anonhg.NetBSD.org/src/rev/19ac525794b2
branches:  trunk
changeset: 374174:19ac525794b2
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri Apr 07 09:39:48 2023 +0000

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

XXX pullup-8
XXX pullup-9
XXX pullup-10

diffstat:

 sys/dev/usb/xhci.c    |  28 +++++++++++++++++++++++-----
 sys/dev/usb/xhcivar.h |   4 ++--
 2 files changed, 25 insertions(+), 7 deletions(-)

diffs (84 lines):

diff -r ec9fcc6c1d3a -r 19ac525794b2 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Fri Apr 07 08:55:29 2023 +0000
+++ b/sys/dev/usb/xhci.c        Fri Apr 07 09:39:48 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.175 2022/10/11 11:01:17 msaitoh Exp $       */
+/*     $NetBSD: xhci.c,v 1.176 2023/04/07 09:39:48 riastradh Exp $     */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.175 2022/10/11 11:01:17 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.176 2023/04/07 09:39:48 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2351,11 +2351,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 */
@@ -2619,7 +2623,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();
 
@@ -2630,6 +2634,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);
diff -r ec9fcc6c1d3a -r 19ac525794b2 sys/dev/usb/xhcivar.h
--- a/sys/dev/usb/xhcivar.h     Fri Apr 07 08:55:29 2023 +0000
+++ b/sys/dev/usb/xhcivar.h     Fri Apr 07 09:39:48 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhcivar.h,v 1.22 2022/10/11 09:18:22 msaitoh Exp $     */
+/*     $NetBSD: xhcivar.h,v 1.23 2023/04/07 09:39:48 riastradh Exp $   */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -121,7 +121,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;
 



Home | Main Index | Thread Index | Old Index