diff options
Diffstat (limited to 'sys/dev/usb/if_rsu.c')
-rw-r--r-- | sys/dev/usb/if_rsu.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/sys/dev/usb/if_rsu.c b/sys/dev/usb/if_rsu.c index 147115c3199..9520e7c1331 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.12 2011/02/09 04:25:32 jakemsr Exp $ */ +/* $OpenBSD: if_rsu.c,v 1.13 2011/02/10 17:26:40 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); } |