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:
parent
b88bc827fc
commit
a24103789b
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue