summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2010-09-23 06:30:38 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2010-09-23 06:30:38 +0000
commitda6b92de342708b2bdb157300eb90cbbfff0d218 (patch)
tree86612b770d663a2c52ae543a3e9b10115eeb937b /sys
parent73f94e14178edec7b40dbd3bfb5feb42e13e28b2 (diff)
add two members to struct usb_task
* usbd_device_handle dev - the device responsible for the task. use this to not run the task if the device's hub is dying. * int running - a flag to be set when the task is running. add usb_rem_wait_task(), a wrapper for usb_rem_task() that waits for the task to complete if the task is already running. s/usb_rem_task/usb_rem_wait_task/ in usb_detach(). probably most drivers using usb_tasks should do this as well. although device attach/detach is serialized in normal cases, in the special case where the usb bus is hotpluggable (like cardbus/pcmcia), devices are not detached in the task thread.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/usb.c27
-rw-r--r--sys/dev/usb/usbdi.h11
2 files changed, 32 insertions, 6 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 166827d019d..dd61f4e4037 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.c,v 1.67 2010/09/23 05:44:15 jakemsr Exp $ */
+/* $OpenBSD: usb.c,v 1.68 2010/09/23 06:30:37 jakemsr Exp $ */
/* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */
/*
@@ -299,6 +299,7 @@ usb_add_task(usbd_device_handle dev, struct usb_task *task)
else
TAILQ_INSERT_TAIL(&usb_tasks, task, next);
task->onqueue = 1;
+ task->dev = dev;
}
wakeup(&usb_run_tasks);
splx(s);
@@ -323,6 +324,22 @@ usb_rem_task(usbd_device_handle dev, struct usb_task *task)
}
void
+usb_rem_wait_task(usbd_device_handle dev, struct usb_task *task)
+{
+ int s;
+
+ DPRINTFN(2,("%s: task=%p onqueue=%d\n", __func__, task, task->onqueue));
+
+ s = splusb();
+ usb_rem_task(dev, task);
+ while (task->running) {
+ DPRINTF(("%s: waiting for task to complete\n", __func__));
+ tsleep(task, PWAIT, "endtask", 0);
+ }
+ splx(s);
+}
+
+void
usb_first_explore(void *arg)
{
struct usb_softc *sc = arg;
@@ -381,9 +398,15 @@ usb_task_thread(void *arg)
continue;
}
task->onqueue = 0;
+ /* Don't execute the task if the root hub is gone. */
+ if (task->dev->bus->dying)
+ continue;
+ task->running = 1;
splx(s);
task->fun(task->arg);
s = splusb();
+ task->running = 0;
+ wakeup(task);
}
splx(s);
@@ -859,7 +882,7 @@ usb_detach(struct device *self, int flags)
if (sc->sc_port.device != NULL)
usb_disconnect_port(&sc->sc_port, self);
- usb_rem_task(sc->sc_bus->root_hub, &sc->sc_explore_task);
+ usb_rem_wait_task(sc->sc_bus->root_hub, &sc->sc_explore_task);
usbd_finish();
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 3b6010250d8..960b380bfa9 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi.h,v 1.33 2009/11/04 19:14:10 kettenis Exp $ */
+/* $OpenBSD: usbdi.h,v 1.34 2010/09/23 06:30:37 jakemsr Exp $ */
/* $NetBSD: usbdi.h,v 1.62 2002/07/11 21:14:35 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */
@@ -181,14 +181,17 @@ const usb_descriptor_t *usb_desc_iter_next(usbd_desc_iter_t *);
*/
struct usb_task {
TAILQ_ENTRY(usb_task) next;
+ usbd_device_handle dev;
void (*fun)(void *);
void *arg;
char onqueue;
+ char running;
};
-void usb_add_task(usbd_device_handle dev, struct usb_task *task);
-void usb_rem_task(usbd_device_handle dev, struct usb_task *task);
-#define usb_init_task(t, f, a) ((t)->fun = (f), (t)->arg = (a), (t)->onqueue = 0)
+void usb_add_task(usbd_device_handle, struct usb_task *);
+void usb_rem_task(usbd_device_handle, struct usb_task *);
+void usb_rem_wait_task(usbd_device_handle, struct usb_task *);
+#define usb_init_task(t, f, a) ((t)->fun = (f), (t)->arg = (a), (t)->onqueue = 0, (t)->running = 0)
struct usb_devno {
u_int16_t ud_vendor;