From nobody Sun Jun 1 15:12:37 2025 X-Original-To: dev-commits-src-main@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 4b9L7T42KNz5xmtr; Sun, 01 Jun 2025 15:12:37 +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 4b9L7T38j2z41rJ; Sun, 01 Jun 2025 15:12:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1748790757; 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=6Im05SBYQLBzw4hpA2ufmFfk8A6goUbbiZGz8h6RjZA=; b=Cpin0Oh5Xka3fP1GSlP6dp6c8tNP7LYzxdvJuv7Ei7Ao+BCrXmRUqgqwBP5MzKAgolXRaN MAryXQbKfkE7jTIX+h6t8OXad5QNnVzwQZdvmEseXarzXILrpsRJ+jei3vjVNLe4FBhsxI 8SxCTcZxz1WvMgjGTdwhIWR3Yr4mt/mIEp7LoqMjboWj6xkxH9emvCyEXhSdmQLJE1BWIR mcs3jewXZmLstNkkkECRmaeYECYZd1VyK2b1zb2+OCsLkxSs5CJLF0u3fcAmgsEG4RpjWD hbbWt7z6TV2XHNfUDnqjUnVAAvT7Fzr3cbN2ZJCKWPgV45VtqxVHtBmtJZAyWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1748790757; 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=6Im05SBYQLBzw4hpA2ufmFfk8A6goUbbiZGz8h6RjZA=; b=J8DhmkWZhPBEQddPJAZua2OSaPClTm+x/kesTeODRC0rAihS79TORSBMv0QqXMb8NxMOfh 72+tvB4wqxSUHC052Ltysv3WF6/wHth4cds5jaXgUWXTFU78vaG/cMrox3MSRZRFtkJbM3 EJ01xndxCnOn5i1PjJ152pMNM0asgK2uGArvIxK1YQ1SyF6N8ZvasV0nxjF0O9YL6gaUY+ AhAw2jT/S549t2fvtBKKKTyEZGSiqtE6wvSOmr7BV4svBdR4SIuQGhNoen90DXg+qrvAZu NdsoZllCvm6ArN3OkxO4N05Zyy/aXfXEGzTS6YIwjITZSj/k4mW43i8DmOEszQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1748790757; a=rsa-sha256; cv=none; b=jbUKlYQRHgTH5pNd2iRCz4nyrZINAHKYa6+oB4BJg/mH7c2WXHHIw6Bn7rQO5BBkZcHZfQ b8d+zwq3AviZ1LN1TUVhqQcgOfXZoIH0XkmhTeYNOB+1P+oTUGDEa0gE1DBeb+391xEdKy k1l9RL3GYA1utL92PYoySlK65SnQVF+RcOXfRTRd9QRfGrCatvzWHFlX/MjeD22uwO0eAr 4yokPYvedDdovu5Cn7ciBnxmXQZSnjnHS0nqKl9jodOoNLoZg9vGs8Nd/U0pZviXsDWO55 bSjQZocq4sI1jmWq1DW857zgLckJQu9pq6vrCVkZa/1xbHuCIz2n7hKcYP2o+w== 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 4b9L7T2RR7zCcC; Sun, 01 Jun 2025 15:12:37 +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 551FCbMW008026; Sun, 1 Jun 2025 15:12:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 551FCbXu008023; Sun, 1 Jun 2025 15:12:37 GMT (envelope-from git) Date: Sun, 1 Jun 2025 15:12:37 GMT Message-Id: <202506011512.551FCbXu008023@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 4bf049bfeefd - main - net80211: fix VHT160 and VHT80P80 selection and enable in LinuxKPI 802.11 List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 4bf049bfeefd988fed93149138c422b05d38251b Auto-Submitted: auto-generated The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=4bf049bfeefd988fed93149138c422b05d38251b commit 4bf049bfeefd988fed93149138c422b05d38251b Author: Bjoern A. Zeeb AuthorDate: 2025-04-11 01:44:50 +0000 Commit: Bjoern A. Zeeb CommitDate: 2025-06-01 15:12:27 +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 MFC after: 3 days Reviewed by: thj Differential Revision: https://reviews.freebsd.org/D49773 --- 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 4540c1aaf1c1..42d23629bc0f 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 1e685eb094f9..90b329500128 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -945,12 +945,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 d4e84ce92531..5ec80e3646b8 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -1931,66 +1931,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); + } + + /* 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 } /*