summaryrefslogtreecommitdiff
path: root/sys/dev/usb/if_rum.c
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2010-12-30 05:22:52 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2010-12-30 05:22:52 +0000
commit1def543700ac1ab92b7f65e3178f9c25b08795ef (patch)
tree490f6e0ee6af9f43e1af18fc0b9c320f9349ac40 /sys/dev/usb/if_rum.c
parentf6a5099b44f1218b8b9e6a7c28b5646e4f277942 (diff)
* do not add timeouts if the driver is dying
* use usbd_ref_{incr,decr,wait} to not detach while another process/thread is using the driver * s/usb_rem_task/usb_rem_wait_task/ in detach functions because detach doesn't always happen in the task thread; otherwise a task could be running while the driver detaches * in detach functions, first delete pending timeouts, then wait for processes to be done with the driver before freeing resources ok martynas@
Diffstat (limited to 'sys/dev/usb/if_rum.c')
-rw-r--r--sys/dev/usb/if_rum.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/sys/dev/usb/if_rum.c b/sys/dev/usb/if_rum.c
index 035b073778a..53560d33c8f 100644
--- a/sys/dev/usb/if_rum.c
+++ b/sys/dev/usb/if_rum.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_rum.c,v 1.95 2010/12/17 22:38:54 jasper Exp $ */
+/* $OpenBSD: if_rum.c,v 1.96 2010/12/30 05:22:51 jakemsr Exp $ */
/*-
* Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini@free.fr>
@@ -460,17 +460,20 @@ rum_detach(struct device *self, int flags)
s = splusb();
- if (ifp->if_softc != NULL) {
- ieee80211_ifdetach(ifp); /* free all nodes */
- if_detach(ifp);
- }
-
- usb_rem_task(sc->sc_udev, &sc->sc_task);
if (timeout_initialized(&sc->scan_to))
timeout_del(&sc->scan_to);
if (timeout_initialized(&sc->amrr_to))
timeout_del(&sc->amrr_to);
+ usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
+
+ usbd_ref_wait(sc->sc_udev);
+
+ if (ifp->if_softc != NULL) {
+ ieee80211_ifdetach(ifp); /* free all nodes */
+ if_detach(ifp);
+ }
+
if (sc->amrr_xfer != NULL) {
usbd_free_xfer(sc->amrr_xfer);
sc->amrr_xfer = NULL;
@@ -647,8 +650,12 @@ rum_next_scan(void *arg)
if (usbd_is_dying(sc->sc_udev))
return;
+ usbd_ref_incr(sc->sc_udev);
+
if (ic->ic_state == IEEE80211_S_SCAN)
ieee80211_next_scan(ifp);
+
+ usbd_ref_decr(sc->sc_udev);
}
void
@@ -676,7 +683,8 @@ rum_task(void *arg)
case IEEE80211_S_SCAN:
rum_set_chan(sc, ic->ic_bss->ni_chan);
- 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:
@@ -1350,6 +1358,11 @@ rum_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) {
@@ -1413,6 +1426,8 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
splx(s);
+ usbd_ref_decr(sc->sc_udev);
+
return error;
}
@@ -2232,7 +2247,8 @@ rum_amrr_start(struct rum_softc *sc, struct ieee80211_node *ni)
i--);
ni->ni_txrate = i;
- timeout_add_sec(&sc->amrr_to, 1);
+ if (!usbd_is_dying(sc->sc_udev))
+ timeout_add_sec(&sc->amrr_to, 1);
}
void
@@ -2286,7 +2302,8 @@ rum_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv,
ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
- timeout_add_sec(&sc->amrr_to, 1);
+ if (!usbd_is_dying(sc->sc_udev))
+ timeout_add_sec(&sc->amrr_to, 1);
}
int