The firmware reports the NSS a radio supports at 160 MHz as a ratio of its 80 MHz NSS. Peer assoc applies that ratio to the peer's NSS instead, so on a radio with a 1:2 ratio a two-stream peer is sent one stream at 160 MHz. The HE 160 and 80+80 MCS maps copy the 80 MHz map, so a 4-chain radio with that ratio offers 4 streams at 160 MHz where it supports 2. Take the 160 MHz NSS from the radio's TX chains, as ath12k does since commit a82ce08775bc ("wifi: ath12k: add extended NSS bandwidth support for 160 MHz"), and limit the 160 and 80+80 MCS maps to the ratio when the firmware reports one. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1 Fixes: f552d6fd2f27 ("ath11k: add support for 80P80 and 160 MHz bandwidth") Assisted-by: LLM Signed-off-by: Julius Bairaktaris --- drivers/net/wireless/ath/ath11k/mac.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 1a237adaa37d1..a842306d65d9c 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -2278,7 +2278,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, if (arg->peer_phymode == MODE_11AC_VHT160 || arg->peer_phymode == MODE_11AC_VHT80_80) { - tx_nss = ath11k_get_nss_160mhz(ar, max_nss); + tx_nss = ath11k_get_nss_160mhz(ar, ar->num_tx_chains); rx_nss = min(arg->peer_nss, tx_nss); arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE; @@ -2588,7 +2588,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, if (arg->peer_phymode == MODE_11AX_HE160 || arg->peer_phymode == MODE_11AX_HE80_80) { - tx_nss = ath11k_get_nss_160mhz(ar, max_nss); + tx_nss = ath11k_get_nss_160mhz(ar, ar->num_tx_chains); rx_nss = min(arg->peer_nss, tx_nss); arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE; @@ -5940,7 +5940,7 @@ static void ath11k_mac_set_hemcsmap(struct ath11k *ar, struct ieee80211_sta_he_cap *he_cap, int band) { - u16 txmcs_map, rxmcs_map; + u16 txmcs_map, rxmcs_map, txmcs_map_160, rxmcs_map_160; u32 i; rxmcs_map = 0; @@ -5958,18 +5958,28 @@ static void ath11k_mac_set_hemcsmap(struct ath11k *ar, else rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); } + + txmcs_map_160 = txmcs_map; + rxmcs_map_160 = rxmcs_map; + if (cap->nss_ratio_enabled) { + for (i = ath11k_get_nss_160mhz(ar, ar->num_tx_chains); i < 8; i++) + txmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); + for (i = ath11k_get_nss_160mhz(ar, ar->num_rx_chains); i < 8; i++) + rxmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); + } + he_cap->he_mcs_nss_supp.rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff); he_cap->he_mcs_nss_supp.tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff); he_cap->he_mcs_nss_supp.rx_mcs_160 = - cpu_to_le16(rxmcs_map & 0xffff); + cpu_to_le16(rxmcs_map_160); he_cap->he_mcs_nss_supp.tx_mcs_160 = - cpu_to_le16(txmcs_map & 0xffff); + cpu_to_le16(txmcs_map_160); he_cap->he_mcs_nss_supp.rx_mcs_80p80 = - cpu_to_le16(rxmcs_map & 0xffff); + cpu_to_le16(rxmcs_map_160); he_cap->he_mcs_nss_supp.tx_mcs_80p80 = - cpu_to_le16(txmcs_map & 0xffff); + cpu_to_le16(txmcs_map_160); } static int ath11k_mac_copy_he_cap(struct ath11k *ar, -- 2.53.0