]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: ath11k: fix VHT MCS assignment
authorBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Fri, 17 Oct 2025 01:48:59 +0000 (09:48 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Dec 2025 13:02:35 +0000 (14:02 +0100)
[ Upstream commit 47d0cd6bccb4604192633cc8d29511e85d811fc0 ]

While associating, firmware needs to know peer's receive capability to
calculate its own VHT transmit MCS, currently host sends this information
to firmware via mcs->rx_mcs_set field, this is wrong as firmware actually
takes it from mcs->tx_mcs_set field. Till now there is no failure seen
due to this, most likely because almost all peers are advertising the
same capability for both transmit and receive. Swap the assignment to
fix it.

Besides, rate control mask is meant to limit our own transmit MCS, hence
need to go via mcs->tx_mcs_set field. With the aforementioned swapping
done, change is needed as well to apply it to the peer's receive
capability rather than transmit capability.

Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20251017-ath11k-mcs-assignment-v1-1-da40825c1783@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath11k/wmi.c
drivers/net/wireless/ath/ath11k/wmi.h

index 0e41b5a91d66da872c2520a95c3d4af379a504da..49c639d73d58d46f869aec40f6439268526ea1bb 100644 (file)
@@ -2235,9 +2235,9 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
        arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
        arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
        arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
+       arg->rx_mcs_set = ath11k_peer_assoc_h_vht_limit(arg->rx_mcs_set, vht_mcs_mask);
        arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
-       arg->tx_mcs_set = ath11k_peer_assoc_h_vht_limit(
-               __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
+       arg->tx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
 
        /* In IPQ8074 platform, VHT mcs rate 10 and 11 is enabled by default.
         * VHT mcs rate 10 and 11 is not supported in 11ac standard.
index e3b444333deed17849042c11bb4cdd71e27042e7..649839d2432931f300f0648b03e63f7d888a3959 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-3-Clause-Clear
 /*
  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  */
 #include <linux/skbuff.h>
 #include <linux/ctype.h>
@@ -2061,10 +2061,13 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
        cmd->peer_bw_rxnss_override |= param->peer_bw_rxnss_override;
 
        if (param->vht_capable) {
-               mcs->rx_max_rate = param->rx_max_rate;
-               mcs->rx_mcs_set = param->rx_mcs_set;
-               mcs->tx_max_rate = param->tx_max_rate;
-               mcs->tx_mcs_set = param->tx_mcs_set;
+               /* firmware interprets mcs->tx_mcs_set field as peer's
+                * RX capability
+                */
+               mcs->tx_max_rate = param->rx_max_rate;
+               mcs->tx_mcs_set = param->rx_mcs_set;
+               mcs->rx_max_rate = param->tx_max_rate;
+               mcs->rx_mcs_set = param->tx_mcs_set;
        }
 
        /* HE Rates */
index 9fcffaa2f383c9348f5f07b139763de50212d856..6e9354297e71d377be4499a9b4271ba5456f0dbb 100644 (file)
@@ -4133,8 +4133,10 @@ struct wmi_rate_set {
 struct wmi_vht_rate_set {
        u32 tlv_header;
        u32 rx_max_rate;
+       /* MCS at which the peer can transmit */
        u32 rx_mcs_set;
        u32 tx_max_rate;
+       /* MCS at which the peer can receive */
        u32 tx_mcs_set;
        u32 tx_max_mcs_nss;
 } __packed;