Index: head/sys/dev/rtwn/if_rtwn.c =================================================================== --- head/sys/dev/rtwn/if_rtwn.c +++ head/sys/dev/rtwn/if_rtwn.c @@ -1525,25 +1525,29 @@ { struct rtwn_softc *sc = ic->ic_softc; uint8_t bands[IEEE80211_MODE_BYTES]; - int i; + int cbw_flags, i; + cbw_flags = (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) ? + NET80211_CBW_FLAG_HT40 : 0; + memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); setbit(bands, IEEE80211_MODE_11NG); ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, - bands, !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + bands, cbw_flags); /* XXX workaround add_channel_list() limitations */ setbit(bands, IEEE80211_MODE_11A); setbit(bands, IEEE80211_MODE_11NA); for (i = 0; i < nitems(sc->chan_num_5ghz); i++) { + if (sc->chan_num_5ghz[i] == 0) continue; ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, sc->chan_list_5ghz[i], sc->chan_num_5ghz[i], bands, - !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + cbw_flags); } } Index: head/sys/dev/usb/wlan/if_rsu.c =================================================================== --- head/sys/dev/usb/wlan/if_rsu.c +++ head/sys/dev/usb/wlan/if_rsu.c @@ -779,7 +779,8 @@ if (sc->sc_ht) setbit(bands, IEEE80211_MODE_11NG); ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, - bands, (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0); + bands, (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) ? + NET80211_CBW_FLAG_HT40 : 0); } static void Index: head/sys/net80211/ieee80211.c =================================================================== --- head/sys/net80211/ieee80211.c +++ head/sys/net80211/ieee80211.c @@ -1301,7 +1301,7 @@ * XXX VHT-2GHz */ static void -getflags_2ghz(const uint8_t bands[], uint32_t flags[], int ht40) +getflags_2ghz(const uint8_t bands[], uint32_t flags[], int cbw_flags) { int nmodes; @@ -1312,7 +1312,7 @@ flags[nmodes++] = IEEE80211_CHAN_G; if (isset(bands, IEEE80211_MODE_11NG)) flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT20; - if (ht40) { + if (cbw_flags & NET80211_CBW_FLAG_HT40) { flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U; flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D; } @@ -1320,12 +1320,12 @@ } static void -getflags_5ghz(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) +getflags_5ghz(const uint8_t bands[], uint32_t flags[], int cbw_flags) { int nmodes; /* - * the addchan_list function seems to expect the flags array to + * The addchan_list() function seems to expect the flags array to * be in channel width order, so the VHT bits are interspersed * as appropriate to maintain said order. * @@ -1344,36 +1344,51 @@ } /* 40MHz */ - if (ht40) { + if (cbw_flags & NET80211_CBW_FLAG_HT40) flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U; - } - if (ht40 && isset(bands, IEEE80211_MODE_VHT_5GHZ)) { - flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U - | IEEE80211_CHAN_VHT40U; - } - if (ht40) { + if ((cbw_flags & NET80211_CBW_FLAG_HT40) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT40U; + if (cbw_flags & NET80211_CBW_FLAG_HT40) flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D; + if ((cbw_flags & NET80211_CBW_FLAG_HT40) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT40D; + + /* 80MHz */ + if ((cbw_flags & NET80211_CBW_FLAG_VHT80) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT80; + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT80; } - if (ht40 && isset(bands, IEEE80211_MODE_VHT_5GHZ)) { - flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D - | IEEE80211_CHAN_VHT40D; + + /* VHT160 */ + if ((cbw_flags & NET80211_CBW_FLAG_VHT160) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT160; + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT160; } - /* 80MHz */ - if (vht80 && isset(bands, IEEE80211_MODE_VHT_5GHZ)) { - flags[nmodes++] = IEEE80211_CHAN_A | - IEEE80211_CHAN_HT40U | IEEE80211_CHAN_VHT80; - flags[nmodes++] = IEEE80211_CHAN_A | - IEEE80211_CHAN_HT40D | IEEE80211_CHAN_VHT80; + /* VHT80+80 */ + if ((cbw_flags & NET80211_CBW_FLAG_VHT80P80) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT80P80; + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT80P80; } - /* XXX VHT160 */ - /* XXX VHT80+80 */ flags[nmodes] = 0; } static void -getflags(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) +getflags(const uint8_t bands[], uint32_t flags[], int cbw_flags) { flags[0] = 0; @@ -1386,15 +1401,16 @@ isset(bands, IEEE80211_MODE_VHT_2GHZ)) return; - getflags_5ghz(bands, flags, ht40, vht80); + getflags_5ghz(bands, flags, cbw_flags); } else - getflags_2ghz(bands, flags, ht40); + getflags_2ghz(bands, flags, cbw_flags); } /* * Add one 20 MHz channel into specified channel list. * You MUST NOT mix bands when calling this. It will not add 5ghz * channels if you have any B/G/N band bit set. + * This also does not support 40/80/160/80+80. */ /* XXX VHT */ int @@ -1405,7 +1421,7 @@ uint32_t flags[IEEE80211_MODE_MAX]; int i, error; - getflags(bands, flags, 0, 0); + getflags(bands, flags, 0); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); error = addchan(chans, maxchans, nchans, ieee, freq, maxregpower, @@ -1632,12 +1648,12 @@ int ieee80211_add_channel_list_2ghz(struct ieee80211_channel chans[], int maxchans, int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[], - int ht40) + int cbw_flags) { uint32_t flags[IEEE80211_MODE_MAX]; /* XXX no VHT for now */ - getflags_2ghz(bands, flags, ht40); + getflags_2ghz(bands, flags, cbw_flags); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags)); @@ -1645,30 +1661,27 @@ int ieee80211_add_channels_default_2ghz(struct ieee80211_channel chans[], - int maxchans, int *nchans, const uint8_t bands[], int ht40) + int maxchans, int *nchans, const uint8_t bands[], int cbw_flags) { const uint8_t default_chan_list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; return (ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - default_chan_list, nitems(default_chan_list), bands, ht40)); + default_chan_list, nitems(default_chan_list), bands, cbw_flags)); } int ieee80211_add_channel_list_5ghz(struct ieee80211_channel chans[], int maxchans, int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[], - int ht40) + int cbw_flags) { - uint32_t flags[IEEE80211_MODE_MAX]; - int vht80 = 0; - /* - * For now, assume VHT == VHT80 support as a minimum. + * XXX-BZ with HT and VHT there is no 1:1 mapping anymore. Review all + * uses of IEEE80211_MODE_MAX and add a new #define name for array size. */ - if (isset(bands, IEEE80211_MODE_VHT_5GHZ)) - vht80 = 1; + uint32_t flags[2 * IEEE80211_MODE_MAX]; - getflags_5ghz(bands, flags, ht40, vht80); + getflags_5ghz(bands, flags, cbw_flags); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags)); Index: head/sys/net80211/ieee80211_regdomain.c =================================================================== --- head/sys/net80211/ieee80211_regdomain.c +++ head/sys/net80211/ieee80211_regdomain.c @@ -118,10 +118,11 @@ { struct ieee80211_channel *chans = ic->ic_channels; int *nchans = &ic->ic_nchans; - int ht40; + int cbw_flags; /* XXX just do something for now */ - ht40 = !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40); + cbw_flags = (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) ? + NET80211_CBW_FLAG_HT40 : 0; *nchans = 0; if (isset(bands, IEEE80211_MODE_11B) || isset(bands, IEEE80211_MODE_11G) || @@ -131,19 +132,40 @@ nchan -= 3; ieee80211_add_channel_list_2ghz(chans, IEEE80211_CHAN_MAX, - nchans, def_chan_2ghz, nchan, bands, ht40); + nchans, def_chan_2ghz, nchan, bands, cbw_flags); } + /* XXX IEEE80211_MODE_VHT_2GHZ if we really want to. */ + if (isset(bands, IEEE80211_MODE_11A) || isset(bands, IEEE80211_MODE_11NA)) { ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, nchans, def_chan_5ghz_band1, nitems(def_chan_5ghz_band1), - bands, ht40); + bands, cbw_flags); ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, nchans, def_chan_5ghz_band2, nitems(def_chan_5ghz_band2), - bands, ht40); + bands, cbw_flags); ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, nchans, def_chan_5ghz_band3, nitems(def_chan_5ghz_band3), - bands, ht40); + bands, cbw_flags); + } + if (isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + cbw_flags |= NET80211_CBW_FLAG_HT40; /* Make sure this is set; or assert? */ + cbw_flags |= NET80211_CBW_FLAG_VHT80; +#define MS(_v, _f) (((_v) & _f) >> _f##_S) + if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1) + cbw_flags |= NET80211_CBW_FLAG_VHT160; + if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) + cbw_flags |= NET80211_CBW_FLAG_VHT80P80; +#undef MS + ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, + nchans, def_chan_5ghz_band1, nitems(def_chan_5ghz_band1), + bands, cbw_flags); + ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, + nchans, def_chan_5ghz_band2, nitems(def_chan_5ghz_band2), + bands, cbw_flags); + ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, + nchans, def_chan_5ghz_band3, nitems(def_chan_5ghz_band3), + bands, cbw_flags); } if (rd != NULL) ic->ic_regdomain = *rd; Index: head/sys/net80211/ieee80211_var.h =================================================================== --- head/sys/net80211/ieee80211_var.h +++ head/sys/net80211/ieee80211_var.h @@ -779,6 +779,10 @@ uint32_t ieee80211_get_channel_center_freq(const struct ieee80211_channel *); uint32_t ieee80211_get_channel_center_freq1(const struct ieee80211_channel *); uint32_t ieee80211_get_channel_center_freq2(const struct ieee80211_channel *); +#define NET80211_CBW_FLAG_HT40 0x01 +#define NET80211_CBW_FLAG_VHT80 0x02 +#define NET80211_CBW_FLAG_VHT160 0x04 +#define NET80211_CBW_FLAG_VHT80P80 0x08 int ieee80211_add_channel_list_2ghz(struct ieee80211_channel[], int, int *, const uint8_t[], int, const uint8_t[], int); int ieee80211_add_channels_default_2ghz(struct ieee80211_channel[], int,