Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb usb(4): Bus exploration is single-threaded -- as...



details:   https://anonhg.NetBSD.org/src/rev/53360176b8a3
branches:  trunk
changeset: 379666:53360176b8a3
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Jun 13 14:48:10 2021 +0000

description:
usb(4): Bus exploration is single-threaded -- assert it so.

New usb_in_event_thread(dev) returns true if dev is a USB device --
that is, a device with a usbN ancestor -- and the current thread is
the USB event thread.

(Kinda kludgey to pass around the device_t instead of, say, struct
usbd_bus, but I don't see a good way to get to the usbN device_t or
struct usb_softc from there.)

diffstat:

 sys/dev/usb/uhub.c     |  12 +++++++-----
 sys/dev/usb/usb.c      |  26 ++++++++++++++++++++++++--
 sys/dev/usb/usb_subr.c |  15 ++++++++-------
 sys/dev/usb/usbdi.h    |   4 +++-
 4 files changed, 42 insertions(+), 15 deletions(-)

diffs (186 lines):

diff -r ec11a15f151d -r 53360176b8a3 sys/dev/usb/uhub.c
--- a/sys/dev/usb/uhub.c        Sun Jun 13 14:46:07 2021 +0000
+++ b/sys/dev/usb/uhub.c        Sun Jun 13 14:48:10 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhub.c,v 1.152 2021/06/13 14:46:07 riastradh Exp $     */
+/*     $NetBSD: uhub.c,v 1.153 2021/06/13 14:48:10 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.152 2021/06/13 14:46:07 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.153 2021/06/13 14:48:10 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -269,9 +269,11 @@ uhub_attach(device_t parent, device_t se
        usb_endpoint_descriptor_t *ed;
        struct usbd_tt *tts = NULL;
 
-       config_pending_incr(self);
+       UHUBHIST_FUNC(); UHUBHIST_CALLED();
 
-       UHUBHIST_FUNC(); UHUBHIST_CALLED();
+       KASSERT(usb_in_event_thread(parent));
+
+       config_pending_incr(self);
 
        sc->sc_dev = self;
        sc->sc_hub = dev;
@@ -498,7 +500,7 @@ uhub_explore(struct usbd_device *dev)
            device_unit(sc->sc_dev), (uintptr_t)dev, dev->ud_addr,
            dev->ud_speed);
 
-       KASSERT(KERNEL_LOCKED_P());
+       KASSERT(usb_in_event_thread(sc->sc_dev));
 
        if (!sc->sc_running)
                return USBD_NOT_STARTED;
diff -r ec11a15f151d -r 53360176b8a3 sys/dev/usb/usb.c
--- a/sys/dev/usb/usb.c Sun Jun 13 14:46:07 2021 +0000
+++ b/sys/dev/usb/usb.c Sun Jun 13 14:48:10 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usb.c,v 1.195 2021/06/12 12:13:10 riastradh Exp $      */
+/*     $NetBSD: usb.c,v 1.196 2021/06/13 14:48:10 riastradh Exp $      */
 
 /*
  * Copyright (c) 1998, 2002, 2008, 2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.195 2021/06/12 12:13:10 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.196 2021/06/13 14:48:10 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -142,6 +142,7 @@ struct usb_softc {
        struct usbd_port sc_port;       /* dummy port for root hub */
 
        struct lwp      *sc_event_thread;
+       struct lwp      *sc_attach_thread;
 
        char            sc_dying;
        bool            sc_pmf_registered;
@@ -483,8 +484,10 @@ usb_doattach(device_t self)
        ue->u.ue_ctrlr.ue_bus = device_unit(self);
        usb_add_event(USB_EVENT_CTRLR_ATTACH, ue);
 
+       sc->sc_attach_thread = curlwp;
        err = usbd_new_device(self, sc->sc_bus, 0, speed, 0,
                  &sc->sc_port);
+       sc->sc_attach_thread = NULL;
        if (!err) {
                dev = sc->sc_port.up_dev;
                if (dev->ud_hub == NULL) {
@@ -529,6 +532,25 @@ usb_create_event_thread(device_t self)
        }
 }
 
