diff options
author | 2015-01-13 16:03:18 +0000 | |
---|---|---|
committer | 2015-01-13 16:03:18 +0000 | |
commit | 4eeca767fcb716de02b5bd9d8b9aff3787d6e665 (patch) | |
tree | 813e6555f2a39439fdf47b382c2f8e462cad3ea6 /sys/dev/usb/usb.c | |
parent | bump failure to set the initial time from debug to warning (diff) | |
download | wireguard-openbsd-4eeca767fcb716de02b5bd9d8b9aff3787d6e665.tar.xz wireguard-openbsd-4eeca767fcb716de02b5bd9d8b9aff3787d6e665.zip |
Always allow abort tasks to be scheduled, even if the device is beeing
detached, in order to prevent a deadlock situation.
This situation can occur if the thread detaching a device is sleeping,
waiting for all submitted transfers to finish, and the device's pipes
have not yet been aborted. This can happen when a USB Ethernet device
is being detached while a userland program is doing an ioctl(2).
Abort tasks need to be able to run in such case since timed out transfers
rely on them to be properly completed.
ok deraadt@
Diffstat (limited to 'sys/dev/usb/usb.c')
-rw-r--r-- | sys/dev/usb/usb.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index ab8ce995603..ed8502a3642 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb.c,v 1.103 2014/12/18 10:44:17 mpi Exp $ */ +/* $OpenBSD: usb.c,v 1.104 2015/01/13 16:03:18 mpi Exp $ */ /* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */ /* @@ -298,8 +298,13 @@ usb_add_task(struct usbd_device *dev, struct usb_task *task) { int s; - /* Don't add task if the device's root hub is dying. */ - if (usbd_is_dying(dev)) + /* + * If the thread detaching ``dev'' is sleeping, waiting + * for all submitted transfers to finish, we must be able + * to enqueue abort tasks. Otherwise timeouts can't give + * back submitted transfers to the stack. + */ + if (usbd_is_dying(dev) && (task->type != USB_TASK_TYPE_ABORT)) return; DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, @@ -455,12 +460,9 @@ usb_abort_task_thread(void *arg) */ task->state |= USB_TASK_STATE_RUN; task->state &= ~USB_TASK_STATE_ONQ; - /* Don't actually execute the task if dying. */ - if (!usbd_is_dying(task->dev)) { - splx(s); - task->fun(task->arg); - s = splusb(); - } + splx(s); + task->fun(task->arg); + s = splusb(); task->state &= ~USB_TASK_STATE_RUN; if (task->state == USB_TASK_STATE_NONE) wakeup(task); |