Module Name: src Committed By: riastradh Date: Sun Mar 13 11:28:52 UTC 2022
Modified Files: src/sys/dev/usb: usb.c usbdivar.h usbroothub.c Log Message: usb: Fix roothub ctrl xfer aborts. No mechanism for actually aborting, but at least this now waits for the xfer to have completed instead of blithely barging ahead whether it's done or not. To generate a diff of this commit: cvs rdiff -u -r1.199 -r1.200 src/sys/dev/usb/usb.c cvs rdiff -u -r1.136 -r1.137 src/sys/dev/usb/usbdivar.h cvs rdiff -u -r1.14 -r1.15 src/sys/dev/usb/usbroothub.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/dev/usb/usb.c diff -u src/sys/dev/usb/usb.c:1.199 src/sys/dev/usb/usb.c:1.200 --- src/sys/dev/usb/usb.c:1.199 Sun Mar 6 09:03:42 2022 +++ src/sys/dev/usb/usb.c Sun Mar 13 11:28:52 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.199 2022/03/06 09:03:42 riastradh Exp $ */ +/* $NetBSD: usb.c,v 1.200 2022/03/13 11:28:52 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.199 2022/03/06 09:03:42 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.200 2022/03/13 11:28:52 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -296,6 +296,7 @@ usb_attach(device_t parent, device_t sel usbrev = sc->sc_bus->ub_revision; cv_init(&sc->sc_bus->ub_needsexplore_cv, "usbevt"); + cv_init(&sc->sc_bus->ub_rhxfercv, "usbrhxfer"); sc->sc_pmf_registered = false; aprint_naive("\n"); @@ -1430,6 +1431,7 @@ usb_detach(device_t self, int flags) usb_add_event(USB_EVENT_CTRLR_DETACH, ue); cv_destroy(&sc->sc_bus->ub_needsexplore_cv); + cv_destroy(&sc->sc_bus->ub_rhxfercv); return 0; } Index: src/sys/dev/usb/usbdivar.h diff -u src/sys/dev/usb/usbdivar.h:1.136 src/sys/dev/usb/usbdivar.h:1.137 --- src/sys/dev/usb/usbdivar.h:1.136 Sun Mar 13 11:28:42 2022 +++ src/sys/dev/usb/usbdivar.h Sun Mar 13 11:28:52 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdivar.h,v 1.136 2022/03/13 11:28:42 riastradh Exp $ */ +/* $NetBSD: usbdivar.h,v 1.137 2022/03/13 11:28:52 riastradh Exp $ */ /* * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc. @@ -181,6 +181,8 @@ struct usbd_bus { /* Filled by usb driver */ kmutex_t *ub_lock; struct usbd_device *ub_roothub; + struct usbd_xfer *ub_rhxfer; /* roothub xfer in progress */ + kcondvar_t ub_rhxfercv; uint8_t ub_rhaddr; /* roothub address */ uint8_t ub_rhconf; /* roothub configuration */ struct usbd_device *ub_devices[USB_TOTAL_DEVICES]; Index: src/sys/dev/usb/usbroothub.c diff -u src/sys/dev/usb/usbroothub.c:1.14 src/sys/dev/usb/usbroothub.c:1.15 --- src/sys/dev/usb/usbroothub.c:1.14 Wed Mar 9 22:17:41 2022 +++ src/sys/dev/usb/usbroothub.c Sun Mar 13 11:28:52 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: usbroothub.c,v 1.14 2022/03/09 22:17:41 riastradh Exp $ */ +/* $NetBSD: usbroothub.c,v 1.15 2022/03/13 11:28:52 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.14 2022/03/09 22:17:41 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.15 2022/03/13 11:28:52 riastradh Exp $"); #include <sys/param.h> #include <sys/systm.h> /* for ostype */ @@ -368,6 +368,9 @@ roothub_ctrl_start(struct usbd_xfer *xfe */ KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); + /* Roothub xfers are serialized through the pipe. */ + KASSERTMSG(bus->ub_rhxfer == NULL, "rhxfer=%p", bus->ub_rhxfer); + KASSERT(xfer->ux_rqflags & URQ_REQUEST); req = &xfer->ux_request; @@ -549,19 +552,19 @@ roothub_ctrl_start(struct usbd_xfer *xfe break; } - /* - * XXX This needs some mechanism for concurrent - * roothub_ctrl_abort to wait for ubm_rhctrl to finish. We - * can't use the bus lock because many ubm_rhctrl methods do - * usb_delay_ms and many bus locks are taken in softint - * context, leading to deadlock in the softclock needed to wake - * up usb_delay_ms. - */ + KASSERTMSG(bus->ub_rhxfer == NULL, "rhxfer=%p", bus->ub_rhxfer); + bus->ub_rhxfer = xfer; if (!bus->ub_usepolling) mutex_exit(bus->ub_lock); + actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen); + if (!bus->ub_usepolling) mutex_enter(bus->ub_lock); + KASSERTMSG(bus->ub_rhxfer == xfer, "rhxfer=%p", bus->ub_rhxfer); + bus->ub_rhxfer = NULL; + cv_signal(&bus->ub_rhxfercv); + if (actlen < 0) goto fail; @@ -582,8 +585,19 @@ roothub_ctrl_start(struct usbd_xfer *xfe Static void roothub_ctrl_abort(struct usbd_xfer *xfer) { + struct usbd_bus *bus = xfer->ux_bus; + + KASSERT(mutex_owned(bus->ub_lock)); + KASSERTMSG(bus->ub_rhxfer == xfer, "rhxfer=%p", bus->ub_rhxfer); - /* Nothing to do, all transfers are synchronous. */ + /* + * No mechanism to abort the xfer (would have to coordinate + * with the bus's ubm_rhctrl to be useful, and usually at most + * there's some short bounded delays of a few tens of + * milliseconds), so just wait for it to complete. + */ + while (bus->ub_rhxfer == xfer) + cv_wait(&bus->ub_rhxfercv, bus->ub_lock); } /* Close the root pipe. */