summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstsp <stsp@openbsd.org>2017-01-21 11:21:41 +0000
committerstsp <stsp@openbsd.org>2017-01-21 11:21:41 +0000
commit2ea2d5439ce2e3bfaf9062e47f281c4708a67421 (patch)
tree2b437dcd63f54c643e2cf08b5961ab05c0c18f51
parentMove if_vio.c to sys/dev/pv/if_vio.c (diff)
downloadwireguard-openbsd-2ea2d5439ce2e3bfaf9062e47f281c4708a67421.tar.xz
wireguard-openbsd-2ea2d5439ce2e3bfaf9062e47f281c4708a67421.zip
In iwm(4), cancel mira timeouts in iwm_stop() and iwm_newstate() instead of
relying on the newstate task to do so. Fixes races of driver code against mira timeouts leading to crashes in some situations, e.g. occasionally when changing channels while the interface is up. ok procter@
-rw-r--r--sys/dev/pci/if_iwm.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index 74334359a79..7f866c49c29 100644
--- a/sys/dev/pci/if_iwm.c
+++ b/sys/dev/pci/if_iwm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwm.c,v 1.156 2017/01/12 18:06:57 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.157 2017/01/21 11:21:41 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -5496,10 +5496,8 @@ iwm_newstate_task(void *psc)
if (ostate == IEEE80211_S_SCAN && nstate != ostate)
iwm_led_blink_stop(sc);
- if (ostate == IEEE80211_S_RUN && nstate != ostate) {
+ if (ostate == IEEE80211_S_RUN && nstate != ostate)
iwm_disable_beacon_filter(sc);
- ieee80211_mira_cancel_timeouts(&in->in_mn);
- }
/* Reset the device if moving out of AUTH, ASSOC, or RUN. */
/* XXX Is there a way to switch states without a full reset? */
@@ -5632,8 +5630,11 @@ iwm_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
{
struct ifnet *ifp = IC2IFP(ic);
struct iwm_softc *sc = ifp->if_softc;
+ struct iwm_node *in = (void *)ic->ic_bss;
timeout_del(&sc->sc_calib_to);
+ if (ic->ic_state == IEEE80211_S_RUN)
+ ieee80211_mira_cancel_timeouts(&in->in_mn);
sc->ns_nstate = nstate;
sc->ns_arg = arg;
@@ -6116,6 +6117,8 @@ iwm_stop(struct ifnet *ifp, int disable)
ifq_clr_oactive(&ifp->if_snd);
in->in_phyctxt = NULL;
+ if (ic->ic_state == IEEE80211_S_RUN)
+ ieee80211_mira_cancel_timeouts(&in->in_mn);
task_del(systq, &sc->init_task);
task_del(sc->sc_nswq, &sc->newstate_task);