summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorriastradh <riastradh@NetBSD.org>2021-06-13 14:48:10 +0000
committerriastradh <riastradh@NetBSD.org>2021-06-13 14:48:10 +0000
commit80dbb9305f86bc06b5d7b574492b8569a7422ce0 (patch)
tree53b25e5162b6e361d9de53655ab17f75af7ba8d9 /sys/dev
parent861fb2a61e6fb22d04beb514d90c95a1edbb72b7 (diff)
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 (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/uhub.c12
-rw-r--r--sys/dev/usb/usb.c26
-rw-r--r--sys/dev/usb/usb_subr.c15
-rw-r--r--sys/dev/usb/usbdi.h4
4 files changed, 42 insertions, 15 deletions
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 6f0ac8c0998..628a6b1816d 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -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 self, void *aux)
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;
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 368d72fc9f3..8be68ad747b 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -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 --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 4d1eec36d18..1e14cc7d3a6 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -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, struct usbd_device *dev, int port,
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, struct usbd_device *dev,
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, struct usbd_device *dev,
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, struct usbd_device *dev,
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 usbd_bus *bus, int depth, int speed,
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 --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 4322d75bffd..71d61eca539 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -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_device *, struct usb_task *, int,
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;