Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F138206593
D49773.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D49773.id.diff
View Options
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -547,19 +547,15 @@
width = (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK);
switch (width) {
-#if 0
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_160;
break;
-#endif
default:
/* Check if we do support 160Mhz somehow after all. */
-#if 0
if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) != 0)
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_160;
else
-#endif
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_80;
}
skip_bw:
@@ -2112,14 +2108,11 @@
#endif
#ifdef LKPI_80211_VHT
if (IEEE80211_IS_CHAN_VHT_5GHZ(ni->ni_chan)) {
-#ifdef __notyet__
if (IEEE80211_IS_CHAN_VHT80P80(ni->ni_chan))
chanctx_conf->def.width = NL80211_CHAN_WIDTH_80P80;
else if (IEEE80211_IS_CHAN_VHT160(ni->ni_chan))
chanctx_conf->def.width = NL80211_CHAN_WIDTH_160;
- else
-#endif
- if (IEEE80211_IS_CHAN_VHT80(ni->ni_chan))
+ else if (IEEE80211_IS_CHAN_VHT80(ni->ni_chan))
chanctx_conf->def.width = NL80211_CHAN_WIDTH_80;
}
#endif
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -945,12 +945,15 @@
struct ieee80211_vht_mcs_info supp_mcs;
} __packed;
-/* 802.11ac-2013, Table 8-183x-VHT Operation Information subfields */
+/*
+ * 802.11ac-2013, Table 8-183x-VHT Operation Information subfields.
+ * 802.11-2020, Table 9-274-VHT Operation Information subfields (for deprecations)
+ */
enum ieee80211_vht_chanwidth {
IEEE80211_VHT_CHANWIDTH_USE_HT = 0, /* 20 MHz or 40 MHz */
IEEE80211_VHT_CHANWIDTH_80MHZ = 1, /* 80MHz */
- IEEE80211_VHT_CHANWIDTH_160MHZ = 2, /* 160MHz */
- IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, /* 80+80MHz */
+ IEEE80211_VHT_CHANWIDTH_160MHZ = 2, /* 160MHz (deprecated) */
+ IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, /* 80+80MHz (deprecated) */
/* 4..255 reserved. */
};
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -1931,66 +1931,132 @@
static uint32_t
ieee80211_vht_get_vhtflags(struct ieee80211_node *ni, uint32_t htflags)
{
- struct ieee80211vap *vap = ni->ni_vap;
- uint32_t vhtflags = 0;
+#define _RETURN_CHAN_BITS(_cb) \
+do { \
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, \
+ "%s:%d: selected %b", __func__, __LINE__, \
+ (_cb), IEEE80211_CHAN_BITS); \
+ return (_cb); \
+} while(0)
+ struct ieee80211vap *vap;
+ const struct ieee80211_ie_htinfo *htinfo;
+ uint32_t vhtflags;
+ bool can_vht160, can_vht80p80, can_vht80;
+ bool ht40;
+
+ vap = ni->ni_vap;
+
+ /* If we do not support VHT or VHT is disabled just return. */
+ if ((ni->ni_flags & IEEE80211_NODE_VHT) == 0 ||
+ (vap->iv_vht_flags & IEEE80211_FVHT_VHT) == 0)
+ _RETURN_CHAN_BITS(0);
+
+ /*
+ * The original code was based on
+ * 802.11ac-2013, Table 8-183x-VHT Operation Information subfields.
+ * 802.11-2020, Table 9-274-VHT Operation Information subfields
+ * has IEEE80211_VHT_CHANWIDTH_160MHZ and
+ * IEEE80211_VHT_CHANWIDTH_80P80MHZ deprecated.
+ * For current logic see
+ * 802.11-2020, 11.38.1 Basic VHT BSS functionality.
+ */
+
+ htinfo = (const struct ieee80211_ie_htinfo *)ni->ni_ies.htinfo_ie;
+ ht40 = ((htinfo->hi_byte1 & IEEE80211_HTINFO_TXWIDTH) ==
+ IEEE80211_HTINFO_TXWIDTH_2040);
+ can_vht160 = can_vht80p80 = can_vht80 = false;
+
+ /* 20 Mhz */
+ if (!ht40) {
+ /* Check for the full valid combination -- other fields be 0. */
+ if (ni->ni_vht_chanwidth != IEEE80211_VHT_CHANWIDTH_USE_HT ||
+ ni->ni_vht_chan2 != 0)
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
+ "%s: invalid VHT BSS bandwidth 0/%d/%d/%d",
+ __func__, ni->ni_vht_chanwidth,
+ ni->ni_vht_chan1, ni->ni_vht_chan2);
+
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT20 | IEEE80211_CHAN_HT20);
+ }
vhtflags = 0;
- if (ni->ni_flags & IEEE80211_NODE_VHT && vap->iv_vht_flags & IEEE80211_FVHT_VHT) {
- if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_160MHZ) &&
- IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(vap->iv_vht_cap.vht_cap_info) &&
- (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT160)) {
- vhtflags = IEEE80211_CHAN_VHT160;
- /* Mirror the HT40 flags */
- if (htflags == IEEE80211_CHAN_HT40U) {
- vhtflags |= IEEE80211_CHAN_HT40U;
- } else if (htflags == IEEE80211_CHAN_HT40D) {
- vhtflags |= IEEE80211_CHAN_HT40D;
- }
- } else if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80P80MHZ) &&
- IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(vap->iv_vht_cap.vht_cap_info) &&
- (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT80P80)) {
- vhtflags = IEEE80211_CHAN_VHT80P80;
- /* Mirror the HT40 flags */
- if (htflags == IEEE80211_CHAN_HT40U) {
- vhtflags |= IEEE80211_CHAN_HT40U;
- } else if (htflags == IEEE80211_CHAN_HT40D) {
- vhtflags |= IEEE80211_CHAN_HT40D;
- }
- } else if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80MHZ) &&
- (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT80)) {
- vhtflags = IEEE80211_CHAN_VHT80;
- /* Mirror the HT40 flags */
- if (htflags == IEEE80211_CHAN_HT40U) {
- vhtflags |= IEEE80211_CHAN_HT40U;
- } else if (htflags == IEEE80211_CHAN_HT40D) {
- vhtflags |= IEEE80211_CHAN_HT40D;
- }
- } else if (ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_USE_HT) {
- /* Mirror the HT40 flags */
- /*
- * XXX TODO: if ht40 is disabled, but vht40 isn't
- * disabled then this logic will get very, very sad.
- * It's quite possible the only sane thing to do is
- * to not have vht40 as an option, and just obey
- * 'ht40' as that flag.
- */
- if ((htflags == IEEE80211_CHAN_HT40U) &&
- (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT40)) {
- vhtflags = IEEE80211_CHAN_VHT40U
- | IEEE80211_CHAN_HT40U;
- } else if (htflags == IEEE80211_CHAN_HT40D &&
- (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT40)) {
- vhtflags = IEEE80211_CHAN_VHT40D
- | IEEE80211_CHAN_HT40D;
- } else if (htflags == IEEE80211_CHAN_HT20) {
- vhtflags = IEEE80211_CHAN_VHT20
- | IEEE80211_CHAN_HT20;
- }
- } else {
- vhtflags = IEEE80211_CHAN_VHT20;
+
+ /* We know we can at least do 40Mhz, so mirror the HT40 flags. */
+ if (htflags == IEEE80211_CHAN_HT40U)
+ vhtflags |= IEEE80211_CHAN_HT40U;
+ else if (htflags == IEEE80211_CHAN_HT40D)
+ vhtflags |= IEEE80211_CHAN_HT40D;
+
+ /* 40 MHz */
+ if (ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_USE_HT) {
+ if (ni->ni_vht_chan2 != 0)
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
+ "%s: invalid VHT BSS bandwidth 1/%d/%d/%d",
+ __func__, ni->ni_vht_chanwidth,
+ ni->ni_vht_chan1, ni->ni_vht_chan2);
+
+ if ((vap->iv_vht_flags & IEEE80211_FVHT_USEVHT40) != 0) {
+ if (htflags == IEEE80211_CHAN_HT40U)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT40U | vhtflags);
+ if (htflags == IEEE80211_CHAN_HT40D)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT40D | vhtflags);
}
+
+ /* If we get here VHT40 is not supported or disabled. */
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT20 | IEEE80211_CHAN_HT20);
+ }
+
+ /* Deprecated check for 160. */
+ if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_160MHZ) &&
+ IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(vap->iv_vht_cap.vht_cap_info) &&
+ (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT160) != 0)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT160 | vhtflags);
+
+ /* Deprecated check for 80P80. */
+ if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80P80MHZ) &&
+ IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(vap->iv_vht_cap.vht_cap_info) &&
+ (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT80P80) != 0)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT80P80 | vhtflags);
+
+ if (ni->ni_vht_chanwidth != IEEE80211_VHT_CHANWIDTH_80MHZ) {
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
+ "%s: invalid VHT BSS bandwidth %d/%d/%d", __func__,
+ ni->ni_vht_chanwidth, ni->ni_vht_chan2);
+
+ _RETURN_CHAN_BITS(0);
}
- return (vhtflags);
+
+ /* CCFS1 > 0 and | CCFS1 - CCFS0 | = 8 */
+ if (ni->ni_vht_chan2 > 0 && (ni->ni_vht_chan2 - ni->ni_vht_chan1) == 8)
+ can_vht160 = can_vht80 = true;
+
+ /* CCFS1 > 0 and | CCFS1 - CCFS0 | > 16 */
+ if (ni->ni_vht_chan2 > 0 && (ni->ni_vht_chan2 - ni->ni_vht_chan1) > 16)
+ can_vht80p80 = can_vht80 = true;
+
+ /* CFFS1 == 0 */
+ if (ni->ni_vht_chan2 == 0)
+ can_vht80 = true;
+
+ if (can_vht160 && (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT160) != 0)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT160 | vhtflags);
+
+ if (can_vht80p80 && (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT80P80) != 0)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT80P80 | vhtflags);
+
+ if (can_vht80 && (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT80) != 0)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT80 | vhtflags);
+
+ if (ht40 && (vap->iv_vht_flags & IEEE80211_FVHT_USEVHT40) != 0) {
+ if (htflags == IEEE80211_CHAN_HT40U)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT40U | vhtflags);
+ if (htflags == IEEE80211_CHAN_HT40D)
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT40D | vhtflags);
+ }
+
+ /* Either we disabled support or got an invalid setting. */
+ _RETURN_CHAN_BITS(IEEE80211_CHAN_VHT20 | IEEE80211_CHAN_HT20);
+#undef _RETURN_CHAN_BITS
}
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 30, 9:56 PM (13 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26408521
Default Alt Text
D49773.id.diff (9 KB)
Attached To
Mode
D49773: net80211: fix VHT160 and VHT80P80 selection and enable in LinuxKPI 802.11
Attached
Detach File
Event Timeline
Log In to Comment