This should fix the infinite scanning loops people have been
reporting with 11n-enabled iwn(4), as well as the issue where
clients associating to 11g APs end up in 11b mode and can't
use OFDM data rates.

ok?

Index: ieee80211.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211.c,v
retrieving revision 1.52
diff -u -p -r1.52 ieee80211.c
--- ieee80211.c 16 Dec 2015 12:52:03 -0000      1.52
+++ ieee80211.c 17 Dec 2015 18:35:27 -0000
@@ -874,6 +874,14 @@ ieee80211_next_mode(struct ifnet *ifp)
                /* Wrap around and ignore turbo mode */
                if (ic->ic_curmode == IEEE80211_MODE_TURBO)
                        continue;
+#ifndef IEEE80211_NO_HT
+               /* 
+                * Skip 11n mode while scanning. Its set of channels is
+                * the superset of all channels supported by other modes.
+                */
+               if (ic->ic_curmode == IEEE80211_MODE_11N)
+                       continue;
+#endif
                if (ic->ic_curmode >= IEEE80211_MODE_MAX) {
                        ic->ic_curmode = IEEE80211_MODE_AUTO;
                        break;
@@ -893,6 +901,11 @@ ieee80211_next_mode(struct ifnet *ifp)
  * caller can select a rate set.  This is problematic and the
  * work here assumes how things work elsewhere in this code.
  *
+ * Because the result of this function is ultimately used to select
+ * a rate from the rate set of the returned mode, it must not return
+ * IEEE802_MODE_11N. This funcion may be called in 11n mode to find
+ * a non-MCS rate to use for sending frames to non-HT STAs.
+ *
  * XXX never returns turbo modes -dcy
  */
 enum ieee80211_phymode
@@ -911,11 +924,6 @@ ieee80211_chan2mode(struct ieee80211com 
         * characteristics.  We assume that turbo-only channels
         * are not considered when the channel set is constructed.
         */
-#ifndef IEEE80211_NO_HT
-       if (IEEE80211_IS_CHAN_N(chan))
-               return IEEE80211_MODE_11N;
-       else
-#endif
        if (IEEE80211_IS_CHAN_T(chan))
                return IEEE80211_MODE_TURBO;
        else if (IEEE80211_IS_CHAN_5GHZ(chan))
Index: ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.145
diff -u -p -r1.145 ieee80211_input.c
--- ieee80211_input.c   12 Dec 2015 13:56:10 -0000      1.145
+++ ieee80211_input.c   17 Dec 2015 18:42:06 -0000
@@ -2257,16 +2257,8 @@ ieee80211_recv_assoc_resp(struct ieee802
 
        /* Hop out of 11n mode after associating to a non-HT AP. */
        if (ic->ic_curmode == IEEE80211_MODE_11N &&
-           (ni->ni_flags & IEEE80211_NODE_HT) == 0) {
-               if (IEEE80211_IS_CHAN_T(ni->ni_chan))
-                       ieee80211_setmode(ic, IEEE80211_MODE_TURBO);
-               else if (IEEE80211_IS_CHAN_A(ni->ni_chan))
-                       ieee80211_setmode(ic, IEEE80211_MODE_11A);
-               else if (IEEE80211_IS_CHAN_G(ni->ni_chan))
-                       ieee80211_setmode(ic, IEEE80211_MODE_11G);
-               else
-                       ieee80211_setmode(ic, IEEE80211_MODE_11B);
-       }
+           (ni->ni_flags & IEEE80211_NODE_HT) == 0)
+               ieee80211_setmode(ic, ieee80211_chan2mode(ic, ni->ni_chan));
 #endif
        /*
         * Configure state now that we are associated.

Reply via email to