Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb uhub(4): Defer rescan to USB event thread.



details:   https://anonhg.NetBSD.org/src/rev/1f23520b1f33
branches:  trunk
changeset: 983908:1f23520b1f33
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Jun 13 14:46:07 2021 +0000

description:
uhub(4): Defer rescan to USB event thread.

Keep all of the USB bus exploration in a single thread -- this
appears to have been the original assumption, violated back in 2008
when uhub_rescan was added, and will make everything simpler.

diffstat:

 sys/dev/usb/uhub.c |  82 +++++++++++++++--------------------------------------
 1 files changed, 23 insertions(+), 59 deletions(-)

diffs (153 lines):

diff -r 4c23ad5623e5 -r 1f23520b1f33 sys/dev/usb/uhub.c
--- a/sys/dev/usb/uhub.c        Sun Jun 13 14:45:36 2021 +0000
+++ b/sys/dev/usb/uhub.c        Sun Jun 13 14:46:07 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhub.c,v 1.151 2021/06/13 00:11:57 riastradh Exp $     */
+/*     $NetBSD: uhub.c,v 1.152 2021/06/13 14:46:07 riastradh Exp $     */
 /*     $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $       */
 /*     $OpenBSD: uhub.c,v 1.86 2015/06/29 18:27:40 mpi Exp $ */
 
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.151 2021/06/13 00:11:57 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.152 2021/06/13 14:46:07 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -119,6 +119,7 @@
        bool                     sc_explorepending;
        bool                     sc_first_explore;
        bool                     sc_running;
+       bool                     sc_rescan;
 
        struct lwp              *sc_exploring;
 };
@@ -130,8 +131,6 @@
 #define PORTSTAT_ISSET(sc, port) \
        ((sc)->sc_status[(port) / 8] & (1 << ((port) % 8)))
 
-Static usbd_status uhub_explore_enter(struct uhub_softc *);
-Static void uhub_explore_exit(struct uhub_softc *);
 Static usbd_status uhub_explore(struct usbd_device *);
 Static void uhub_intr(struct usbd_xfer *, void *, usbd_status);
 
@@ -482,51 +481,17 @@
        config_pending_decr(self);
 }
 
-Static usbd_status
-uhub_explore_enter(struct uhub_softc *sc)
-{
-       usbd_status err;
-
-       mutex_enter(&sc->sc_lock);
-       for (;;) {
-               if (sc->sc_exploring == NULL) {
-                       sc->sc_exploring = curlwp;
-                       err = 0;
-                       break;
-               }
-               KASSERT(sc->sc_exploring != curlwp);
-               if (cv_wait_sig(&sc->sc_cv, &sc->sc_lock)) {
-                       err = USBD_INTERRUPTED;
-                       break;
-               }
-       }
-       mutex_exit(&sc->sc_lock);
-
-       return err;
-}
-
-Static void
-uhub_explore_exit(struct uhub_softc *sc)
-{
-
-       mutex_enter(&sc->sc_lock);
-       KASSERTMSG(sc->sc_exploring == curlwp, "lwp %p exploring %s",
-           sc->sc_exploring, device_xname(sc->sc_dev));
-       sc->sc_exploring = NULL;
-       cv_broadcast(&sc->sc_cv);
-       mutex_exit(&sc->sc_lock);
-}
-
 usbd_status
 uhub_explore(struct usbd_device *dev)
 {
        usb_hub_descriptor_t *hd = &dev->ud_hub->uh_hubdesc;
        struct uhub_softc *sc = dev->ud_hub->uh_hubsoftc;
        struct usbd_port *up;
+       struct usbd_device *subdev;
        usbd_status err;
        int speed;
        int port;
-       int change, status, reconnect;
+       int change, status, reconnect, rescan;
 
        UHUBHIST_FUNC();
        UHUBHIST_CALLARGS("uhub%jd dev=%#jx addr=%jd speed=%ju",
@@ -542,10 +507,19 @@
        if (dev->ud_depth > USB_HUB_MAX_DEPTH)
                return USBD_TOO_DEEP;
 
-       /* Only one explore at a time, please.  */
-       err = uhub_explore_enter(sc);
-       if (err)
-               return err;
+       /* Process rescan if requested.  */
+       mutex_enter(&sc->sc_lock);
+       rescan = sc->sc_rescan;
+       sc->sc_rescan = false;
+       mutex_exit(&sc->sc_lock);
+       if (rescan) {
+               for (port = 1; port <= hd->bNbrPorts; port++) {
+                       subdev = dev->ud_hub->uh_ports[port - 1].up_dev;
+                       if (subdev == NULL)
+                               continue;
+                       usbd_reattach_device(sc->sc_dev, subdev, port, NULL);
+               }
+       }
 
        if (PORTSTAT_ISSET(sc, 0)) { /* hub status change */
                usb_hub_status_t hs;
@@ -851,7 +825,6 @@
                }
        }
        mutex_exit(&sc->sc_lock);
-       uhub_explore_exit(sc);
        if (sc->sc_first_explore) {
                config_pending_decr(sc->sc_dev);
                sc->sc_first_explore = false;
@@ -928,26 +901,17 @@
 uhub_rescan(device_t self, const char *ifattr, const int *locators)
 {
        struct uhub_softc *sc = device_private(self);
-       struct usbd_hub *hub = sc->sc_hub->ud_hub;
-       struct usbd_device *dev;
-       int port;
 
        UHUBHIST_FUNC();
        UHUBHIST_CALLARGS("uhub%jd", device_unit(sc->sc_dev), 0, 0, 0);
 
        KASSERT(KERNEL_LOCKED_P());
 
-       if (uhub_explore_enter(sc) != 0)
-               return EBUSY;
-       for (port = 1; port <= hub->uh_hubdesc.bNbrPorts; port++) {
-               dev = hub->uh_ports[port - 1].up_dev;
-               if (dev == NULL)
-                       continue;
-               usbd_reattach_device(sc->sc_dev, dev, port, locators);
-       }
-       uhub_explore_exit(sc);
-
-       /* Arrange to recursively explore hubs we may have found.  */
+       /* Trigger bus exploration.  */
+       /* XXX locators */
+       mutex_enter(&sc->sc_lock);
+       sc->sc_rescan = true;
+       mutex_exit(&sc->sc_lock);
        usb_needs_explore(sc->sc_hub);
 
        return 0;



Home | Main Index | Thread Index | Old Index