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;

Reply via email to