Module Name:    src
Committed By:   riastradh
Date:           Thu Mar  3 06:12:11 UTC 2022

Modified Files:
        src/sys/arch/mips/adm5120/dev: ahci.c
        src/sys/dev/ic: sl811hs.c
        src/sys/dev/usb: ehci.c motg.c ohci.c uhci.c usbdi.c usbdivar.h
            usbroothub.c vhci.c xhci.c
        src/sys/external/bsd/dwc2: dwc2.c
        src/sys/rump/dev/lib/libugenhc: ugenhc.c

Log Message:
usb: Hold pipe lock across upm_transfer and upm_start.

This simplifies the code and fixes races with abort.  Access to the
pipe's queue is now done exclusively while the pipe is locked.


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/mips/adm5120/dev/ahci.c
cvs rdiff -u -r1.109 -r1.110 src/sys/dev/ic/sl811hs.c
cvs rdiff -u -r1.304 -r1.305 src/sys/dev/usb/ehci.c
cvs rdiff -u -r1.39 -r1.40 src/sys/dev/usb/motg.c
cvs rdiff -u -r1.320 -r1.321 src/sys/dev/usb/ohci.c
cvs rdiff -u -r1.310 -r1.311 src/sys/dev/usb/uhci.c
cvs rdiff -u -r1.230 -r1.231 src/sys/dev/usb/usbdi.c
cvs rdiff -u -r1.133 -r1.134 src/sys/dev/usb/usbdivar.h
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/usb/usbroothub.c
cvs rdiff -u -r1.24 -r1.25 src/sys/dev/usb/vhci.c
cvs rdiff -u -r1.157 -r1.158 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.79 -r1.80 src/sys/external/bsd/dwc2/dwc2.c
cvs rdiff -u -r1.30 -r1.31 src/sys/rump/dev/lib/libugenhc/ugenhc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/adm5120/dev/ahci.c
diff -u src/sys/arch/mips/adm5120/dev/ahci.c:1.29 src/sys/arch/mips/adm5120/dev/ahci.c:1.30
--- src/sys/arch/mips/adm5120/dev/ahci.c:1.29	Thu Mar  3 06:04:31 2022
+++ src/sys/arch/mips/adm5120/dev/ahci.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ahci.c,v 1.29 2022/03/03 06:04:31 riastradh Exp $	*/
+/*	$NetBSD: ahci.c,v 1.30 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.29 2022/03/03 06:04:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.30 2022/03/03 06:12:11 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -569,6 +569,8 @@ ahci_roothub_ctrl(struct usbd_bus *bus, 
 
 	DPRINTF(D_TRACE, ("SLRCstart "));
 
+	KASSERT(bus->ub_polling || mutex_owned(bus->ub_lock));
+
 	len = UGETW(req->wLength);
 	value = UGETW(req->wValue);
 	index = UGETW(req->wIndex);
@@ -743,13 +745,13 @@ ahci_root_intr_start(struct usbd_xfer *x
 
 	DPRINTF(D_TRACE, ("SLRIstart "));
 
-	mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
+
 	KASSERT(sc->sc_intr_xfer == NULL);
 	sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval);
 	callout_schedule(&sc->sc_poll_handle, sc->sc_interval);
 	sc->sc_intr_xfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -834,11 +836,11 @@ ahci_device_ctrl_start(struct usbd_xfer 
 	struct ahci_softc *sc = AHCI_XFER2SC(xfer);
 	int len, isread;
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
 
 #if 0
 	struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
 #endif
-	mutex_enter(&sc->sc_lock);
 /*	printf("ctrl_start>>>\n"); */
 
 #ifdef DIAGNOSTIC
