summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2015-03-02 13:08:19 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2015-03-02 13:08:19 +0000
commitc094eb874b0be105eb5d67799e3146ee17f3f4ab (patch)
tree9b2bee3a320dca3bcba5caa5dea0cdd6990bbaff /sys/dev
parent013e4e7ccd75fe17f7b41b79b87614ff23dc1358 (diff)
Teach athn(4) about USB reference counting to prevent it from causing major
confusion in the USB stack. Also add some usbd_is_dying checks. suggested by + ok mpi@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/if_athn_usb.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/sys/dev/usb/if_athn_usb.c b/sys/dev/usb/if_athn_usb.c
index 09411158436..4d67266c5d4 100644
--- a/sys/dev/usb/if_athn_usb.c
+++ b/sys/dev/usb/if_athn_usb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_athn_usb.c,v 1.26 2015/02/10 23:25:46 mpi Exp $ */
+/* $OpenBSD: if_athn_usb.c,v 1.27 2015/03/02 13:08:18 stsp Exp $ */
/*-
* Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
@@ -291,6 +291,8 @@ athn_usb_detach(struct device *self, int flags)
/* Wait for all async commands to complete. */
athn_usb_wait_async(usc);
+ usbd_ref_wait(usc->sc_udev);
+
/* Abort and close Tx/Rx pipes. */
athn_usb_close_pipes(usc);
@@ -956,8 +958,12 @@ athn_usb_write_barrier(struct athn_softc *sc)
int
athn_usb_media_change(struct ifnet *ifp)
{
+ struct athn_usb_softc *usc = (struct athn_usb_softc *)ifp->if_softc;
int error;
+ if (usbd_is_dying(usc->sc_udev))
+ return ENXIO;
+
error = ieee80211_media_change(ifp);
if (error != ENETRESET)
return (error);
@@ -1014,7 +1020,8 @@ athn_usb_newstate_cb(struct athn_usb_softc *usc, void *arg)
/* Make the LED blink while scanning. */
athn_set_led(sc, !sc->led_state);
(void)athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
- timeout_add_msec(&sc->scan_to, 200);
+ if (!usbd_is_dying(usc->sc_udev))
+ timeout_add_msec(&sc->scan_to, 200);
break;
case IEEE80211_S_AUTH:
athn_set_led(sc, 0);
@@ -2048,11 +2055,17 @@ int
athn_usb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct athn_softc *sc = ifp->if_softc;
+ struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
struct ieee80211com *ic = &sc->sc_ic;
struct ifaddr *ifa;
struct ifreq *ifr;
int s, error = 0;
+ if (usbd_is_dying(usc->sc_udev))
+ return ENXIO;
+
+ usbd_ref_incr(usc->sc_udev);
+
s = splnet();
switch (cmd) {
@@ -2105,6 +2118,9 @@ athn_usb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
}
splx(s);
+
+ usbd_ref_decr(usc->sc_udev);
+
return (error);
}