I made a mistake in my last commit to iwn and broke the scan loop. The problem happens if we don't find an AP to connect to after one scan iteration. The stack then performs a SCAN -> SCAN transition to kick off another scan, but iwn(4) code in -current always treats this transition as a no-op.
With ifconfig iwn0 debug enabled, it's evident that the driver never shows another list of access points but the LED keeps blinking (this indicates SCAN state). This diff makes iwn(4) start another scan during a SCAN->SCAN transition if no scan is in progress. This behaviour matches what iwm(4) does. Index: if_iwn.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v retrieving revision 1.200 diff -u -p -r1.200 if_iwn.c --- if_iwn.c 1 Feb 2018 11:21:34 -0000 1.200 +++ if_iwn.c 24 Feb 2018 18:43:33 -0000 @@ -1773,8 +1773,11 @@ iwn_newstate(struct ieee80211com *ic, en } 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 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; } @@ -4947,6 +4953,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) Index: if_iwnvar.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwnvar.h,v retrieving revision 1.33 diff -u -p -r1.33 if_iwnvar.h --- if_iwnvar.h 14 Dec 2017 14:21:11 -0000 1.33 +++ if_iwnvar.h 24 Feb 2018 18:19:51 -0000 @@ -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;