diff options
| author | riastradh <riastradh@NetBSD.org> | 2022-03-13 11:28:52 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2022-03-13 11:28:52 +0000 |
| commit | fd6bcfb67366b341462d5ceaa82b8f85796573a5 (patch) | |
| tree | aaff678b22fa00987c7e3bd632e55bf0e59dfc17 /sys/dev | |
| parent | 44daa32b30403f63f3f7e4b3802a63311569e86a (diff) | |
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.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/usb/usb.c | 6 | ||||
| -rw-r--r-- | sys/dev/usb/usbdivar.h | 4 | ||||
| -rw-r--r-- | sys/dev/usb/usbroothub.c | 36 |
3 files changed, 32 insertions, 14 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 86578027331..ac93cda2a57 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -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 self, void *aux) 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; } diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index 6c0b9962afd..2ff3cbe6cfb 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -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]; diff --git a/sys/dev/usb/usbroothub.c b/sys/dev/usb/usbroothub.c index ff396b33a10..bb78bdc3004 100644 --- a/sys/dev/usb/usbroothub.c +++ b/sys/dev/usb/usbroothub.c @@ -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 *xfer) */ 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 *xfer) 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 *xfer) 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. */ |
