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.