diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2011-02-05 18:10:45 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2011-02-05 18:10:45 +0000 |
commit | 5297b10a7d9912ed9f44f8f75487936ae5e4ab1c (patch) | |
tree | a76052f893e68b5968f34384423e42fe16bbb649 /sys | |
parent | d1d6ddc24641be41f6a4c4f0027877d244936dc2 (diff) |
* use usb_ref_{incr,decr,wait}() to avoid detaching the driver while a
process is still using the hardware.
* don't add timeout(9)s if the device is detached.
* add checks to see if the device has been detached before running
ioctls, timeouts, and tasks.
* use usb_wait_task() to wait for tasks to complete.
ok damien@
Diffstat (limited to 'sys')
-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 |
4 files changed, 103 insertions, 49 deletions
diff --git a/sys/dev/usb/if_otus.c b/sys/dev/usb/if_otus.c index bc27b1a209f..ed715bb3d29 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.27 2011/01/25 20:03:35 jakemsr Exp $ */ +/* $OpenBSD: if_otus.c,v 1.28 2011/02/05 18:10:44 jakemsr Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -243,17 +243,18 @@ otus_detach(struct device *self, int flags) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - s = splnet(); - - /* Wait for all queued asynchronous commands to complete. */ - while (sc->cmdq.queued > 0) - tsleep(&sc->cmdq, 0, "cmdq", 0); + s = splusb(); 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); @@ -727,8 +728,15 @@ 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 @@ -750,7 +758,6 @@ otus_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT; } - wakeup(ring); splx(s); } @@ -804,7 +811,8 @@ otus_newstate_cb(struct otus_softc *sc, void *arg) case IEEE80211_S_SCAN: (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 0); - timeout_add_msec(&sc->scan_to, 200); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_msec(&sc->scan_to, 200); break; case IEEE80211_S_AUTH: @@ -825,7 +833,8 @@ otus_newstate_cb(struct otus_softc *sc, void *arg) otus_newassoc(ic, ni, 1); /* Start calibration timer. */ - timeout_add_sec(&sc->calib_to, 1); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_sec(&sc->calib_to, 1); } break; } @@ -1494,6 +1503,11 @@ 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) { @@ -1550,6 +1564,9 @@ otus_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } splx(s); + + usbd_ref_decr(sc->sc_udev); + return error; } @@ -2171,12 +2188,20 @@ 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); - timeout_add_sec(&sc->calib_to, 1); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_sec(&sc->calib_to, 1); + + usbd_ref_decr(sc->sc_udev); } int @@ -2324,8 +2349,7 @@ otus_stop(struct ifnet *ifp) s = splusb(); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* Wait for all queued asynchronous commands to complete. */ - while (sc->cmdq.queued > 0) - tsleep(&sc->cmdq, 0, "cmdq", 0); + usb_wait_task(sc->sc_udev, &sc->sc_task); splx(s); /* Stop Rx. */ diff --git a/sys/dev/usb/if_rsu.c b/sys/dev/usb/if_rsu.c index cb2adf71c63..afcfef86a94 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.10 2011/01/25 20:03:35 jakemsr Exp $ */ +/* $OpenBSD: if_rsu.c,v 1.11 2011/02/05 18:10:44 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -341,12 +341,16 @@ rsu_detach(struct device *self, int flags) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - s = splnet(); - /* Wait for all async commands to complete. */ - rsu_wait_async(sc); + s = splusb(); 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); @@ -537,7 +541,6 @@ rsu_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % RSU_HOST_CMD_RING_COUNT; } - wakeup(ring); splx(s); } @@ -566,8 +569,7 @@ void rsu_wait_async(struct rsu_softc *sc) { /* Wait for all queued asynchronous commands to complete. */ - while (sc->cmdq.queued > 0) - tsleep(&sc->cmdq, 0, "cmdq", 0); + usb_wait_task(sc->sc_udev, &sc->sc_task); } int @@ -802,8 +804,15 @@ 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 */ @@ -828,7 +837,8 @@ rsu_calib_cb(struct rsu_softc *sc, void *arg) DPRINTFN(8, ("RSSI=%d%%\n", reg >> 4)); } - timeout_add_sec(&sc->calib_to, 2); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_sec(&sc->calib_to, 2); } int @@ -895,7 +905,8 @@ 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. */ - timeout_add_sec(&sc->calib_to, 2); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_sec(&sc->calib_to, 2); break; } (void)sc->sc_newstate(ic, cmd->state, cmd->arg); @@ -1699,6 +1710,11 @@ 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) { @@ -1741,6 +1757,9 @@ 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 5d4fe93a1c0..9622756109a 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.85 2011/01/30 17:31:08 tedu Exp $ */ +/* $OpenBSD: if_run.c,v 1.86 2011/02/05 18:10:44 jakemsr Exp $ */ /*- * Copyright (c) 2008-2010 Damien Bergamini <damien.bergamini@free.fr> @@ -600,22 +600,8 @@ 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) { @@ -1485,7 +1471,6 @@ run_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % RUN_HOST_CMD_RING_COUNT; } - wakeup(ring); splx(s); } @@ -3534,8 +3519,7 @@ 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 */ - while (sc->cmdq.queued > 0) - tsleep(&sc->cmdq, 0, "cmdq", 0); + usb_wait_task(sc->sc_udev, &sc->sc_task); splx(s); /* disable Tx/Rx */ diff --git a/sys/dev/usb/if_urtwn.c b/sys/dev/usb/if_urtwn.c index 1a1e09a2b87..555b4754479 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.13 2011/01/25 20:03:35 jakemsr Exp $ */ +/* $OpenBSD: if_urtwn.c,v 1.14 2011/02/05 18:10:44 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -369,14 +369,18 @@ urtwn_detach(struct device *self, int flags) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - s = splnet(); - /* Wait for all async commands to complete. */ - urtwn_wait_async(sc); + s = splusb(); 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); @@ -592,7 +596,6 @@ urtwn_task(void *arg) ring->queued--; ring->next = (ring->next + 1) % URTWN_HOST_CMD_RING_COUNT; } - wakeup(ring); splx(s); } @@ -621,8 +624,7 @@ void urtwn_wait_async(struct urtwn_softc *sc) { /* Wait for all queued asynchronous commands to complete. */ - while (sc->cmdq.queued > 0) - tsleep(&sc->cmdq, 0, "cmdq", 0); + usb_wait_task(sc->sc_udev, &sc->sc_task); } int @@ -1061,8 +1063,15 @@ 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 */ @@ -1083,7 +1092,8 @@ urtwn_calib_cb(struct urtwn_softc *sc, void *arg) /* Do temperature compensation. */ urtwn_temp_calib(sc); - timeout_add_sec(&sc->calib_to, 2); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_sec(&sc->calib_to, 2); } void @@ -1093,10 +1103,17 @@ 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 @@ -1185,7 +1202,8 @@ 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); - timeout_add_msec(&sc->scan_to, 200); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_msec(&sc->scan_to, 200); break; case IEEE80211_S_AUTH: @@ -1263,7 +1281,8 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg) sc->thcal_state = 0; sc->thcal_lctemp = 0; /* Start periodic calibration. */ - timeout_add_sec(&sc->calib_to, 2); + if (!usbd_is_dying(sc->sc_udev)) + timeout_add_sec(&sc->calib_to, 2); break; } (void)sc->sc_newstate(ic, cmd->state, cmd->arg); @@ -1926,6 +1945,11 @@ 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) { @@ -1978,6 +2002,9 @@ urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; } splx(s); + + usbd_ref_decr(sc->sc_udev); + return (error); } |