Author: bz
Date: Sun Oct 18 00:27:20 2020
New Revision: 366800
URL: https://svnweb.freebsd.org/changeset/base/366800

Log:
  net80211: update for (more) VHT160 support
  
  Implement two macros IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ()
  and its 80+80 counter part to check in vhtcaps for appropriate
  levels of support and use the macros throughout the code.
  
  Add vht160_chan_ranges/is_vht160_valid_freq and handle analogue
  to vht80 in various parts of the code.
  
  Add ieee80211_add_channel_cbw() which also takes the CBW flag
  fields and make the former ieee80211_add_channel() a wrapper to it.
  With the CBW flags we can add HT/VHT channels passing them to
  getflags() for the 2/5ghz functions.
  
  In ifconfig(8) add the regdomain_addchans() support for VHT160
  and VHT80P80.
  
  With this (+ regdoain.xml updates) VHT160 channels can be
  configured, listed, and pass regdomain where appropriate.
  
  Tested with:  iwlwifi
  Reviewed by:  adrian
  MFC after:    10 days
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D26712

Modified:
  head/sbin/ifconfig/ifieee80211.c
  head/sys/net80211/ieee80211.c
  head/sys/net80211/ieee80211.h
  head/sys/net80211/ieee80211_regdomain.c
  head/sys/net80211/ieee80211_var.h
  head/sys/net80211/ieee80211_vht.c

Modified: head/sbin/ifconfig/ifieee80211.c
==============================================================================
--- head/sbin/ifconfig/ifieee80211.c    Sat Oct 17 23:42:33 2020        
(r366799)
+++ head/sbin/ifconfig/ifieee80211.c    Sun Oct 18 00:27:20 2020        
(r366800)
@@ -2405,7 +2405,31 @@ regdomain_makechannels(
                                    &dc->dc_chaninfo);
                        }
 
