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.
This commit is contained in:
riastradh 2022-03-13 11:28:52 +00:00
parent b88bc827fc
commit a24103789b
3 changed files with 32 additions and 14 deletions

View File

@ -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;
}

View File

@ -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];

View File

@ -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;
/* Nothing to do, all transfers are synchronous. */
KASSERT(mutex_owned(bus->ub_lock));
KASSERTMSG(bus->ub_rhxfer == xfer, "rhxfer=%p", bus->ub_rhxfer);
/*
* 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. */