summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2011-02-05 18:10:45 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2011-02-05 18:10:45 +0000
commit5297b10a7d9912ed9f44f8f75487936ae5e4ab1c (patch)
treea76052f893e68b5968f34384423e42fe16bbb649 /sys
parentd1d6ddc24641be41f6a4c4f0027877d244936dc2 (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.c48
-rw-r--r--sys/dev/usb/if_rsu.c37
-rw-r--r--sys/dev/usb/if_run.c20
-rw-r--r--sys/dev/usb/if_urtwn.c47
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);
}