-                       /* XXX TODO: VHT80P80, VHT160 */
+                       /* VHT160 */
+                       if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(
+                           dc->dc_vhtcaps)) {
+                               regdomain_addchans(ci, &rd->bands_11ac, reg,
+                                   IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U |
+                                   IEEE80211_CHAN_VHT160,
+                                   &dc->dc_chaninfo);
+                               regdomain_addchans(ci, &rd->bands_11ac, reg,
+                                   IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D |
+                                   IEEE80211_CHAN_VHT160,
+                                   &dc->dc_chaninfo);
+                       }
+
+                       /* VHT80P80 */
+                       if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(
+                           dc->dc_vhtcaps)) {
+                               regdomain_addchans(ci, &rd->bands_11ac, reg,
+                                   IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U |
+                                   IEEE80211_CHAN_VHT80P80,
+                                   &dc->dc_chaninfo);
+                               regdomain_addchans(ci, &rd->bands_11ac, reg,
+                                   IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D |
+                                   IEEE80211_CHAN_VHT80P80,
+                                   &dc->dc_chaninfo);
+                       }
                }
 
                if (!LIST_EMPTY(&rd->bands_11ng) && dc->dc_htcaps != 0) {

Modified: head/sys/net80211/ieee80211.c
==============================================================================
--- head/sys/net80211/ieee80211.c       Sat Oct 17 23:42:33 2020        
(r366799)
+++ head/sys/net80211/ieee80211.c       Sun Oct 18 00:27:20 2020        
(r366800)
@@ -1163,6 +1163,12 @@ struct vht_chan_range vht80_chan_ranges[] = {
        { 0, 0 }
 };
 
+struct vht_chan_range vht160_chan_ranges[] = {
+       { 5170, 5330 },
+       { 5490, 5650 },
+       { 0, 0 }
+};
+
 static int
 set_vht_extchan(struct ieee80211_channel *c)
 {
@@ -1177,8 +1183,24 @@ set_vht_extchan(struct ieee80211_channel *c)
        }
 
        if (IEEE80211_IS_CHAN_VHT160(c)) {
-               printf("%s: TODO VHT160 channel (ieee=%d, flags=0x%08x)\n",
-                   __func__, c->ic_ieee, c->ic_flags);
+               for (i = 0; vht160_chan_ranges[i].freq_start != 0; i++) {
+                       if (c->ic_freq >= vht160_chan_ranges[i].freq_start &&
+                           c->ic_freq < vht160_chan_ranges[i].freq_end) {
+                               int midpoint;
+
+                               midpoint = vht160_chan_ranges[i].freq_start + 
80;
+                               c->ic_vht_ch_freq1 =
+                                   ieee80211_mhz2ieee(midpoint, c->ic_flags);
+                               c->ic_vht_ch_freq2 = 0;
+#if 0
+                               printf("%s: %d, freq=%d, midpoint=%d, freq1=%d, 
freq2=%d\n",
+                                   __func__, c->ic_ieee, c->ic_freq, midpoint,
+                                   c->ic_vht_ch_freq1, c->ic_vht_ch_freq2);
+#endif
+                               return (1);
+                       }
+               }
+               return (0);
        }
 
        if (IEEE80211_IS_CHAN_VHT80(c)) {
@@ -1225,11 +1247,24 @@ set_vht_extchan(struct ieee80211_channel *c)
 
 /*
  * Return whether the current channel could possibly be a part of
- * a VHT80 channel.
+ * a VHT80/VHT160 channel.
  *
  * This doesn't check that the whole range is in the allowed list
  * according to regulatory.
  */
+static bool
+is_vht160_valid_freq(uint16_t freq)
+{
+       int i;
+
+       for (i = 0; vht160_chan_ranges[i].freq_start != 0; i++) {
+               if (freq >= vht160_chan_ranges[i].freq_start &&
+                   freq < vht160_chan_ranges[i].freq_end)
+                       return (true);
+       }
+       return (false);
+}
+
 static int
 is_vht80_valid_freq(uint16_t freq)
 {
@@ -1410,18 +1445,17 @@ getflags(const uint8_t bands[], uint32_t flags[], int 
  * 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.
+ * The _cbw() variant does also support HT40/VHT80/160/80+80.
  */
-/* XXX VHT */
 int
-ieee80211_add_channel(struct ieee80211_channel chans[], int maxchans,
+ieee80211_add_channel_cbw(struct ieee80211_channel chans[], int maxchans,
     int *nchans, uint8_t ieee, uint16_t freq, int8_t maxregpower,
-    uint32_t chan_flags, const uint8_t bands[])
+    uint32_t chan_flags, const uint8_t bands[], int cbw_flags)
 {
        uint32_t flags[IEEE80211_MODE_MAX];
        int i, error;
 
-       getflags(bands, flags, 0);
+       getflags(bands, flags, cbw_flags);
        KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
 
        error = addchan(chans, maxchans, nchans, ieee, freq, maxregpower,
@@ -1434,6 +1468,16 @@ ieee80211_add_channel(struct ieee80211_channel chans[]
        return (error);
 }
 
+int
+ieee80211_add_channel(struct ieee80211_channel chans[], int maxchans,
+    int *nchans, uint8_t ieee, uint16_t freq, int8_t maxregpower,
+    uint32_t chan_flags, const uint8_t bands[])
+{
+
+       return (ieee80211_add_channel_cbw(chans, maxchans, nchans, ieee, freq,
+           maxregpower, chan_flags, bands, 0));
+}
+
 static struct ieee80211_channel *
 findchannel(struct ieee80211_channel chans[], int nchans, uint16_t freq,
     uint32_t flags)
@@ -1573,7 +1617,11 @@ add_chanlist(struct ieee80211_channel chans[], int max
                        is_vht = !! (flags[j] & IEEE80211_CHAN_VHT);
 
                        /* XXX TODO FIXME VHT80P80. */
-                       /* XXX TODO FIXME VHT160. */
+
+                       /* Test for VHT160 analogue to the VHT80 below. */
+                       if (is_vht && flags[j] & IEEE80211_CHAN_VHT160)
+                               if (! is_vht160_valid_freq(freq))
+                                       continue;
 
                        /*
                         * Test for VHT80.

Modified: head/sys/net80211/ieee80211.h
==============================================================================
--- head/sys/net80211/ieee80211.h       Sat Oct 17 23:42:33 2020        
(r366799)
+++ head/sys/net80211/ieee80211.h       Sun Oct 18 00:27:20 2020        
(r366800)
@@ -815,6 +815,13 @@ struct ieee80211_ie_vht_operation {
 #define        IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ   2
 #define        IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_RESERVED       3
 
+#define        IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(_vhtcaps)            
\
+    (_IEEE80211_MASKSHIFT(_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= \
+            IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ)
+#define        IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(_vhtcaps)      
\
+    (_IEEE80211_MASKSHIFT(_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == \
+            IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ)
+
 #define        IEEE80211_VHTCAP_RXLDPC         0x00000010
 #define        IEEE80211_VHTCAP_RXLDPC_S       4
 

Modified: head/sys/net80211/ieee80211_regdomain.c
==============================================================================
--- head/sys/net80211/ieee80211_regdomain.c     Sat Oct 17 23:42:33 2020        
(r366799)
+++ head/sys/net80211/ieee80211_regdomain.c     Sun Oct 18 00:27:20 2020        
(r366800)
@@ -151,11 +151,10 @@ ieee80211_init_channels(struct ieee80211com *ic,
        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;
-               if (_IEEE80211_MASKSHIFT(ic->ic_vhtcaps,
-                   IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1)
+               if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(ic->ic_vhtcaps))
                        cbw_flags |= NET80211_CBW_FLAG_VHT160;
-               if (_IEEE80211_MASKSHIFT(ic->ic_vhtcaps,
-                   IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2)
+               if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(
+                   ic->ic_vhtcaps))
                        cbw_flags |= NET80211_CBW_FLAG_VHT80P80;
                ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX,
                    nchans, def_chan_5ghz_band1, nitems(def_chan_5ghz_band1),

Modified: head/sys/net80211/ieee80211_var.h
==============================================================================
--- head/sys/net80211/ieee80211_var.h   Sat Oct 17 23:42:33 2020        
(r366799)
+++ head/sys/net80211/ieee80211_var.h   Sun Oct 18 00:27:20 2020        
(r366800)
@@ -772,6 +772,8 @@ int ieee80211_mhz2ieee(u_int, u_int);
 int    ieee80211_chan2ieee(struct ieee80211com *,
                const struct ieee80211_channel *);
 u_int  ieee80211_ieee2mhz(u_int, u_int);
+int    ieee80211_add_channel_cbw(struct ieee80211_channel[], int, int *,
+           uint8_t, uint16_t, int8_t, uint32_t, const uint8_t[], int);
 int    ieee80211_add_channel(struct ieee80211_channel[], int, int *,
            uint8_t, uint16_t, int8_t, uint32_t, const uint8_t[]);
 int    ieee80211_add_channel_ht40(struct ieee80211_channel[], int, int *,

Modified: head/sys/net80211/ieee80211_vht.c
==============================================================================
--- head/sys/net80211/ieee80211_vht.c   Sat Oct 17 23:42:33 2020        
(r366799)
+++ head/sys/net80211/ieee80211_vht.c   Sun Oct 18 00:27:20 2020        
(r366800)
@@ -153,13 +153,10 @@ ieee80211_vht_vattach(struct ieee80211vap *vap)
            IEEE80211_FVHT_VHT
            | IEEE80211_FVHT_USEVHT40
            | IEEE80211_FVHT_USEVHT80;
-#if 0
-       /* XXX TODO: enable VHT80+80, VHT160 capabilities */
-       if (XXX TODO FIXME)
+       if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(vap->iv_vhtcaps))
                vap->iv_flags_vht |= IEEE80211_FVHT_USEVHT160;
-       if (XXX TODO FIXME)
+       if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(vap->iv_vhtcaps))
                vap->iv_flags_vht |= IEEE80211_FVHT_USEVHT80P80;
-#endif
 
        memcpy(&vap->iv_vht_mcsinfo, &ic->ic_vht_mcsinfo,
            sizeof(struct ieee80211_vht_mcs_info));
@@ -202,15 +199,11 @@ ieee80211_vht_announce(struct ieee80211com *ic)
                return;
 
        /* Channel width */
-       ic_printf(ic, "[VHT] Channel Widths: 20MHz, 40MHz, 80MHz");
-       if (_IEEE80211_MASKSHIFT(ic->ic_vhtcaps,
-           IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1)
-               printf(" 160MHz");
-       if (_IEEE80211_MASKSHIFT(ic->ic_vhtcaps,
-           IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2)
-               printf(" 80+80MHz");
-       printf("\n");
-
+       ic_printf(ic, "[VHT] Channel Widths: 20MHz, 40MHz, 80MHz%s%s\n",
+           (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(ic->ic_vhtcaps)) ?
+               ", 160MHz" : "",
+           (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(ic->ic_vhtcaps)) ?
+                ", 80+80MHz" : "");
        /* Features */
        ic_printf(ic, "[VHT] Features: %b\n", ic->ic_vhtcaps,
            IEEE80211_VHTCAP_BITS);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to