summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstsp <stsp@openbsd.org>2017-06-14 16:56:50 +0000
committerstsp <stsp@openbsd.org>2017-06-14 16:56:50 +0000
commit90e46a7be75b277c317f80ee4ebed30b937dd0eb (patch)
tree7f3715f8004888e01e09b5db7243c58712961b9c
parentMake iwm(4) wait for the PHY calibration result notification during HW init. (diff)
downloadwireguard-openbsd-90e46a7be75b277c317f80ee4ebed30b937dd0eb.tar.xz
wireguard-openbsd-90e46a7be75b277c317f80ee4ebed30b937dd0eb.zip
Make the iwm(4) ioctl handler wait until the transition to SCAN has completed
when bringing the interface up. Otherwise we get racy behaviour when running ifconfig commands which issue several ioctls in quick succession. Should fix the occasional "could not initiate scan" errors. ok deraadt@
-rw-r--r--sys/dev/pci/if_iwm.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index 9478ce76dec..1edfdd72179 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.193 2017/06/14 16:56:04 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.194 2017/06/14 16:56:50 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -5623,6 +5623,7 @@ iwm_newstate_task(void *psc)
sc->sc_flags |= IWM_FLAG_SCANNING;
ic->ic_state = nstate;
iwm_led_blink_start(sc);
+ wakeup(&ic->ic_state); /* wake iwm_init() */
return;
case IEEE80211_S_AUTH:
@@ -6102,7 +6103,8 @@ int
iwm_init(struct ifnet *ifp)
{
struct iwm_softc *sc = ifp->if_softc;
- int err;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int err, generation;
if (sc->sc_flags & IWM_FLAG_HW_INITED) {
return 0;
@@ -6119,6 +6121,20 @@ iwm_init(struct ifnet *ifp)
ifp->if_flags |= IFF_RUNNING;
ieee80211_begin_scan(ifp);
+
+ /*
+ * ieee80211_begin_scan() ends up scheduling iwm_newstate_task().
+ * Wait until the transition to SCAN state has completed.
+ */
+ do {
+ generation = sc->sc_generation;
+ err = tsleep(&ic->ic_state, PCATCH, "iwminit", hz);
+ if (generation != sc->sc_generation)
+ return ENXIO;
+ if (err)
+ return err;
+ } while (ic->ic_state != IEEE80211_S_SCAN);
+
sc->sc_flags |= IWM_FLAG_HW_INITED;
return 0;