From: stsp Date: Sun, 25 Feb 2018 12:40:06 +0000 (+0000) Subject: My previous commit to iwn(4) broke the scan loop. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=afe2e7dfd7922aa8f73cbfb092ccac18d3055200;p=openbsd 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@ --- 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 @@ -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;