diff options
-rw-r--r-- | sys/dev/usb/if_otus.c | 48 | ||||
-rw-r--r-- | sys/dev/usb/if_rsu.c | 37 | ||||
-rw-r--r-- | sys/dev/usb/if_run.c | 20 | ||||
-rw-r--r-- | sys/dev/usb/if_urtwn.c | 47 | ||||
-rw-r--r-- | sys/dev/usb/usb.c | 119 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 18 |
6 files changed, 89 insertions, 200 deletions
diff --git a/sys/dev/usb/if_otus.c b/sys/dev/usb/if_otus.c index ed715bb3d29..3348eb98612 100644 --- a/sys/dev/usb/if_otus.c +++ b/sys/dev/usb/if_otus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_otus.c,v 1.28 2011/02/05 18:10:44 jakemsr Exp $ */ +/* $OpenBSD: if_otus.c,v 1.29 2011/02/09 04:25:31 jakemsr Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -243,18 +243,17 @@ otus_detach(struct device *self, int flags) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - s = splusb(); + s = splnet(); + + /* Wait for all queued asynchronous commands to complete. */ + while (sc->cmdq.queued > 0) + tsleep(&sc->cmdq, 0, "cmdq", 0); if (timeout_initialized(&sc->scan_to)) timeout_del(&sc->scan_to); if (timeout_initialized(&sc->calib_to)) timeout_del(&sc->calib_to); - /* Wait for all queued asynchronous commands to complete. */ - usb_rem_wait_task(sc->sc_udev, &sc->sc_task); - - usbd_ref_wait(sc->sc_udev); - if (ifp->if_softc != NULL) { ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ieee80211_ifdetach(ifp); @@ -728,15 +727,8 @@ otus_next_scan(void *arg) { struct otus_softc *sc = arg; - if (usbd_is_dying(sc->sc_udev)) - return; - - usbd_ref_incr(sc->sc_udev); - if (sc->sc_ic.ic_state == IEEE80211_S_SCAN) ieee80211_next_scan(&sc->sc_ic.ic_if); - - usbd_ref_decr(sc->sc_udev); } void @@ -758,6 +750,7 @@ otus_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT; } + wakeup(ring); splx(s); } @@ -811,8 +804,7 @@ otus_newstate_cb(struct otus_softc *sc, void *arg) case IEEE80211_S_SCAN: (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 0); - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_msec(&sc->scan_to, 200); + timeout_add_msec(&sc->scan_to, 200); break; case IEEE80211_S_AUTH: @@ -833,8 +825,7 @@ otus_newstate_cb(struct otus_softc *sc, void *arg) otus_newassoc(ic, ni, 1); /* Start calibration timer. */ - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_sec(&sc->calib_to, 1); + timeout_add_sec(&sc->calib_to, 1); } break; } @@ -1503,11 +1494,6 @@ otus_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ifreq *ifr; int s, error = 0; - if (usbd_is_dying(sc->sc_udev)) - return ENXIO; - - usbd_ref_incr(sc->sc_udev); - s = splnet(); switch (cmd) { @@ -1564,9 +1550,6 @@ otus_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } splx(s); - - usbd_ref_decr(sc->sc_udev); - return error; } @@ -2188,20 +2171,12 @@ otus_calibrate_to(void *arg) struct ieee80211_node *ni; int s; - if (usbd_is_dying(sc->sc_udev)) - return; - - usbd_ref_incr(sc->sc_udev); - s = splnet(); ni = ic->ic_bss; ieee80211_amrr_choose(&sc->amrr, ni, &((struct otus_node *)ni)->amn); splx(s); - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_sec(&sc->calib_to, 1); - - usbd_ref_decr(sc->sc_udev); + timeout_add_sec(&sc->calib_to, 1); } int @@ -2349,7 +2324,8 @@ otus_stop(struct ifnet *ifp) s = splusb(); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* Wait for all queued asynchronous commands to complete. */ - usb_wait_task(sc->sc_udev, &sc->sc_task); + while (sc->cmdq.queued > 0) + tsleep(&sc->cmdq, 0, "cmdq", 0); splx(s); /* Stop Rx. */ diff --git a/sys/dev/usb/if_rsu.c b/sys/dev/usb/if_rsu.c index afcfef86a94..147115c3199 100644 --- a/sys/dev/usb/if_rsu.c +++ b/sys/dev/usb/if_rsu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_rsu.c,v 1.11 2011/02/05 18:10:44 jakemsr Exp $ */ +/* $OpenBSD: if_rsu.c,v 1.12 2011/02/09 04:25:32 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -341,16 +341,12 @@ rsu_detach(struct device *self, int flags) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - s = splusb(); + s = splnet(); + /* Wait for all async commands to complete. */ + rsu_wait_async(sc); if (timeout_initialized(&sc->calib_to)) timeout_del(&sc->calib_to); - - /* Wait for all async commands to complete. */ - usb_rem_wait_task(sc->sc_udev, &sc->sc_task); - - usbd_ref_wait(sc->sc_udev); - if (ifp->if_softc != NULL) { ieee80211_ifdetach(ifp); if_detach(ifp); @@ -541,6 +537,7 @@ rsu_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % RSU_HOST_CMD_RING_COUNT; } + wakeup(ring); splx(s); } @@ -569,7 +566,8 @@ void rsu_wait_async(struct rsu_softc *sc) { /* Wait for all queued asynchronous commands to complete. */ - usb_wait_task(sc->sc_udev, &sc->sc_task); + while (sc->cmdq.queued > 0) + tsleep(&sc->cmdq, 0, "cmdq", 0); } int @@ -804,15 +802,8 @@ rsu_calib_to(void *arg) { struct rsu_softc *sc = arg; - if (usbd_is_dying(sc->sc_udev)) - return; - - usbd_ref_incr(sc->sc_udev); - /* Do it in a process context. */ rsu_do_async(sc, rsu_calib_cb, NULL, 0); - - usbd_ref_decr(sc->sc_udev); } /* ARGSUSED */ @@ -837,8 +828,7 @@ rsu_calib_cb(struct rsu_softc *sc, void *arg) DPRINTFN(8, ("RSSI=%d%%\n", reg >> 4)); } - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_sec(&sc->calib_to, 2); + timeout_add_sec(&sc->calib_to, 2); } int @@ -905,8 +895,7 @@ rsu_newstate_cb(struct rsu_softc *sc, void *arg) ic->ic_bss->ni_txrate = ic->ic_bss->ni_rates.rs_nrates - 1; /* Start periodic calibration. */ - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_sec(&sc->calib_to, 2); + timeout_add_sec(&sc->calib_to, 2); break; } (void)sc->sc_newstate(ic, cmd->state, cmd->arg); @@ -1710,11 +1699,6 @@ rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ifreq *ifr; int s, error = 0; - if (usbd_is_dying(sc->sc_udev)) - return ENXIO; - - usbd_ref_incr(sc->sc_udev); - s = splnet(); switch (cmd) { @@ -1757,9 +1741,6 @@ rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; } splx(s); - - usbd_ref_decr(sc->sc_udev); - return (error); } diff --git a/sys/dev/usb/if_run.c b/sys/dev/usb/if_run.c index 9622756109a..07e071d86e4 100644 --- a/sys/dev/usb/if_run.c +++ b/sys/dev/usb/if_run.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_run.c,v 1.86 2011/02/05 18:10:44 jakemsr Exp $ */ +/* $OpenBSD: if_run.c,v 1.87 2011/02/09 04:25:32 jakemsr Exp $ */ /*- * Copyright (c) 2008-2010 Damien Bergamini <damien.bergamini@free.fr> @@ -600,8 +600,22 @@ run_detach(struct device *self, int flags) timeout_del(&sc->calib_to); /* wait for all queued asynchronous commands to complete */ +#if 0 + while (sc->cmdq.queued > 0) + tsleep(&sc->cmdq, 0, "cmdq", 0); +#endif + /* the async commands are run in a task */ usb_rem_wait_task(sc->sc_udev, &sc->sc_task); + /* but the task might not have run if it did not start before + * usbd_deactivate() was called, so wakeup now. we're + * detaching, no need to try to run more commands. + */ + if (sc->cmdq.queued > 0) { + sc->cmdq.queued = 0; + wakeup(&sc->cmdq); + } + usbd_ref_wait(sc->sc_udev); if (ifp->if_softc != NULL) { @@ -1471,6 +1485,7 @@ run_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % RUN_HOST_CMD_RING_COUNT; } + wakeup(ring); splx(s); } @@ -3519,7 +3534,8 @@ run_stop(struct ifnet *ifp, int disable) s = splusb(); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* wait for all queued asynchronous commands to complete */ - usb_wait_task(sc->sc_udev, &sc->sc_task); + while (sc->cmdq.queued > 0) + tsleep(&sc->cmdq, 0, "cmdq", 0); splx(s); /* disable Tx/Rx */ diff --git a/sys/dev/usb/if_urtwn.c b/sys/dev/usb/if_urtwn.c index 555b4754479..256e4a2a996 100644 --- a/sys/dev/usb/if_urtwn.c +++ b/sys/dev/usb/if_urtwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_urtwn.c,v 1.14 2011/02/05 18:10:44 jakemsr Exp $ */ +/* $OpenBSD: if_urtwn.c,v 1.15 2011/02/09 04:25:32 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -369,18 +369,14 @@ urtwn_detach(struct device *self, int flags) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - s = splusb(); + s = splnet(); + /* Wait for all async commands to complete. */ + urtwn_wait_async(sc); if (timeout_initialized(&sc->scan_to)) timeout_del(&sc->scan_to); if (timeout_initialized(&sc->calib_to)) timeout_del(&sc->calib_to); - - /* Wait for all async commands to complete. */ - usb_rem_wait_task(sc->sc_udev, &sc->sc_task); - - usbd_ref_wait(sc->sc_udev); - if (ifp->if_softc != NULL) { ieee80211_ifdetach(ifp); if_detach(ifp); @@ -596,6 +592,7 @@ urtwn_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % URTWN_HOST_CMD_RING_COUNT; } + wakeup(ring); splx(s); } @@ -624,7 +621,8 @@ void urtwn_wait_async(struct urtwn_softc *sc) { /* Wait for all queued asynchronous commands to complete. */ - usb_wait_task(sc->sc_udev, &sc->sc_task); + while (sc->cmdq.queued > 0) + tsleep(&sc->cmdq, 0, "cmdq", 0); } int @@ -1063,15 +1061,8 @@ urtwn_calib_to(void *arg) { struct urtwn_softc *sc = arg; - if (usbd_is_dying(sc->sc_udev)) - return; - - usbd_ref_incr(sc->sc_udev); - /* Do it in a process context. */ urtwn_do_async(sc, urtwn_calib_cb, NULL, 0); - - usbd_ref_decr(sc->sc_udev); } /* ARGSUSED */ @@ -1092,8 +1083,7 @@ urtwn_calib_cb(struct urtwn_softc *sc, void *arg) /* Do temperature compensation. */ urtwn_temp_calib(sc); - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_sec(&sc->calib_to, 2); + timeout_add_sec(&sc->calib_to, 2); } void @@ -1103,17 +1093,10 @@ urtwn_next_scan(void *arg) struct ieee80211com *ic = &sc->sc_ic; int s; - if (usbd_is_dying(sc->sc_udev)) - return; - - usbd_ref_incr(sc->sc_udev); - s = splnet(); if (ic->ic_state == IEEE80211_S_SCAN) ieee80211_next_scan(&ic->ic_if); splx(s); - - usbd_ref_decr(sc->sc_udev); } int @@ -1202,8 +1185,7 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg) urtwn_read_1(sc, R92C_TXPAUSE) | 0x0f); urtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL); - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_msec(&sc->scan_to, 200); + timeout_add_msec(&sc->scan_to, 200); break; case IEEE80211_S_AUTH: @@ -1281,8 +1263,7 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg) sc->thcal_state = 0; sc->thcal_lctemp = 0; /* Start periodic calibration. */ - if (!usbd_is_dying(sc->sc_udev)) - timeout_add_sec(&sc->calib_to, 2); + timeout_add_sec(&sc->calib_to, 2); break; } (void)sc->sc_newstate(ic, cmd->state, cmd->arg); @@ -1945,11 +1926,6 @@ urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ifreq *ifr; int s, error = 0; - if (usbd_is_dying(sc->sc_udev)) - return ENXIO; - - usbd_ref_incr(sc->sc_udev); - s = splnet(); switch (cmd) { @@ -2002,9 +1978,6 @@ urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; } splx(s); - - usbd_ref_decr(sc->sc_udev); - return (error); } diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 1f3788739dc..af452b9c7e7 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb.c,v 1.73 2011/02/04 08:21:39 jakemsr Exp $ */ +/* $OpenBSD: usb.c,v 1.74 2011/02/09 04:25:32 jakemsr Exp $ */ /* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */ /* @@ -275,15 +275,15 @@ usb_add_task(usbd_device_handle dev, struct usb_task *task) { int s; - DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, - task->state, task->type)); + DPRINTFN(2,("%s: task=%p onqueue=%d type=%d\n", __func__, task, + task->onqueue, task->type)); /* Don't add task if the device's root hub is dying. */ if (usbd_is_dying(dev)) return; s = splusb(); - if (task->state != USB_TASK_STATE_ONQ) { + if (!task->onqueue) { switch (task->type) { case USB_TASK_TYPE_ABORT: TAILQ_INSERT_TAIL(&usb_abort_tasks, task, next); @@ -295,7 +295,7 @@ usb_add_task(usbd_device_handle dev, struct usb_task *task) TAILQ_INSERT_TAIL(&usb_generic_tasks, task, next); break; } - task->state = USB_TASK_STATE_ONQ; + task->onqueue = 1; task->dev = dev; } if (task->type == USB_TASK_TYPE_ABORT) @@ -310,43 +310,38 @@ usb_rem_task(usbd_device_handle dev, struct usb_task *task) { int s; - DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, - task->state, task->type)); - - if (task->state != USB_TASK_STATE_ONQ) - return; + DPRINTFN(2,("%s: task=%p onqueue=%d type=%d\n", __func__, task, + task->onqueue, task->type)); s = splusb(); - - switch (task->type) { - case USB_TASK_TYPE_ABORT: - TAILQ_REMOVE(&usb_abort_tasks, task, next); - break; - case USB_TASK_TYPE_EXPLORE: - TAILQ_REMOVE(&usb_explore_tasks, task, next); - break; - case USB_TASK_TYPE_GENERIC: - TAILQ_REMOVE(&usb_generic_tasks, task, next); - break; + if (task->onqueue) { + switch (task->type) { + case USB_TASK_TYPE_ABORT: + TAILQ_REMOVE(&usb_abort_tasks, task, next); + break; + case USB_TASK_TYPE_EXPLORE: + TAILQ_REMOVE(&usb_explore_tasks, task, next); + break; + case USB_TASK_TYPE_GENERIC: + TAILQ_REMOVE(&usb_generic_tasks, task, next); + break; + } + task->onqueue = 0; } - task->state = USB_TASK_STATE_NONE; - splx(s); } void -usb_wait_task(usbd_device_handle dev, struct usb_task *task) +usb_rem_wait_task(usbd_device_handle dev, struct usb_task *task) { int s; - DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, - task->state, task->type)); - - if (task->state == USB_TASK_STATE_NONE) - return; + DPRINTFN(2,("%s: task=%p onqueue=%d type=%d\n", __func__, task, + task->onqueue, task->type)); s = splusb(); - while (task->state != USB_TASK_STATE_NONE) { + usb_rem_task(dev, task); + while (task->running) { DPRINTF(("%s: waiting for task to complete\n", __func__)); tsleep(task, PWAIT, "endtask", 0); } @@ -354,13 +349,6 @@ usb_wait_task(usbd_device_handle dev, struct usb_task *task) } void -usb_rem_wait_task(usbd_device_handle dev, struct usb_task *task) -{ - usb_rem_task(dev, task); - usb_wait_task(dev, task); -} - -void usb_first_explore(void *arg) { struct usb_softc *sc = arg; @@ -418,16 +406,15 @@ usb_task_thread(void *arg) tsleep(&usb_run_tasks, PWAIT, "usbtsk", 0); continue; } + task->onqueue = 0; /* Don't execute the task if the root hub is gone. */ - if (usbd_is_dying(task->dev)) { - task->state = USB_TASK_STATE_NONE; + if (usbd_is_dying(task->dev)) continue; - } - task->state = USB_TASK_STATE_RUN; + task->running = 1; splx(s); task->fun(task->arg); s = splusb(); - task->state = USB_TASK_STATE_NONE; + task->running = 0; wakeup(task); } splx(s); @@ -456,16 +443,15 @@ usb_abort_task_thread(void *arg) tsleep(&usb_run_abort_tasks, PWAIT, "usbatsk", 0); continue; } + task->onqueue = 0; /* Don't execute the task if the root hub is gone. */ - if (usbd_is_dying(task->dev)) { - task->state = USB_TASK_STATE_NONE; + if (usbd_is_dying(task->dev)) continue; - } - task->state = USB_TASK_STATE_RUN; + task->running = 1; splx(s); task->fun(task->arg); s = splusb(); - task->state = USB_TASK_STATE_NONE; + task->running = 0; wakeup(task); } splx(s); @@ -507,26 +493,6 @@ usbclose(dev_t dev, int flag, int mode, struct proc *p) return (0); } -void -usbd_fill_di_task(void *arg) -{ - struct usb_device_info *di = (struct usb_device_info *)arg; - struct usb_softc *sc; - usbd_device_handle dev; - - /* check that the bus and device are still present */ - if (di->udi_bus >= usb_cd.cd_ndevs) - return; - sc = usb_cd.cd_devs[di->udi_bus]; - if (sc == NULL) - return; - dev = sc->sc_bus->devices[di->udi_addr]; - if (dev == NULL) - return; - - usbd_fill_deviceinfo(dev, di, 1); -} - int usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p) { @@ -623,31 +589,14 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p) { struct usb_device_info *di = (void *)data; int addr = di->udi_addr; - struct usb_task di_task; usbd_device_handle dev; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); - dev = sc->sc_bus->devices[addr]; if (dev == NULL) return (ENXIO); - - di->udi_bus = unit; - - /* All devices get a driver, thanks to ugen(4). If the - * task ends without adding a driver name, there was an error. - */ - di->udi_devnames[0][0] = '\0'; - - usb_init_task(&di_task, usbd_fill_di_task, di, - USB_TASK_TYPE_GENERIC); - usb_add_task(sc->sc_bus->root_hub, &di_task); - usb_wait_task(sc->sc_bus->root_hub, &di_task); - - if (di->udi_devnames[0][0] == '\0') - return (ENXIO); - + usbd_fill_deviceinfo(dev, di, 1); break; } diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index a38a953031d..9aaa0bba5f9 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi.h,v 1.40 2011/02/04 08:21:39 jakemsr Exp $ */ +/* $OpenBSD: usbdi.h,v 1.41 2011/02/09 04:25:32 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 $ */ @@ -139,7 +139,6 @@ usbd_status usbd_set_interface(usbd_interface_handle, int); int usbd_get_no_alts(usb_config_descriptor_t *, int); usbd_status usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface); void usbd_fill_deviceinfo(usbd_device_handle, struct usb_device_info *, int); -void usbd_fill_di_task(void *); int usbd_get_interface_altindex(usbd_interface_handle iface); usb_interface_descriptor_t *usbd_find_idesc(usb_config_descriptor_t *cd, @@ -188,33 +187,28 @@ const usb_descriptor_t *usb_desc_iter_next(usbd_desc_iter_t *); * has been detected. But it may also be used by drivers that need to * perform (short) tasks that must have a process context. */ -enum usb_task_state { - USB_TASK_STATE_NONE, - USB_TASK_STATE_ONQ, - USB_TASK_STATE_RUN -}; - struct usb_task { TAILQ_ENTRY(usb_task) next; usbd_device_handle dev; void (*fun)(void *); void *arg; char type; -#define USB_TASK_TYPE_GENERIC 0 +#define USB_TASK_TYPE_GENERIC 0 #define USB_TASK_TYPE_EXPLORE 1 #define USB_TASK_TYPE_ABORT 2 - enum usb_task_state state; + char onqueue; + char running; }; void usb_add_task(usbd_device_handle, struct usb_task *); void usb_rem_task(usbd_device_handle, struct usb_task *); -void usb_wait_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, y) \ ((t)->fun = (f), \ (t)->arg = (a), \ (t)->type = (y), \ - (t)->state = USB_TASK_STATE_NONE) + (t)->onqueue = 0, \ + (t)->running = 0) struct usb_devno { u_int16_t ud_vendor; |