diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-09-23 06:30:38 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-09-23 06:30:38 +0000 |
commit | da6b92de342708b2bdb157300eb90cbbfff0d218 (patch) | |
tree | 86612b770d663a2c52ae543a3e9b10115eeb937b /sys | |
parent | 73f94e14178edec7b40dbd3bfb5feb42e13e28b2 (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.c | 27 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 11 |
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; |