summaryrefslogtreecommitdiff
path: root/sys/dev/usb/if_rsu.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/if_rsu.c')
-rw-r--r--sys/dev/usb/if_rsu.c37
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);
}