summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2018-02-25 12:40:07 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2018-02-25 12:40:07 +0000
commitf9a0a0abaf661e66b54deade75845d52b03b5534 (patch)
tree03dec0d0471bd8418aa7a82b6050322582d3bb21 /sys/dev
parent2742f51a13545c0f3b39c4625ac7cdf6fa634390 (diff)
My previous commit to iwn(4) broke the scan loop.
The problem happened if we didn't find an AP to connect to after one scan iteration. The net80211 stack then performs a SCAN -> SCAN transition to kick off another scan, but the driver treated this transition as a no-op and remained in SCAN state doing nothing. To fix this, introduce a flag which keeps track of whether a firmware scan command is in progress, and start another scan during a SCAN->SCAN transition if no scan is in progress. Matches what iwm(4) does. Note that previously (i.e. in 6.2), iwn(4) would always try to start a new scan regardless of what the firmware was currently doing. Problem noticed by myself and also by deraadt@ test & ok tb@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_iwn.c25
-rw-r--r--sys/dev/pci/if_iwnvar.h3
2 files changed, 19 insertions, 9 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 65969746188..d26fb6a5e64 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwn.c,v 1.200 2018/02/01 11:21:34 stsp Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.201 2018/02/25 12:40:06 stsp Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -1773,8 +1773,11 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
}
if (ic->ic_state == IEEE80211_S_SCAN) {
- if (nstate == IEEE80211_S_SCAN)
- return 0;
+ if (nstate == IEEE80211_S_SCAN) {
+ if (sc->sc_flags & IWN_FLAG_SCANNING)
+ return 0;
+ } else
+ sc->sc_flags &= ~IWN_FLAG_SCANNING;
/* Turn LED off when leaving scan state. */
iwn_set_led(sc, IWN_LED_LINK, 1, 0);
}
@@ -2653,8 +2656,9 @@ iwn_notif_intr(struct iwn_softc *sc)
if (error == 0)
break;
}
- ieee80211_end_scan(ifp);
+ sc->sc_flags &= ~IWN_FLAG_SCANNING;
sc->sc_flags &= ~IWN_FLAG_BGSCAN;
+ ieee80211_end_scan(ifp);
break;
}
case IWN5000_CALIBRATION_RESULT:
@@ -4922,11 +4926,12 @@ iwn_scan(struct iwn_softc *sc, uint16_t flags, int bgscan)
hdr->len = htole16(buflen);
DPRINTF(("sending scan command nchan=%d\n", hdr->nchan));
- if (bgscan)
- sc->sc_flags |= IWN_FLAG_BGSCAN;
error = iwn_cmd(sc, IWN_CMD_SCAN, buf, buflen, 1);
- if (bgscan && error)
- sc->sc_flags &= ~IWN_FLAG_BGSCAN;
+ if (error == 0) {
+ sc->sc_flags |= IWN_FLAG_SCANNING;
+ if (bgscan)
+ sc->sc_flags |= IWN_FLAG_BGSCAN;
+ }
free(buf, M_DEVBUF, IWN_SCAN_MAXSZ);
return error;
}
@@ -4939,6 +4944,7 @@ iwn_scan_abort(struct iwn_softc *sc)
/* XXX Cannot wait for status response in interrupt context. */
DELAY(100);
+ sc->sc_flags &= ~IWN_FLAG_SCANNING;
sc->sc_flags &= ~IWN_FLAG_BGSCAN;
}
@@ -4948,6 +4954,9 @@ iwn_bgscan(struct ieee80211com *ic)
struct iwn_softc *sc = ic->ic_softc;
int error;
+ if (sc->sc_flags & IWN_FLAG_SCANNING)
+ return 0;
+
error = iwn_scan(sc, IEEE80211_CHAN_2GHZ, 1);
if (error)
printf("%s: could not initiate background scan\n",
diff --git a/sys/dev/pci/if_iwnvar.h b/sys/dev/pci/if_iwnvar.h
index 82a3693439d..fd9616f0258 100644
--- a/sys/dev/pci/if_iwnvar.h
+++ b/sys/dev/pci/if_iwnvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnvar.h,v 1.33 2017/12/14 14:21:11 stsp Exp $ */
+/* $OpenBSD: if_iwnvar.h,v 1.34 2018/02/25 12:40:06 stsp Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -203,6 +203,7 @@ struct iwn_softc {
#define IWN_FLAG_ENH_SENS (1 << 7)
#define IWN_FLAG_ADV_BT_COEX (1 << 8)
#define IWN_FLAG_BGSCAN (1 << 9)
+#define IWN_FLAG_SCANNING (1 << 10)
uint8_t hw_type;