Improve stability of roaming on iwn(4), in particular with wpa_supplicant.
authorstsp <stsp@openbsd.org>
Wed, 9 Mar 2022 11:38:51 +0000 (11:38 +0000)
committerstsp <stsp@openbsd.org>
Wed, 9 Mar 2022 11:38:51 +0000 (11:38 +0000)
Clear HT-related rxon flags in firmware when switching away from RUN
or ASSOC state. This avoids fatal firmware errors.

When starting a scan, set link state down and clear ic_bss before
sending the scan command to the device, not after.

tested by mbuhl@ on eduroam
ok mbuhl@

sys/dev/pci/if_iwn.c

index 3972342..2c06d01 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwn.c,v 1.254 2022/01/09 05:42:52 jsg Exp $        */
+/*     $OpenBSD: if_iwn.c,v 1.255 2022/03/09 11:38:51 stsp Exp $       */
 
 /*-
  * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -1821,6 +1821,8 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
                /* Reset state to handle re- and disassociations. */
                sc->rxon.associd = 0;
                sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
+               sc->rxon.flags &= ~htole32(IWN_RXON_HT_CHANMODE_MIXED2040 |
+                   IWN_RXON_HT_CHANMODE_PURE40 | IWN_RXON_HT_HT40MINUS);
                sc->calib.state = IWN_CALIB_STATE_INIT;
                error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
                if (error != 0)
@@ -1833,21 +1835,20 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
                /* Make the link LED blink while we're scanning. */
                iwn_set_led(sc, IWN_LED_LINK, 10, 10);
 
-               if ((error = iwn_scan(sc, IEEE80211_CHAN_2GHZ, 0)) != 0) {
-                       printf("%s: could not initiate scan\n",
-                           sc->sc_dev.dv_xname);
-                       return error;
+               if ((sc->sc_flags & IWN_FLAG_BGSCAN) == 0) {
+                       ieee80211_set_link_state(ic, LINK_STATE_DOWN);
+                       ieee80211_node_cleanup(ic, ic->ic_bss);
                }
                if (ifp->if_flags & IFF_DEBUG)
                        printf("%s: %s -> %s\n", ifp->if_xname,
                            ieee80211_state_name[ic->ic_state],
                            ieee80211_state_name[nstate]);
-               if ((sc->sc_flags & IWN_FLAG_BGSCAN) == 0) {
-                       ieee80211_set_link_state(ic, LINK_STATE_DOWN);
-                       ieee80211_node_cleanup(ic, ic->ic_bss);
-               }
                ic->ic_state = nstate;
-               return 0;
+               if ((error = iwn_scan(sc, IEEE80211_CHAN_2GHZ, 0)) != 0) {
+                       printf("%s: could not initiate scan\n",
+                           sc->sc_dev.dv_xname);
+               }
+               return error;
 
        case IEEE80211_S_ASSOC:
                if (ic->ic_state != IEEE80211_S_RUN)