]> 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 12:54:47 +0000 (13:54 +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 419c9497800af917fddda7b20c54c8b9583f0343..9521fcb2c11ceefc9a3cbbfe19cbd3603dd0a8e1 100644 (file)
@@ -2225,9 +2225,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 suppoerted in 11ac standard.
index bfca9d36398107327da56e3a961c49646b736334..6f1fd7d661a89c30d0c822f62f7723f9f41ae287 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;