@@ -968,7 +970,6 @@ ahci_device_ctrl_start(struct usbd_xfer 
 /* 	printf("ctrl_start<<<\n"); */
 
 	usb_transfer_complete(xfer);
-	mutex_exit(&sc->sc_lock);
 
 	usb_freemem(&reqdma);
 
@@ -1006,11 +1007,14 @@ ahci_device_intr_transfer(struct usbd_xf
 static usbd_status
 ahci_device_intr_start(struct usbd_xfer *xfer)
 {
+	struct ahci_softc *sc = AHCI_XFER2SC(xfer);
 	struct usbd_pipe *pipe = xfer->ux_pipe;
 	struct ahci_xfer *sx;
 
 	DPRINTF(D_TRACE, ("INTRstart "));
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
+
 	sx = kmem_intr_alloc(sizeof(*sx), KM_NOSLEEP);
 	if (sx == NULL)
 		goto reterr;
@@ -1156,6 +1160,8 @@ ahci_device_bulk_start(struct usbd_xfer 
 #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
 	DPRINTF(D_TRACE, ("st "));
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
+
 #ifdef DIAGNOSTIC
 	if (xfer->ux_rqflags & URQ_REQUEST) {
 		/* XXX panic */
@@ -1164,7 +1170,6 @@ ahci_device_bulk_start(struct usbd_xfer 
 	}
 #endif
 
-	mutex_enter(&sc->sc_lock);
 	level++;
 /* 	printf("bulk_start>>>\n"); */
 
@@ -1291,7 +1296,6 @@ ahci_device_bulk_start(struct usbd_xfer 
 		    isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
 
 	usb_transfer_complete(xfer);
-	mutex_exit(&sc->sc_lock);
 
 	return USBD_NORMAL_COMPLETION;
 }

Index: src/sys/dev/ic/sl811hs.c
diff -u src/sys/dev/ic/sl811hs.c:1.109 src/sys/dev/ic/sl811hs.c:1.110
--- src/sys/dev/ic/sl811hs.c:1.109	Thu Mar  3 06:04:31 2022
+++ src/sys/dev/ic/sl811hs.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: sl811hs.c,v 1.109 2022/03/03 06:04:31 riastradh Exp $	*/
+/*	$NetBSD: sl811hs.c,v 1.110 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Not (c) 2007 Matthew Orgass
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.109 2022/03/03 06:04:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.110 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_slhci.h"
@@ -846,10 +846,6 @@ slhci_transfer(struct usbd_xfer *xfer)
 	    0);
 
 	/* Pipe isn't running, so start it first.  */
-
-	/*
-	 * Start will take the lock.
-	 */
 	error = xfer->ux_pipe->up_methods->upm_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
 
 	return error;
@@ -867,7 +863,7 @@ slhci_start(struct usbd_xfer *xfer)
 	usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
 	unsigned int max_packet;
 
-	mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
 
 	max_packet = UGETW(ed->wMaxPacketSize);
 
@@ -989,8 +985,6 @@ slhci_start(struct usbd_xfer *xfer)
 
 	slhci_start_entry(sc, spipe);
 
-	mutex_exit(&sc->sc_lock);
-
 	return USBD_IN_PROGRESS;
 }
 
@@ -1012,13 +1006,13 @@ slhci_root_start(struct usbd_xfer *xfer)
 	DLOG(D_TRACE, "transfer type %jd start",
 	    SLHCI_XFER_TYPE(xfer), 0, 0, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	KASSERT(spipe->ptype == PT_ROOT_INTR);
 
-	mutex_enter(&sc->sc_intr_lock);
 	KASSERT(t->rootintr == NULL);
 	t->rootintr = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_intr_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3201,6 +3195,8 @@ slhci_roothub_ctrl(struct usbd_bus *bus,
 	uint8_t type;
 	int actlen = 0;
 
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	len = UGETW(req->wLength);
 	value = UGETW(req->wValue);
 	index = UGETW(req->wIndex);

Index: src/sys/dev/usb/ehci.c
diff -u src/sys/dev/usb/ehci.c:1.304 src/sys/dev/usb/ehci.c:1.305
--- src/sys/dev/usb/ehci.c:1.304	Thu Mar  3 06:08:50 2022
+++ src/sys/dev/usb/ehci.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehci.c,v 1.304 2022/03/03 06:08:50 riastradh Exp $ */
+/*	$NetBSD: ehci.c,v 1.305 2022/03/03 06:12:11 riastradh Exp $ */
 
 /*
  * Copyright (c) 2004-2012,2016,2020 The NetBSD Foundation, Inc.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.304 2022/03/03 06:08:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.305 2022/03/03 06:12:11 riastradh Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -2369,6 +2369,8 @@ ehci_roothub_ctrl(struct usbd_bus *bus, 
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	if (sc->sc_dying)
 		return -1;
 
@@ -2757,18 +2759,15 @@ Static usbd_status
 ehci_root_intr_start(struct usbd_xfer *xfer)
 {
 	ehci_softc_t *sc = EHCI_XFER2SC(xfer);
-	const bool polling = sc->sc_bus.ub_usepolling;
+
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
 
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3607,10 +3606,10 @@ ehci_device_ctrl_start(struct usbd_xfer 
 	ehci_softc_t *sc = EHCI_XFER2SC(xfer);
 	ehci_soft_qtd_t *setup, *status, *next;
 	ehci_soft_qh_t *sqh;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
 	KASSERT(xfer->ux_rqflags & URQ_REQUEST);
 
 	if (sc->sc_dying)
@@ -3729,16 +3728,11 @@ ehci_device_ctrl_start(struct usbd_xfer 
 	DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0);
 #endif
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	/* Insert qTD in QH list - also does usb_syncmem(sqh) */
 	ehci_set_qh_qtd(sqh, setup);
 	usbd_xfer_schedule_timeout(xfer);
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 #if 0
 #ifdef EHCI_DEBUG
@@ -3878,13 +3872,14 @@ ehci_device_bulk_start(struct usbd_xfer 
 	ehci_soft_qh_t *sqh;
 	ehci_soft_qtd_t *end;
 	int len, isread, endpt;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
 	DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length,
 	    xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -3901,10 +3896,6 @@ ehci_device_bulk_start(struct usbd_xfer 
 	exfer->ex_isdone = false;
 #endif
 
-	/* Take lock here to protect nexttoggle */
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end);
 
 	exfer->ex_sqtdend = end;
@@ -3928,8 +3919,6 @@ ehci_device_bulk_start(struct usbd_xfer 
 	usbd_xfer_schedule_timeout(xfer);
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 #if 0
 #ifdef EHCI_DEBUG
@@ -4082,13 +4071,14 @@ ehci_device_intr_start(struct usbd_xfer 
 	ehci_soft_qtd_t *end;
 	ehci_soft_qh_t *sqh;
 	int len, isread, endpt;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
 	DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length,
 	    xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -4105,10 +4095,6 @@ ehci_device_intr_start(struct usbd_xfer 
 	exfer->ex_isdone = false;
 #endif
 
-	/* Take lock to protect nexttoggle */
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end);
 
 	end->qtd.qtd_status |= htole32(EHCI_QTD_IOC);
@@ -4132,8 +4118,6 @@ ehci_device_intr_start(struct usbd_xfer 
 	usbd_xfer_schedule_timeout(xfer);
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 #if 0
 #ifdef EHCI_DEBUG
@@ -4325,6 +4309,8 @@ ehci_device_fs_isoc_transfer(struct usbd
 	DPRINTF("xfer %#jx len %jd flags %jd", (uintptr_t)xfer, xfer->ux_length,
 	    xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -4458,8 +4444,6 @@ ehci_device_fs_isoc_transfer(struct usbd
 	 * more than the period frame list.
 	 */
 
-	mutex_enter(&sc->sc_lock);
-
 	/* Start inserting frames */
 	if (epipe->isoc.cur_xfers > 0) {
 		frindex = epipe->isoc.next_frame;
@@ -4522,7 +4506,6 @@ ehci_device_fs_isoc_transfer(struct usbd
 
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -4690,6 +4673,8 @@ ehci_device_isoc_transfer(struct usbd_xf
 
 	DPRINTF("xfer %#jx flags %jd", (uintptr_t)xfer, xfer->ux_flags, 0, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -4836,8 +4821,6 @@ ehci_device_isoc_transfer(struct usbd_xf
 	 * more than the period frame list.
 	 */
 
-	mutex_enter(&sc->sc_lock);
-
 	/* Start inserting frames */
 	if (epipe->isoc.cur_xfers > 0) {
 		frindex = epipe->isoc.next_frame;
@@ -4905,7 +4888,6 @@ ehci_device_isoc_transfer(struct usbd_xf
 
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }

Index: src/sys/dev/usb/motg.c
diff -u src/sys/dev/usb/motg.c:1.39 src/sys/dev/usb/motg.c:1.40
--- src/sys/dev/usb/motg.c:1.39	Thu Mar  3 06:08:50 2022
+++ src/sys/dev/usb/motg.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: motg.c,v 1.39 2022/03/03 06:08:50 riastradh Exp $	*/
+/*	$NetBSD: motg.c,v 1.40 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.39 2022/03/03 06:08:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.40 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -806,6 +806,8 @@ motg_roothub_ctrl(struct usbd_bus *bus, 
 
 	MOTGHIST_FUNC(); MOTGHIST_CALLED();
 
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	if (sc->sc_dying)
 		return -1;
 
@@ -1020,23 +1022,20 @@ motg_root_intr_start(struct usbd_xfer *x
 {
 	struct usbd_pipe *pipe = xfer->ux_pipe;
 	struct motg_softc *sc = MOTG_PIPE2SC(pipe);
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	MOTGHIST_FUNC(); MOTGHIST_CALLED();
 
 	DPRINTFN(MD_ROOT, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer,
 	    xfer->ux_length, xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intr_xfer == NULL);
 	sc->sc_intr_xfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -1276,11 +1275,10 @@ static usbd_status
 motg_device_ctrl_start(struct usbd_xfer *xfer)
 {
 	struct motg_softc *sc = MOTG_XFER2SC(xfer);
-	usbd_status err;
-	mutex_enter(&sc->sc_lock);
-	err = motg_device_ctrl_start1(sc);
-	mutex_exit(&sc->sc_lock);
-	return err;
+
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
+	return motg_device_ctrl_start1(sc);
 }
 
 static usbd_status
@@ -1717,15 +1715,14 @@ motg_device_data_start(struct usbd_xfer 
 {
 	struct motg_softc *sc = MOTG_XFER2SC(xfer);
 	struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
-	usbd_status err;
 
 	MOTGHIST_FUNC(); MOTGHIST_CALLED();
 
-	mutex_enter(&sc->sc_lock);
 	DPRINTF("xfer %#jx status %jd", (uintptr_t)xfer, xfer->ux_status, 0, 0);
-	err = motg_device_data_start1(sc, otgpipe->hw_ep);
-	mutex_exit(&sc->sc_lock);
-	return err;
+
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
+	return motg_device_data_start1(sc, otgpipe->hw_ep);
 }
 
 static usbd_status

Index: src/sys/dev/usb/ohci.c
diff -u src/sys/dev/usb/ohci.c:1.320 src/sys/dev/usb/ohci.c:1.321
--- src/sys/dev/usb/ohci.c:1.320	Thu Mar  3 06:08:50 2022
+++ src/sys/dev/usb/ohci.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohci.c,v 1.320 2022/03/03 06:08:50 riastradh Exp $	*/
+/*	$NetBSD: ohci.c,v 1.321 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2005, 2012, 2016, 2020 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.320 2022/03/03 06:08:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.321 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2431,6 +2431,8 @@ ohci_roothub_ctrl(struct usbd_bus *bus, 
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	if (sc->sc_dying)
 		return -1;
 
@@ -2620,18 +2622,15 @@ Static usbd_status
 ohci_root_intr_start(struct usbd_xfer *xfer)
 {
 	ohci_softc_t *sc = OHCI_XFER2SC(xfer);
-	const bool polling = sc->sc_bus.ub_usepolling;
+
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
 
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -2777,10 +2776,11 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	ohci_soft_ed_t *sed;
 	int isread;
 	int len;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -2795,10 +2795,6 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	    req->bmRequestType, req->bRequest, UGETW(req->wValue),
 	    UGETW(req->wIndex));
 
-	/* Need to take lock here for pipe->tail.td */
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	/*
 	 * Use the pipe "tail" TD as our first and loan our first TD to the
 	 * next transfer
@@ -2933,8 +2929,6 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	DPRINTF("done", 0, 0, 0, 0);
 
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3054,10 +3048,11 @@ ohci_device_bulk_start(struct usbd_xfer 
 	ohci_soft_td_t *data, *tail, *tdp;
 	ohci_soft_ed_t *sed;
 	int len, isread, endpt;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -3072,9 +3067,6 @@ ohci_device_bulk_start(struct usbd_xfer 
 	    len, isread, xfer->ux_flags);
 	DPRINTFN(4, "endpt=%jd", endpt, 0, 0, 0);
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	/*
 	 * Use the pipe "tail" TD as our first and loan our first TD to the
 	 * next transfer
@@ -3141,8 +3133,6 @@ ohci_device_bulk_start(struct usbd_xfer 
 	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
 	usbd_xfer_schedule_timeout(xfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3252,10 +3242,11 @@ ohci_device_intr_start(struct usbd_xfer 
 	ohci_soft_ed_t *sed = opipe->sed;
 	ohci_soft_td_t *data, *last, *tail;
 	int len, isread, endpt;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -3268,9 +3259,6 @@ ohci_device_intr_start(struct usbd_xfer 
 	endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress;
 	isread = UE_GET_DIR(endpt) == UE_DIR_IN;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	/*
 	 * Use the pipe "tail" TD as our first and loan our first TD to the
 	 * next transfer.
@@ -3327,8 +3315,6 @@ ohci_device_intr_start(struct usbd_xfer 
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3559,12 +3545,10 @@ ohci_device_isoc_enter(struct usbd_xfer 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 	DPRINTFN(5, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0);
 
-	mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
 
-	if (sc->sc_dying) {
-		mutex_exit(&sc->sc_lock);
+	if (sc->sc_dying)
 		return;
-	}
 
 	struct isoc *isoc = &opipe->isoc;
 
@@ -3723,7 +3707,6 @@ ohci_device_isoc_enter(struct usbd_xfer 
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
 	    sizeof(sed->ed.ed_flags),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-	mutex_exit(&sc->sc_lock);
 }
 
 void

Index: src/sys/dev/usb/uhci.c
diff -u src/sys/dev/usb/uhci.c:1.310 src/sys/dev/usb/uhci.c:1.311
--- src/sys/dev/usb/uhci.c:1.310	Thu Mar  3 06:08:50 2022
+++ src/sys/dev/usb/uhci.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhci.c,v 1.310 2022/03/03 06:08:50 riastradh Exp $	*/
+/*	$NetBSD: uhci.c,v 1.311 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2011, 2012, 2016, 2020 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.310 2022/03/03 06:08:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.311 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2271,7 +2271,6 @@ uhci_device_bulk_start(struct usbd_xfer 
 	uhci_softc_t *sc = UHCI_XFER2SC(xfer);
 	uhci_soft_td_t *data, *dataend;
 	uhci_soft_qh_t *sqh;
-	const bool polling = sc->sc_bus.ub_usepolling;
 	int len;
 	int endpt;
 	int isread;
@@ -2280,6 +2279,8 @@ uhci_device_bulk_start(struct usbd_xfer 
 	DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer,
 	    xfer->ux_length, xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -2291,10 +2292,6 @@ uhci_device_bulk_start(struct usbd_xfer 
 	isread = UE_GET_DIR(endpt) == UE_DIR_IN;
 	sqh = upipe->bulk.sqh;
 
-	/* Take lock here to protect nexttoggle */
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	uhci_reset_std_chain(sc, xfer, len, isread, &upipe->nexttoggle,
 	    &dataend);
 
@@ -2328,8 +2325,6 @@ uhci_device_bulk_start(struct usbd_xfer 
 	uhci_add_intr_list(sc, ux);
 	usbd_xfer_schedule_timeout(xfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -2495,12 +2490,13 @@ uhci_device_ctrl_start(struct usbd_xfer 
 	int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress;
 	uhci_soft_td_t *setup, *stat, *next, *dataend;
 	uhci_soft_qh_t *sqh;
-	const bool polling = sc->sc_bus.ub_usepolling;
 	int len;
 	int isread;
 
 	UHCIHIST_FUNC(); UHCIHIST_CALLED();
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -2523,9 +2519,6 @@ uhci_device_ctrl_start(struct usbd_xfer 
 	memcpy(KERNADDR(&upipe->ctrl.reqdma, 0), req, sizeof(*req));
 	usb_syncmem(&upipe->ctrl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE);
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	/* Set up data transaction */
 	if (len != 0) {
 		upipe->nexttoggle = 1;
@@ -2623,8 +2616,6 @@ uhci_device_ctrl_start(struct usbd_xfer 
 #endif
 	usbd_xfer_schedule_timeout(xfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -2685,18 +2676,19 @@ uhci_device_intr_start(struct usbd_xfer 
 	uhci_softc_t *sc = UHCI_XFER2SC(xfer);
 	uhci_soft_td_t *data, *dataend;
 	uhci_soft_qh_t *sqh;
-	const bool polling = sc->sc_bus.ub_usepolling;
 	int isread, endpt;
 	int i;
 
-	if (sc->sc_dying)
-		return USBD_IOERROR;
-
 	UHCIHIST_FUNC(); UHCIHIST_CALLED();
 
 	DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer,
 	    xfer->ux_length, xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
+	if (sc->sc_dying)
+		return USBD_IOERROR;
+
 	KASSERT(!(xfer->ux_rqflags & URQ_REQUEST));
 	KASSERT(xfer->ux_length <= xfer->ux_bufsize);
 
@@ -2711,8 +2703,6 @@ uhci_device_intr_start(struct usbd_xfer 
 #endif
 
 	/* Take lock to protect nexttoggle */
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	uhci_reset_std_chain(sc, xfer, xfer->ux_length, isread,
 	    &upipe->nexttoggle, &dataend);
 
@@ -2744,8 +2734,6 @@ uhci_device_intr_start(struct usbd_xfer 
 	}
 	uhci_add_intr_list(sc, ux);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 #ifdef UHCI_DEBUG
 	if (uhcidebug >= 10) {
@@ -2854,6 +2842,8 @@ uhci_device_isoc_transfer(struct usbd_xf
 	UHCIHIST_FUNC(); UHCIHIST_CALLED();
 	DPRINTFN(5, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	/* insert into schedule, */
 
 	struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe);
@@ -2887,7 +2877,6 @@ uhci_device_isoc_transfer(struct usbd_xf
 		usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length,
 		    rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
 
-	mutex_enter(&sc->sc_lock);
 	next = isoc->next;
 	if (next == -1) {
 		/* Not in use yet, schedule it a few frames ahead. */
@@ -2949,8 +2938,6 @@ uhci_device_isoc_transfer(struct usbd_xf
 #endif
 	uhci_add_intr_list(sc, ux);
 
-	mutex_exit(&sc->sc_lock);
-
 	return USBD_IN_PROGRESS;
 }
 
@@ -3602,6 +3589,8 @@ uhci_roothub_ctrl(struct usbd_bus *bus, 
 
 	UHCIHIST_FUNC(); UHCIHIST_CALLED();
 
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	if (sc->sc_dying)
 		return -1;
 
@@ -3853,18 +3842,16 @@ uhci_root_intr_start(struct usbd_xfer *x
 	struct usbd_pipe *pipe = xfer->ux_pipe;
 	uhci_softc_t *sc = UHCI_PIPE2SC(pipe);
 	unsigned int ival;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	UHCIHIST_FUNC(); UHCIHIST_CALLED();
 	DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length,
 	    xfer->ux_flags, 0);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	KASSERT(sc->sc_intr_xfer == NULL);
 
 	/* XXX temporary variable needed to avoid gcc3 warning */
@@ -3874,9 +3861,6 @@ uhci_root_intr_start(struct usbd_xfer *x
 	sc->sc_intr_xfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
 
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
-
 	return USBD_IN_PROGRESS;
 }
 

Index: src/sys/dev/usb/usbdi.c
diff -u src/sys/dev/usb/usbdi.c:1.230 src/sys/dev/usb/usbdi.c:1.231
--- src/sys/dev/usb/usbdi.c:1.230	Thu Mar  3 06:09:57 2022
+++ src/sys/dev/usb/usbdi.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi.c,v 1.230 2022/03/03 06:09:57 riastradh Exp $	*/
+/*	$NetBSD: usbdi.c,v 1.231 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012, 2015 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.230 2022/03/03 06:09:57 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.231 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -422,13 +422,14 @@ usbd_transfer(struct usbd_xfer *xfer)
 			pipe->up_running = 1;
 			err = USBD_NORMAL_COMPLETION;
 		}
-		usbd_unlock_pipe(pipe);
 		if (err)
 			break;
 		err = pipe->up_methods->upm_transfer(xfer);
 	} while (0);
 	SDT_PROBE3(usb, device, pipe, transfer__done,  pipe, xfer, err);
 
+	usbd_unlock_pipe(pipe);
+
 	if (err != USBD_IN_PROGRESS && err) {
 		/*
 		 * The transfer made it onto the pipe queue, but didn't get
@@ -1190,12 +1191,8 @@ usbd_start_next(struct usbd_pipe *pipe)
 	if (xfer == NULL) {
 		pipe->up_running = 0;
 	} else {
-		if (!polling)
-			mutex_exit(pipe->up_dev->ud_bus->ub_lock);
 		SDT_PROBE2(usb, device, pipe, start,  pipe, xfer);
 		err = pipe->up_methods->upm_start(xfer);
-		if (!polling)
-			mutex_enter(pipe->up_dev->ud_bus->ub_lock);
 
 		if (err != USBD_IN_PROGRESS) {
 			USBHIST_LOG(usbdebug, "error = %jd", err, 0, 0, 0);

Index: src/sys/dev/usb/usbdivar.h
diff -u src/sys/dev/usb/usbdivar.h:1.133 src/sys/dev/usb/usbdivar.h:1.134
--- src/sys/dev/usb/usbdivar.h:1.133	Thu Mar  3 06:09:20 2022
+++ src/sys/dev/usb/usbdivar.h	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdivar.h,v 1.133 2022/03/03 06:09:20 riastradh Exp $	*/
+/*	$NetBSD: usbdivar.h,v 1.134 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
@@ -51,14 +51,14 @@
  *	ubm_abortx		x	must not release/reacquire lock
  *	ubm_getlock 		-	Called at attach time
  *	ubm_newdev		-	Will take lock
- *	ubm_rhctrl
+ *	ubm_rhctrl              x
  *
  *	PIPE METHOD		LOCK	NOTES
  *	----------------------- -------	-------------------------
  *	upm_init		-
  *	upm_fini		-
- *	upm_transfer		-
- *	upm_start		-	might want to take lock?
+ *	upm_transfer		x
+ *	upm_start		x
  *	upm_abort		x
  *	upm_close		x
  *	upm_cleartoggle		-

Index: src/sys/dev/usb/usbroothub.c
diff -u src/sys/dev/usb/usbroothub.c:1.12 src/sys/dev/usb/usbroothub.c:1.13
--- src/sys/dev/usb/usbroothub.c:1.12	Thu Mar  3 06:04:31 2022
+++ src/sys/dev/usb/usbroothub.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: usbroothub.c,v 1.12 2022/03/03 06:04:31 riastradh Exp $ */
+/* $NetBSD: usbroothub.c,v 1.13 2022/03/03 06:12:11 riastradh Exp $ */
 
 /*-
  * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.12 2022/03/03 06:04:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.13 2022/03/03 06:12:11 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>		/* for ostype */
@@ -361,6 +361,13 @@ roothub_ctrl_start(struct usbd_xfer *xfe
 
 	USBHIST_FUNC();
 
+	/*
+	 * XXX Should really assert pipe lock, in case ever have
+	 * per-pipe locking instead of using the bus lock for all
+	 * pipes.
+	 */
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	KASSERT(xfer->ux_rqflags & URQ_REQUEST);
 	req = &xfer->ux_request;
 
@@ -554,9 +561,7 @@ roothub_ctrl_start(struct usbd_xfer *xfe
 	    (uintptr_t)xfer, buflen, actlen, err);
 
 	xfer->ux_status = err;
-	mutex_enter(bus->ub_lock);
 	usb_transfer_complete(xfer);
-	mutex_exit(bus->ub_lock);
 
 	return USBD_NORMAL_COMPLETION;
 }

Index: src/sys/dev/usb/vhci.c
diff -u src/sys/dev/usb/vhci.c:1.24 src/sys/dev/usb/vhci.c:1.25
--- src/sys/dev/usb/vhci.c:1.24	Thu Mar  3 06:04:31 2022
+++ src/sys/dev/usb/vhci.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vhci.c,v 1.24 2022/03/03 06:04:31 riastradh Exp $ */
+/*	$NetBSD: vhci.c,v 1.25 2022/03/03 06:12:11 riastradh Exp $ */
 
 /*
  * Copyright (c) 2019-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.24 2022/03/03 06:04:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.25 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -605,7 +605,6 @@ vhci_device_ctrl_start(struct usbd_xfer 
 	struct usbd_device *dev = xfer->ux_pipe->up_dev;
 	vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
 	vhci_port_t *port;
-	bool polling = sc->sc_bus.ub_usepolling;
 	bool isread = (req->bmRequestType & UT_READ) != 0;
 	uint8_t addr = UE_GET_ADDR(ed->bEndpointAddress);
 	int portno, ret;
@@ -618,14 +617,13 @@ vhci_device_ctrl_start(struct usbd_xfer 
 	DPRINTF("%s: type=0x%02x, len=%d, isread=%d, portno=%d\n",
 	    __func__, req->bmRequestType, UGETW(req->wLength), isread, portno);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
 	port = &sc->sc_port[portno];
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
-
 	mutex_enter(&port->lock);
 	if (port->status & UPS_PORT_ENABLED) {
 		xfer->ux_status = USBD_IN_PROGRESS;
@@ -636,9 +634,6 @@ vhci_device_ctrl_start(struct usbd_xfer 
 	}
 	mutex_exit(&port->lock);
 
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
-
 	return ret;
 }
 
@@ -709,20 +704,17 @@ static usbd_status
 vhci_root_intr_start(struct usbd_xfer *xfer)
 {
 	vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	DPRINTF("%s: called, len=%zu\n", __func__, (size_t)xfer->ux_length);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }

Index: src/sys/dev/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.157 src/sys/dev/usb/xhci.c:1.158
--- src/sys/dev/usb/xhci.c:1.157	Thu Mar  3 06:08:50 2022
+++ src/sys/dev/usb/xhci.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.157 2022/03/03 06:08:50 riastradh Exp $	*/
+/*	$NetBSD: xhci.c,v 1.158 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.157 2022/03/03 06:08:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.158 2022/03/03 06:12:11 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2186,7 +2186,6 @@ xhci_pipe_async_task(void *cookie)
 	struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv;
 	const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc);
 	struct xhci_ring * const tr = xs->xs_xr[dci];
-	bool restart = false;
 
 	XHCIHIST_FUNC();
 	XHCIHIST_CALLARGS("pipe %#jx slot %ju dci %ju",
@@ -2227,31 +2226,18 @@ xhci_pipe_async_task(void *cookie)
 
 	/*
 	 * If we halted our own queue because it stalled, mark it no
-	 * longer halted and arrange to start it up again.
+	 * longer halted and start issuing queued transfers again.
 	 */
 	if (tr->is_halted) {
+		struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue);
+
 		tr->is_halted = false;
-		if (!SIMPLEQ_EMPTY(&pipe->up_queue))
-			restart = true;
+		if (xfer)
+			(*pipe->up_methods->upm_start)(xfer);
 	}
 
 	mutex_exit(&sc->sc_lock);
 
-	/*
-	 * If the endpoint was stalled, start issuing queued transfers
-	 * again.
-	 */
-	if (restart) {
-		/*
-		 * XXX Shouldn't touch the queue unlocked -- upm_start
-		 * should be called with the lock held instead.  The
-		 * pipe could be aborted at this point, and the xfer
-		 * freed.
-		 */
-		struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue);
-		(*pipe->up_methods->upm_start)(xfer);
-	}
-
 	DPRINTFN(4, "ends", 0, 0, 0, 0);
 }
 
@@ -3870,6 +3856,8 @@ xhci_roothub_ctrl(struct usbd_bus *bus, 
 
 	XHCIHIST_FUNC();
 
+	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
+
 	if (sc->sc_dying)
 		return -1;
 
@@ -4139,20 +4127,17 @@ xhci_root_intr_start(struct usbd_xfer *x
 {
 	struct xhci_softc * const sc = XHCI_XFER2SC(xfer);
 	const size_t bn = XHCI_XFER2BUS(xfer) == &sc->sc_bus ? 0 : 1;
-	const bool polling = xhci_polling_p(sc);
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
+	KASSERT(xhci_polling_p(sc) || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer[bn] == NULL);
 	sc->sc_intrxfer[bn] = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -4250,14 +4235,14 @@ xhci_device_ctrl_start(struct usbd_xfer 
 	    req->bmRequestType | (req->bRequest << 8), UGETW(req->wValue),
 	    UGETW(req->wIndex), UGETW(req->wLength));
 
+	KASSERT(polling || mutex_owned(&sc->sc_lock));
+
 	/* we rely on the bottom bits for extra info */
 	KASSERTMSG(((uintptr_t)xfer & 0x3) == 0x0, "xfer %zx",
 	    (uintptr_t) xfer);
 
 	KASSERT((xfer->ux_rqflags & URQ_REQUEST) != 0);
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	if (tr->is_halted)
 		goto out;
 
@@ -4315,8 +4300,6 @@ out:	if (xfer->ux_status == USBD_NOT_STA
 		 */
 	}
 	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -4388,6 +4371,8 @@ xhci_device_isoc_enter(struct usbd_xfer 
 	XHCIHIST_CALLARGS("%#jx slot %ju dci %ju",
 	    (uintptr_t)xfer, xs->xs_idx, dci, 0);
 
+	KASSERT(polling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
@@ -4460,13 +4445,9 @@ xhci_device_isoc_enter(struct usbd_xfer 
 	if (!polling)
 		mutex_exit(&tr->xr_lock);
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	xfer->ux_status = USBD_IN_PROGRESS;
 	xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci);
 	usbd_xfer_schedule_timeout(xfer);
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -4536,13 +4517,13 @@ xhci_device_bulk_start(struct usbd_xfer 
 	XHCIHIST_CALLARGS("%#jx slot %ju dci %ju",
 	    (uintptr_t)xfer, xs->xs_idx, dci, 0);
 
+	KASSERT(polling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
 	KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0);
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	if (tr->is_halted)
 		goto out;
 
@@ -4590,8 +4571,6 @@ out:	if (xfer->ux_status == USBD_NOT_STA
 		 */
 	}
 	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -4661,11 +4640,11 @@ xhci_device_intr_start(struct usbd_xfer 
 	XHCIHIST_CALLARGS("%#jx slot %ju dci %ju",
 	    (uintptr_t)xfer, xs->xs_idx, dci, 0);
 
+	KASSERT(polling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	if (tr->is_halted)
 		goto out;
 
@@ -4703,8 +4682,6 @@ out:	if (xfer->ux_status == USBD_NOT_STA
 		 */
 	}
 	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }

Index: src/sys/external/bsd/dwc2/dwc2.c
diff -u src/sys/external/bsd/dwc2/dwc2.c:1.79 src/sys/external/bsd/dwc2/dwc2.c:1.80
--- src/sys/external/bsd/dwc2/dwc2.c:1.79	Thu Mar  3 06:08:50 2022
+++ src/sys/external/bsd/dwc2/dwc2.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: dwc2.c,v 1.79 2022/03/03 06:08:50 riastradh Exp $	*/
+/*	$NetBSD: dwc2.c,v 1.80 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.79 2022/03/03 06:08:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.80 2022/03/03 06:12:11 riastradh Exp $");
 
 #include "opt_usb.h"
 
@@ -620,20 +620,17 @@ Static usbd_status
 dwc2_root_intr_start(struct usbd_xfer *xfer)
 {
 	struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	DPRINTF("\n");
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
 	xfer->ux_status = USBD_IN_PROGRESS;
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -709,17 +706,13 @@ dwc2_device_ctrl_start(struct usbd_xfer 
 {
 	struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
 	usbd_status err;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
 	DPRINTF("\n");
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	xfer->ux_status = USBD_IN_PROGRESS;
 	err = dwc2_device_start(xfer);
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
-
 	if (err)
 		return err;
 
@@ -760,18 +753,12 @@ dwc2_device_ctrl_done(struct usbd_xfer *
 Static usbd_status
 dwc2_device_bulk_transfer(struct usbd_xfer *xfer)
 {
-	struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
-	usbd_status err;
 
 	DPRINTF("xfer=%p\n", xfer);
 
-	mutex_enter(&sc->sc_lock);
 	KASSERT(xfer->ux_status == USBD_NOT_STARTED);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	err = dwc2_device_start(xfer);
-	mutex_exit(&sc->sc_lock);
-
-	return err;
+	return dwc2_device_start(xfer);
 }
 
 Static void
@@ -820,15 +807,11 @@ dwc2_device_intr_start(struct usbd_xfer 
 	struct usbd_device *dev = dpipe->pipe.up_dev;
 	struct dwc2_softc *sc = dev->ud_bus->ub_hcpriv;
 	usbd_status err;
-	const bool polling = sc->sc_bus.ub_usepolling;
 
-	if (!polling)
-		mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	xfer->ux_status = USBD_IN_PROGRESS;
 	err = dwc2_device_start(xfer);
-	if (!polling)
-		mutex_exit(&sc->sc_lock);
-
 	if (err)
 		return err;
 
@@ -868,18 +851,12 @@ dwc2_device_intr_done(struct usbd_xfer *
 usbd_status
 dwc2_device_isoc_transfer(struct usbd_xfer *xfer)
 {
-	struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
-	usbd_status err;
 
 	DPRINTF("xfer=%p\n", xfer);
 
-	mutex_enter(&sc->sc_lock);
 	KASSERT(xfer->ux_status == USBD_NOT_STARTED);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	err = dwc2_device_start(xfer);
-	mutex_exit(&sc->sc_lock);
-
-	return err;
+	return dwc2_device_start(xfer);
 }
 
 void
@@ -933,6 +910,8 @@ dwc2_device_start(struct usbd_xfer *xfer
 
 	DPRINTFN(1, "xfer=%p pipe=%p\n", xfer, xfer->ux_pipe);
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	if (xfertype == UE_ISOCHRONOUS ||
 	    xfertype == UE_INTERRUPT) {
 		mutex_spin_enter(&hsotg->lock);
@@ -1121,9 +1100,7 @@ dwc2_device_start(struct usbd_xfer *xfer
 				dwc2_hcd_get_ep_bandwidth(hsotg, dpipe),
 				xfer);
 	}
-
 	mutex_spin_exit(&hsotg->lock);
-// 	mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 

Index: src/sys/rump/dev/lib/libugenhc/ugenhc.c
diff -u src/sys/rump/dev/lib/libugenhc/ugenhc.c:1.30 src/sys/rump/dev/lib/libugenhc/ugenhc.c:1.31
--- src/sys/rump/dev/lib/libugenhc/ugenhc.c:1.30	Thu Mar  3 06:04:31 2022
+++ src/sys/rump/dev/lib/libugenhc/ugenhc.c	Thu Mar  3 06:12:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ugenhc.c,v 1.30 2022/03/03 06:04:31 riastradh Exp $	*/
+/*	$NetBSD: ugenhc.c,v 1.31 2022/03/03 06:12:11 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.30 2022/03/03 06:04:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.31 2022/03/03 06:12:11 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -227,6 +227,8 @@ rumpusb_device_ctrl_start(struct usbd_xf
 	int err = 0;
 	int ru_error, mightfail = 0;
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	len = totlen = UGETW(req->wLength);
 	if (len)
 		buf = xfer->ux_buf;
@@ -391,9 +393,7 @@ rumpusb_device_ctrl_start(struct usbd_xf
 
  ret:
 	xfer->ux_status = err;
-	mutex_enter(&sc->sc_lock);
 	usb_transfer_complete(xfer);
-	mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -516,7 +516,8 @@ rumpusb_root_intr_start(struct usbd_xfer
 	struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer);
 	int error;
 
-	mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	sc->sc_intrxfer = xfer;
 	if (!sc->sc_rhintr) {
 		error = kthread_create(PRI_NONE, 0, NULL,
@@ -524,7 +525,6 @@ rumpusb_root_intr_start(struct usbd_xfer
 		if (error)
 			xfer->ux_status = USBD_IOERROR;
 	}
-	mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -581,6 +581,8 @@ rumpusb_device_bulk_start(struct usbd_xf
 	int xfererr = USBD_NORMAL_COMPLETION;
 	int shortval, i;
 
+	KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+
 	ed = xfer->ux_pipe->up_endpoint->ue_edesc;
 	endpt = ed->bEndpointAddress;
 	isread = UE_GET_DIR(endpt) == UE_DIR_IN;
@@ -667,9 +669,7 @@ rumpusb_device_bulk_start(struct usbd_xf
 		if (done != len)
 			panic("lazy bum");
 	xfer->ux_status = xfererr;
-	mutex_enter(&sc->sc_lock);
 	usb_transfer_complete(xfer);
-	mutex_exit(&sc->sc_lock);
 	return USBD_IN_PROGRESS;
 }
 
@@ -682,9 +682,7 @@ doxfer_kth(void *arg)
 	mutex_enter(&sc->sc_lock);
 	do {
 		struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue);
-		mutex_exit(&sc->sc_lock);
 		rumpusb_device_bulk_start(xfer);
-		mutex_enter(&sc->sc_lock);
 	} while (!SIMPLEQ_EMPTY(&pipe->up_queue));
 	mutex_exit(&sc->sc_lock);
 	kthread_exit(0);

Reply via email to