From nobody Wed Jun 11 09:14:04 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bHKj95jLCz600Bk; Wed, 11 Jun 2025 09:14:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bHKj91pcyz3lJ6; Wed, 11 Jun 2025 09:14:05 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1749633245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=i1WaEPY3QogGg+nB4Wvtxf+0zsQX1Mb0ENGE91NIdK0=; b=CowPTonXbIi3CRKaXU2RgQUDiVvkNbjxTj3HWO5G4z3ZSAFj/IWzdaoZbGY4mR8srATYvo B6j73Gmn9v3SndRNxb+/D8+vKUMCQl74e4j4sujpdhKJ6cqKG2nrFLctZBWVMFbzc3RSAp DXKJFOf0lwjjTJbMXdoeqSU+S3RhYOA+mVG/WKo8wOM7RR7XKOuqFHRFJE44Gp4mHww4cY LQeYk0yByy9UXtKyMWWCiEfGcSlclFNs9MVnSS1XxoLu2CWcY6T1p8qp0Msn1257xFdVFh RpqNDAqPbt8ChiJcitilM/4/HdGKOYrbAW0qRoNZdPppiqrfaVL2CH3cHwfK+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1749633245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=i1WaEPY3QogGg+nB4Wvtxf+0zsQX1Mb0ENGE91NIdK0=; b=qRvhckXiZRY9xAdePhFhZk5a/XTHnqApPsK2mR8flBEM1LER+UCxPTLW/EwfIcLQPqFd1k NPpidHMYlWtWWGudtMd0RT5ogt1h4u2v+aqAlWAUk2e4hsMTeHdnQ6QlALoiGK9t9DNVEa YNMtgNW1igKOMXpYMcPj4x+m+qz/A/DGmGiHUEB4udiTAzw3ZHcq3ssW+RQ7DqRl6XvVwj TWGm3mv9kI9x+BnvLWmz81hvjuV0v1dCA4/9xZJMk6w09jNZtb6XBVE0l+rDgvwoZ0TDgB S3tD/DbOdgEPXY2EjCYrKLqVgnjfPmuQcg4NvCJoaq0vI1LE601eQ/cpfJkdwg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1749633245; a=rsa-sha256; cv=none; b=vN+eBej9xd3MjDDg7z50Qp/siDkb3tCV0XTzCoKsNC/uuw0mVKrY0qY8V7ip2JJiKQbWCs VulFV4knxzerzmpS/QPGqS/1xG2urZf5k2/C2ECNxFRQwVtXHuGQwnNQRqixu4swuwG4qb YamjJHWrLMtT/2NqPNS84miQxTWtp271r/HVxfNBStfYjgU8QzORLSLjcC0Fez7ZSW4Bve 0HXPU2zK7A/d2/2BegNm0RxlbqJsyoP6RG+aJLijQcL/urjT2DjbT8j09Q9W4fjS5nc2wr g8kUFI9kV8v1BDOyBa8CM+TzR7gn+GHRjOUYFrBd/NQc7o0bk5mu6x37FO1FeA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bHKj90QN0z527; Wed, 11 Jun 2025 09:14:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 55B9E4WN061615; Wed, 11 Jun 2025 09:14:04 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 55B9E4oP061612; Wed, 11 Jun 2025 09:14:04 GMT (envelope-from git) Date: Wed, 11 Jun 2025 09:14:04 GMT Message-Id: <202506110914.55B9E4oP061612@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: ccdd6285df5d - stable/14 - net80211: fix VHT160 and VHT80P80 selection and enable in LinuxKPI 802.11 List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: ccdd6285df5dfa81c22e36685bab9be184a4e733 Auto-Submitted: auto-generated The branch stable/14 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=ccdd6285df5dfa81c22e36685bab9be184a4e733 commit ccdd6285df5dfa81c22e36685bab9be184a4e733 Author: Bjoern A. Zeeb AuthorDate: 2025-04-11 01:44:50 +0000 Commit: Bjoern A. Zeeb CommitDate: 2025-06-10 23:37:22 +0000 net80211: fix VHT160 and VHT80P80 selection and enable in LinuxKPI 802.11 Between 802.11ac-2013 and 802.11-2020 some fields were deprecated and the way VHT160 and VHT80P80 are selected has changed. In order to get onto VHT160 with modern APs adopt and support both the deprecated as well as the new logic. For simplicity of blocks we pull out the non-HT40 handling early on, followed by the "use HT", followed by the deprectaed options and then the 80Mhz channel width. In all cases keep checking (a) what is locally supported, (b) what the user has locally allowed (FVHT flags, [-]vht160 [-]vht80p80 [-]vht80 [-]vht40), as well as (c) what is announced. Provide possible fallbacks to lower channel widths in all cases (but VHT20, which means VHT is disabled). With this enable VHT160 and VHT80P80 in the LinuxKPI 802.11 driver compat code as well. Sponsored by: The FreeBSD Foundation Reviewed by: thj Differential Revision: https://reviews.freebsd.org/D49773 (cherry picked from commit 4bf049bfeefd988fed93149138c422b05d38251b) --- sys/compat/linuxkpi/common/src/linux_80211.c | 9 +- sys/net80211/ieee80211.h | 9 +- sys/net80211/ieee80211_ht.c | 178 ++++++++++++++++++--------- 3 files changed, 129 insertions(+), 67 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 82eaa64790b4..da4342b0c479 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -547,19 +547,15 @@ lkpi_sta_sync_vht_from_ni(struct ieee80211_vif *vif, struct ieee80211_sta *sta, 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 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int #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 index a5008796d89f..ddc062b285c4 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -870,12 +870,15 @@ struct ieee80211_vht_cap { 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 index 821c45c9f4e7..45b373329bff 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -1932,66 +1932,132 @@ ieee80211_ht_updateparams(struct ieee80211_node *ni, 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); } - return (vhtflags); + + /* 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); + } + + /* 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 } /*