]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath11k: fix peer HE MCS assignment
authorBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Fri, 17 Oct 2025 01:49:00 +0000 (09:49 +0800)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Thu, 23 Oct 2025 13:59:20 +0000 (06:59 -0700)
In ath11k_wmi_send_peer_assoc_cmd(), peer's transmit MCS is sent to
firmware as receive MCS while peer's receive MCS sent as transmit MCS,
which goes against firmwire's definition.

While connecting to a misbehaved AP that advertises 0xffff (meaning not
supported) for 160 MHz transmit MCS map, firmware crashes due to 0xffff
is assigned to he_mcs->rx_mcs_set field.

Ext Tag: HE Capabilities
    [...]
    Supported HE-MCS and NSS Set
[...]
        Rx and Tx MCS Maps 160 MHz
    [...]
            Tx HE-MCS Map 160 MHz: 0xffff

Swap the assignment to fix this issue.

As the HE rate control mask is meant to limit our own transmit MCS, it
needs to go via he_mcs->rx_mcs_set field. With the aforementioned swapping
done, change is needed as well to apply it to the peer's receive MCS.

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: 61fe43e7216d ("ath11k: add support for setting fixed HE rate/gi/ltf")
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-2-da40825c1783@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath11k/wmi.c

index 367ca0c90167b8e3ba03f60e65965936391085d2..ebde4208791ce193612b038f1c270b3f86d244a9 100644 (file)
@@ -2522,10 +2522,10 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
                        he_tx_mcs = v;
                }
                v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
+               v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
                arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
 
                v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
-               v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
                arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
 
                arg->peer_he_mcs_count++;
@@ -2535,10 +2535,10 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
 
        default:
                v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
+               v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
                arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
 
                v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
-               v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask);
                arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
 
                arg->peer_he_mcs_count++;
index 942dfeb8b1af8553d1c872ac1444bfacf11f44cd..edff6fb613449c96edd049b8531d46e5f680cfea 100644 (file)
@@ -2091,8 +2091,11 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
                                     FIELD_PREP(WMI_TLV_LEN,
                                                sizeof(*he_mcs) - TLV_HDR_SIZE);
 
-               he_mcs->rx_mcs_set = param->peer_he_tx_mcs_set[i];
-               he_mcs->tx_mcs_set = param->peer_he_rx_mcs_set[i];
+               /* firmware interprets mcs->rx_mcs_set field as peer's
+                * RX capability
+                */
+               he_mcs->rx_mcs_set = param->peer_he_rx_mcs_set[i];
+               he_mcs->tx_mcs_set = param->peer_he_tx_mcs_set[i];
                ptr += sizeof(*he_mcs);
        }