Date: Mon, 24 Feb 2025 03:08:15 GMT From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: f9c7a07d7f5e - main - LinuxKPI: 802.11: synchronize LinuxKPI 802.11 sta from net80211 ni Message-ID: <202502240308.51O38Fk3083226@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=f9c7a07d7f5e1c3694b463423c43051451b61e87 commit f9c7a07d7f5e1c3694b463423c43051451b61e87 Author: Bjoern A. Zeeb <bz@FreeBSD.org> AuthorDate: 2024-12-30 06:35:03 +0000 Commit: Bjoern A. Zeeb <bz@FreeBSD.org> CommitDate: 2025-02-24 01:32:22 +0000 LinuxKPI: 802.11: synchronize LinuxKPI 802.11 sta from net80211 ni Have a wrapper function dealing with the synchronization for all the dfferent standards (HT and VHT currently). In case HT or VHT is not supported make sure to turn the LinuxKPI "supported" flag off for that. Previously if it was on once it would never be turned off. For HT and VHT properly compute the NSS and also set the max_amsdu_len correctly. Set the NSS directly in the function (which is called in proper order for this) rather than passing the results back and do the setting in the caller. The only thing we need to make sure upfront is that it remains at least 1 (see f5a58c2da239). This all makes the caller and code a tiny bit simpler and work better. There is more synchronization to be done between the chanctx and the deflink bandwidth, which needs to happen dynamically in case net80211 decides to change that under us but no native driver seems to properly implement this (if at all). HT20-only, HT40, and VHT80 are supposed to work for now at least. VHT160 and VHT80P80 have further debug work to do as it does not yet seem to be consistently set in all cases to sync from. Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/compat/linuxkpi/common/src/linux_80211.c | 133 +++++++++++++++++++-------- 1 file changed, 96 insertions(+), 37 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 8daa2fa4dc8e..b53d8eaa7925 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -367,19 +367,17 @@ lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS) #if defined(LKPI_80211_HT) static void -lkpi_sta_sync_ht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni, int *ht_rx_nss) +lkpi_sta_sync_ht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni) { struct ieee80211vap *vap; uint8_t *ie; struct ieee80211_ht_cap *htcap; int i, rx_nss; - if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) + if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) { + sta->deflink.ht_cap.ht_supported = false; return; - - if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && - IEEE80211_IS_CHAN_HT40(ni->ni_chan)) - sta->deflink.bandwidth = IEEE80211_STA_RX_BW_40; + } sta->deflink.ht_cap.ht_supported = true; @@ -401,43 +399,116 @@ lkpi_sta_sync_ht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni, i sta->deflink.ht_cap.cap = htcap->cap_info; sta->deflink.ht_cap.mcs = htcap->mcs; + if ((sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) != 0) + sta->deflink.bandwidth = IEEE80211_STA_RX_BW_40; + + /* + * 802.11n-2009 20.6 Parameters for HT MCSs gives the mandatory/ + * optional MCS for Nss=1..4. We need to check the first four + * MCS sets from the Rx MCS Bitmask; then there is MCS 32 and + * MCS33.. is UEQM. + */ rx_nss = 0; - for (i = 0; i < nitems(htcap->mcs.rx_mask); i++) { + for (i = 0; i < 4; i++) { if (htcap->mcs.rx_mask[i]) rx_nss++; } - if (ht_rx_nss != NULL) - *ht_rx_nss = rx_nss; + if (rx_nss > 0) + sta->deflink.rx_nss = rx_nss; - IMPROVE("sta->wme, sta->deflink.agg.max*"); + IMPROVE("sta->wme"); + + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU) + sta->deflink.agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935; + else + sta->deflink.agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839; + sta->deflink.agg.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA; +#ifdef __handled_by_driver__ /* iwlwifi only? actually unused? */ + for (i = 0; i < nitems(sta.deflink.agg.max_tid_amsdu_len); i++) { + sta->deflink.agg.max_tid_amsdu_len[j] = ; + } +#endif } #endif #if defined(LKPI_80211_VHT) static void -lkpi_sta_sync_vht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni, int *vht_rx_nss) +lkpi_sta_sync_vht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni) { + uint32_t width; + int rx_nss; + uint16_t rx_mcs_map; + uint8_t mcs; - if ((ni->ni_flags & IEEE80211_NODE_VHT) == 0) + if ((ni->ni_flags & IEEE80211_NODE_VHT) == 0) { + sta->deflink.vht_cap.vht_supported = false; return; + } - if (IEEE80211_IS_CHAN_VHT(ni->ni_chan)) { -#ifdef __notyet__ - if (IEEE80211_IS_CHAN_VHT80P80(ni->ni_chan)) { - sta->deflink.bandwidth = IEEE80211_STA_RX_BW_160; /* XXX? */ - } else + sta->deflink.vht_cap.vht_supported = true; + + sta->deflink.vht_cap.cap = ni->ni_vhtcap; + sta->deflink.vht_cap.vht_mcs = ni->ni_vht_mcsinfo; + + 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 - if (IEEE80211_IS_CHAN_VHT160(ni->ni_chan)) + 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 if (IEEE80211_IS_CHAN_VHT80(ni->ni_chan)) + else +#endif sta->deflink.bandwidth = IEEE80211_STA_RX_BW_80; } - IMPROVE("VHT sync ni to sta"); - return; + + rx_nss = 0; + rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map; + for (int i = 7; i >= 0; i--) { + mcs = rx_mcs_map >> (2 * i); + mcs &= 0x3; + if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) { + rx_nss = i + 1; + break; + } + } + if (rx_nss > 0) + sta->deflink.rx_nss = rx_nss; + + switch (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: + sta->deflink.agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; + break; + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: + sta->deflink.agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991; + break; + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895: + default: + sta->deflink.agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895; + break; + } } #endif +static void +lkpi_sta_sync_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni) +{ + +#if defined(LKPI_80211_HT) + lkpi_sta_sync_ht_from_ni(sta, ni); +#endif +#if defined(LKPI_80211_VHT) + lkpi_sta_sync_vht_from_ni(sta, ni); +#endif +} + static void lkpi_lsta_dump(struct lkpi_sta *lsta, struct ieee80211_node *ni, const char *_f, int _l) @@ -480,8 +551,6 @@ lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], struct ieee80211_vif *vif; struct ieee80211_sta *sta; int band, i, tid; - int ht_rx_nss; - int vht_rx_nss; lsta = malloc(sizeof(*lsta) + hw->sta_data_size, M_LKPI80211, M_NOWAIT | M_ZERO); @@ -581,18 +650,9 @@ lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], sta->deflink.bandwidth = IEEE80211_STA_RX_BW_20; sta->deflink.rx_nss = 1; - ht_rx_nss = 0; -#if defined(LKPI_80211_HT) - lkpi_sta_sync_ht_from_ni(sta, ni, &ht_rx_nss); -#endif - vht_rx_nss = 0; -#if defined(LKPI_80211_VHT) - lkpi_sta_sync_vht_from_ni(sta, ni, &vht_rx_nss); -#endif + lkpi_sta_sync_from_ni(sta, ni); - sta->deflink.rx_nss = MAX(ht_rx_nss, sta->deflink.rx_nss); - sta->deflink.rx_nss = MAX(vht_rx_nss, sta->deflink.rx_nss); - IMPROVE("he, ... smps_mode, .."); + IMPROVE("he, eht, bw_320, ... smps_mode, .."); /* Link configuration. */ IEEE80211_ADDR_COPY(sta->deflink.addr, sta->addr); @@ -2531,10 +2591,9 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int IMPROVE("net80211 does not consider node authorized"); } -#if defined(LKPI_80211_HT) + sta->deflink.rx_nss = MAX(1, sta->deflink.rx_nss); IMPROVE("Is this the right spot, has net80211 done all updates already?"); - lkpi_sta_sync_ht_from_ni(sta, ni, NULL); -#endif + lkpi_sta_sync_from_ni(sta, ni); /* Update sta_state (ASSOC to AUTHORIZED). */ KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502240308.51O38Fk3083226>