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;
 

Reply via email to