+bool
+usb_in_event_thread(device_t dev)
+{
+       struct usb_softc *sc;
+
+       if (cold)
+               return true;
+
+       for (; dev; dev = device_parent(dev)) {
+               if (device_is_a(dev, "usb"))
+                       break;
+       }
+       if (dev == NULL)
+               return false;
+       sc = device_private(dev);
+
+       return curlwp == sc->sc_event_thread || curlwp == sc->sc_attach_thread;
+}
+
 /*
  * Add a task to be performed by the task thread.  This function can be
  * called from any context and the task will be executed in a process
diff -r ec11a15f151d -r 53360176b8a3 sys/dev/usb/usb_subr.c
--- a/sys/dev/usb/usb_subr.c    Sun Jun 13 14:46:07 2021 +0000
+++ b/sys/dev/usb/usb_subr.c    Sun Jun 13 14:48:10 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usb_subr.c,v 1.264 2021/06/13 09:12:24 mlelstv Exp $   */
+/*     $NetBSD: usb_subr.c,v 1.265 2021/06/13 14:48:10 riastradh Exp $ */
 /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.264 2021/06/13 09:12:24 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.265 2021/06/13 14:48:10 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -1097,6 +1097,8 @@ usbd_attachwholedevice(device_t parent, 
        device_t dv;
        int dlocs[USBDEVIFCF_NLOCS];
 
+       KASSERT(usb_in_event_thread(parent));
+
        uaa.uaa_device = dev;
        uaa.uaa_usegeneric = usegeneric;
        uaa.uaa_port = port;
@@ -1147,8 +1149,7 @@ usbd_attachinterfaces(device_t parent, s
        int i, j, loc;
        device_t dv;
 
-       /* Needed for access to dev->ud_subdevs.  */
-       KASSERT(KERNEL_LOCKED_P());
+       KASSERT(usb_in_event_thread(parent));
 
        nifaces = dev->ud_cdesc->bNumInterface;
        ifaces = kmem_zalloc(nifaces * sizeof(*ifaces), KM_SLEEP);
@@ -1240,7 +1241,7 @@ usbd_probe_and_attach(device_t parent, s
        int confi, nifaces;
        usbd_status err;
 
-       KASSERT(KERNEL_LOCKED_P());
+       KASSERT(usb_in_event_thread(parent));
 
        /* First try with device specific drivers. */
        err = usbd_attachwholedevice(parent, dev, port, 0);
@@ -1310,7 +1311,7 @@ usbd_reattach_device(device_t parent, st
        USBHIST_CALLARGS(usbdebug, "uhub%jd port=%jd",
            device_unit(parent), port, 0, 0);
 
-       KASSERT(KERNEL_LOCKED_P());
+       KASSERT(usb_in_event_thread(parent));
 
        if (locators != NULL) {
                loc = locators[USBIFIFCF_PORT];
@@ -1370,7 +1371,7 @@ usbd_new_device(device_t parent, struct 
        int i;
        int p;
 
-       KASSERT(KERNEL_LOCKED_P());
+       KASSERT(usb_in_event_thread(parent));
 
        if (bus->ub_methods->ubm_newdev != NULL)
                return (bus->ub_methods->ubm_newdev)(parent, bus, depth, speed,
diff -r ec11a15f151d -r 53360176b8a3 sys/dev/usb/usbdi.h
--- a/sys/dev/usb/usbdi.h       Sun Jun 13 14:46:07 2021 +0000
+++ b/sys/dev/usb/usbdi.h       Sun Jun 13 14:48:10 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usbdi.h,v 1.102 2020/02/16 09:40:35 maxv Exp $ */
+/*     $NetBSD: usbdi.h,v 1.103 2021/06/13 14:48:10 riastradh Exp $    */
 /*     $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $      */
 
 /*
@@ -222,6 +222,8 @@ bool usb_rem_task_wait(struct usbd_devic
 bool usb_task_pending(struct usbd_device *, struct usb_task *);
 #define usb_init_task(t, f, a, fl) ((t)->fun = (f), (t)->arg = (a), (t)->queue = USB_NUM_TASKQS, (t)->flags = (fl))
 
+bool usb_in_event_thread(device_t);
+
 struct usb_devno {
        uint16_t ud_vendor;
        uint16_t ud_product;



Home | Main Index | Thread Index | Old Index