diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2018-02-25 12:40:07 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2018-02-25 12:40:07 +0000 |
commit | f9a0a0abaf661e66b54deade75845d52b03b5534 (patch) | |
tree | 03dec0d0471bd8418aa7a82b6050322582d3bb21 /sys/dev | |
parent | 2742f51a13545c0f3b39c4625ac7cdf6fa634390 (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.c | 25 | ||||
-rw-r--r-- | sys/dev/pci/if_iwnvar.h | 3 |
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; |