Index: sys/net80211/ieee80211.c =================================================================== --- sys/net80211/ieee80211.c +++ sys/net80211/ieee80211.c @@ -233,6 +233,8 @@ DEFAULTRATES(IEEE80211_MODE_VHT_2GHZ, ieee80211_rateset_11g); DEFAULTRATES(IEEE80211_MODE_VHT_5GHZ, ieee80211_rateset_11a); + ieee80211_init_suphtrates(ic); + /* * Setup required information to fill the mcsset field, if driver did * not. Assume a 2T2R setup for historic reasons. @@ -1905,6 +1907,14 @@ return &ic->ic_sup_rates[ieee80211_chan2mode(c)]; } +/* XXX inline or eliminate? */ +const struct ieee80211_htrateset * +ieee80211_get_suphtrates(struct ieee80211com *ic, + const struct ieee80211_channel *c) +{ + return &ic->ic_sup_htrates; +} + void ieee80211_announce(struct ieee80211com *ic) { Index: sys/net80211/ieee80211_ht.h =================================================================== --- sys/net80211/ieee80211_ht.h +++ sys/net80211/ieee80211_ht.h @@ -177,8 +177,7 @@ uint16_t ht40_rate_400ns; }; extern const struct ieee80211_mcs_rates ieee80211_htrates[]; -const struct ieee80211_htrateset *ieee80211_get_suphtrates( - struct ieee80211com *, const struct ieee80211_channel *); +void ieee80211_init_suphtrates(struct ieee80211com *); struct ieee80211_node; int ieee80211_setup_htrates(struct ieee80211_node *, Index: sys/net80211/ieee80211_ht.c =================================================================== --- sys/net80211/ieee80211_ht.c +++ sys/net80211/ieee80211_ht.c @@ -421,19 +421,17 @@ ht_announce(ic, IEEE80211_MODE_11NG); } -static struct ieee80211_htrateset htrateset; - -const struct ieee80211_htrateset * -ieee80211_get_suphtrates(struct ieee80211com *ic, - const struct ieee80211_channel *c) +void +ieee80211_init_suphtrates(struct ieee80211com *ic) { #define ADDRATE(x) do { \ - htrateset.rs_rates[htrateset.rs_nrates] = x; \ - htrateset.rs_nrates++; \ + htrateset->rs_rates[htrateset->rs_nrates] = x; \ + htrateset->rs_nrates++; \ } while (0) + struct ieee80211_htrateset *htrateset = &ic->ic_sup_htrates; int i; - memset(&htrateset, 0, sizeof(struct ieee80211_htrateset)); + memset(htrateset, 0, sizeof(struct ieee80211_htrateset)); for (i = 0; i < ic->ic_txstream * 8; i++) ADDRATE(i); if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) && @@ -453,7 +451,6 @@ ADDRATE(i); } } - return &htrateset; #undef ADDRATE } Index: sys/net80211/ieee80211_ioctl.c =================================================================== --- sys/net80211/ieee80211_ioctl.c +++ sys/net80211/ieee80211_ioctl.c @@ -2226,13 +2226,19 @@ } static int -checkmcs(int mcs) +checkmcs(const struct ieee80211_htrateset *rs, int mcs) { + int rate_val = IEEE80211_RV(mcs); + int i; + if (mcs == IEEE80211_FIXED_RATE_NONE) return 1; if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */ return 0; - return (mcs & 0x7f) <= 31; /* XXX could search ht rate set */ + for (i = 0; i < rs->rs_nrates; i++) + if (IEEE80211_RV(rs->rs_rates[i]) == rate_val) + return 1; + return 0; } static int @@ -2242,6 +2248,7 @@ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_txparams_req parms; /* XXX stack use? */ struct ieee80211_txparam *src, *dst; + const struct ieee80211_htrateset *rs_ht; const struct ieee80211_rateset *rs; int error, mode, changed, is11n, nmodes; @@ -2260,23 +2267,24 @@ src = &parms.params[mode]; dst = &vap->iv_txparms[mode]; rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */ + rs_ht = &ic->ic_sup_htrates; is11n = (mode == IEEE80211_MODE_11NA || mode == IEEE80211_MODE_11NG); if (src->ucastrate != dst->ucastrate) { if (!checkrate(rs, src->ucastrate) && - (!is11n || !checkmcs(src->ucastrate))) + (!is11n || !checkmcs(rs_ht, src->ucastrate))) return EINVAL; changed++; } if (src->mcastrate != dst->mcastrate) { if (!checkrate(rs, src->mcastrate) && - (!is11n || !checkmcs(src->mcastrate))) + (!is11n || !checkmcs(rs_ht, src->mcastrate))) return EINVAL; changed++; } if (src->mgmtrate != dst->mgmtrate) { if (!checkrate(rs, src->mgmtrate) && - (!is11n || !checkmcs(src->mgmtrate))) + (!is11n || !checkmcs(rs_ht, src->mgmtrate))) return EINVAL; changed++; } Index: sys/net80211/ieee80211_var.h =================================================================== --- sys/net80211/ieee80211_var.h +++ sys/net80211/ieee80211_var.h @@ -175,6 +175,7 @@ uint16_t ic_holdover; /* PM hold over duration */ uint16_t ic_txpowlimit; /* global tx power limit */ struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX]; + struct ieee80211_htrateset ic_sup_htrates; /* * Channel state: @@ -692,6 +693,8 @@ void ieee80211_vap_detach(struct ieee80211vap *); const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *); +const struct ieee80211_htrateset *ieee80211_get_suphtrates( + struct ieee80211com *, const struct ieee80211_channel *); void ieee80211_announce(struct ieee80211com *); void ieee80211_announce_channels(struct ieee80211com *); void ieee80211_drain(struct ieee80211com *);