Module Name: src Committed By: riastradh Date: Sun Jun 13 14:48:10 UTC 2021
Modified Files: src/sys/dev/usb: uhub.c usb.c usb_subr.c usbdi.h Log Message: 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.) To generate a diff of this commit: cvs rdiff -u -r1.152 -r1.153 src/sys/dev/usb/uhub.c cvs rdiff -u -r1.195 -r1.196 src/sys/dev/usb/usb.c cvs rdiff -u -r1.264 -r1.265 src/sys/dev/usb/usb_subr.c cvs rdiff -u -r1.102 -r1.103 src/sys/dev/usb/usbdi.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/uhub.c diff -u src/sys/dev/usb/uhub.c:1.152 src/sys/dev/usb/uhub.c:1.153 --- src/sys/dev/usb/uhub.c:1.152 Sun Jun 13 14:46:07 2021 +++ src/sys/dev/usb/uhub.c Sun Jun 13 14:48:10 2021 @@ -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,10 +269,12 @@ 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(); + KASSERT(usb_in_event_thread(parent)); + + config_pending_incr(self); + sc->sc_dev = self; sc->sc_hub = dev; sc->sc_proto = uaa->uaa_proto; @@ -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; Index: src/sys/dev/usb/usb.c diff -u src/sys/dev/usb/usb.c:1.195 src/sys/dev/usb/usb.c:1.196 --- src/sys/dev/usb/usb.c:1.195 Sat Jun 12 12:13:10 2021 +++ src/sys/dev/usb/usb.c Sun Jun 13 14:48:10 2021 @@ -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 Index: src/sys/dev/usb/usb_subr.c diff -u src/sys/dev/usb/usb_subr.c:1.264 src/sys/dev/usb/usb_subr.c:1.265 --- src/sys/dev/usb/usb_subr.c:1.264 Sun Jun 13 09:12:24 2021 +++ src/sys/dev/usb/usb_subr.c Sun Jun 13 14:48:10 2021 @@ -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, Index: src/sys/dev/usb/usbdi.h diff -u src/sys/dev/usb/usbdi.h:1.102 src/sys/dev/usb/usbdi.h:1.103 --- src/sys/dev/usb/usbdi.h:1.102 Sun Feb 16 09:40:35 2020 +++ src/sys/dev/usb/usbdi.h Sun Jun 13 14:48:10 2021 @@ -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;