From 53a9ce15e887839dd9d61478628d0bf5ea28cfef Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 20 Mar 2022 00:30:23 +0000 Subject: [PATCH] usbdi(9): Make sure aborting a pipe waits for all callbacks. There may be a callback in flight from an xfer that has already been taken off the queue by the time usbd_ar_pipe gets to it. We must guarantee that even that callback has completed before returning control to the caller. --- sys/dev/usb/usbdi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 6f564f2ccc8f..592147dc4bd6 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1071,6 +1071,19 @@ usbd_ar_pipe(struct usbd_pipe *pipe) } } + /* + * There may be an xfer callback already in progress which was + * taken off the queue before we got to it. We must wait for + * the callback to finish before returning control to the + * caller. + */ + while (pipe->up_callingxfer) { + USBHIST_LOG(usbdebug, "wait for callback" + "pipe = %#jx xfer = %#jx", + (uintptr_t)pipe, (uintptr_t)pipe->up_callingxfer, 0, 0); + cv_wait(&pipe->up_callingcv, pipe->up_dev->ud_bus->ub_lock); + } + KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock)); KASSERTMSG(pipe->up_abortlwp == curlwp, "pipe->up_abortlwp=%p", pipe->up_abortlwp);