wifi: ath11k: fix wrong handling of CCMP256 and GCMP ciphers
authorBaochen Qiang <quic_bqiang@quicinc.com>
Tue, 11 Jun 2024 06:42:34 +0000 (09:42 +0300)
committerKalle Valo <quic_kvalo@quicinc.com>
Tue, 11 Jun 2024 18:43:30 +0000 (21:43 +0300)
Currently for CCMP256, GCMP128 and GCMP256 ciphers, in ath11k_install_key()
IEEE80211_KEY_FLAG_GENERATE_IV_MGMT is not set. And in ath11k_mac_mgmt_tx_wmi()
a length of IEEE80211_CCMP_MIC_LEN is reserved for all ciphers.

This results in unexpected management frame drop in case either of above 3 ciphers
is used. The reason is, without IEEE80211_KEY_FLAG_GENERATE_IV_MGMT set, mac80211
will not generate CCMP/GCMP headers in frame for ath11k. Also MIC length reserved
is wrong. Such frame is dropped later by hardware:

ath11k_pci 0000:5a:00.0: mac tx mgmt frame, buf id 0
ath11k_pci 0000:5a:00.0: mgmt tx compl ev pdev_id 1, desc_id 0, status 1

From user point of view, we have observed very low throughput due to this issue:
action frames are all dropped so ADDBA response from DUT never reaches AP. AP
can not use aggregation thus throughput is low.

Fix this by setting IEEE80211_KEY_FLAG_GENERATE_IV_MGMT flag and by reserving proper
MIC length for those ciphers.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1

Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Reported-by: Yaroslav Isakov <yaroslav.isakov@gmail.com>
Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com>
Closes: https://lore.kernel.org/all/CADS+iDX5=JtJr0apAtAQ02WWBxgOFEv8G063vuGYwDTC8AVZaw@mail.gmail.com
Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://msgid.link/20240605014826.22498-1-quic_bqiang@quicinc.com
drivers/net/wireless/ath/ath11k/dp_rx.c
drivers/net/wireless/ath/ath11k/dp_rx.h
drivers/net/wireless/ath/ath11k/mac.c

index 198fb359a688c5248768e2db5e6a5a76a387c665..86485580dd895378a07f531dac4e0c2cda115372 100644 (file)
@@ -1877,8 +1877,7 @@ static void ath11k_dp_rx_h_csum_offload(struct ath11k *ar, struct sk_buff *msdu)
                          CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
 }
 
-static int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar,
-                                      enum hal_encrypt_type enctype)
+int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype)
 {
        switch (enctype) {
        case HAL_ENCRYPT_TYPE_OPEN:
index 623da3bf9dc81035ed7ce5db3258515c172b6f08..c322e30caa9683b53e49beca2a41edde59566cef 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause-Clear */
 /*
  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #ifndef ATH11K_DP_RX_H
 #define ATH11K_DP_RX_H
@@ -95,4 +96,6 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
 int ath11k_dp_rx_pktlog_start(struct ath11k_base *ab);
 int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer);
 
+int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype);
+
 #endif /* ATH11K_DP_RX_H */
index 29af015a16f9aa283f7e3c3c290901ac1d557d89..bb56160048ba589b304b205db0d91111211be001 100644 (file)
@@ -4229,6 +4229,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
 
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_CCMP:
+       case WLAN_CIPHER_SUITE_CCMP_256:
                arg.key_cipher = WMI_CIPHER_AES_CCM;
                /* TODO: Re-check if flag is valid */
                key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
@@ -4238,12 +4239,10 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
                arg.key_txmic_len = 8;
                arg.key_rxmic_len = 8;
                break;
-       case WLAN_CIPHER_SUITE_CCMP_256:
-               arg.key_cipher = WMI_CIPHER_AES_CCM;
-               break;
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
                arg.key_cipher = WMI_CIPHER_AES_GCM;
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
                break;
        default:
                ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
@@ -5903,7 +5902,10 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
 {
        struct ath11k_base *ab = ar->ab;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
        struct ieee80211_tx_info *info;
+       enum hal_encrypt_type enctype;
+       unsigned int mic_len;
        dma_addr_t paddr;
        int buf_id;
        int ret;
@@ -5927,7 +5929,12 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
                     ieee80211_is_deauth(hdr->frame_control) ||
                     ieee80211_is_disassoc(hdr->frame_control)) &&
                     ieee80211_has_protected(hdr->frame_control)) {
-                       skb_put(skb, IEEE80211_CCMP_MIC_LEN);
+                       if (!(skb_cb->flags & ATH11K_SKB_CIPHER_SET))
+                               ath11k_warn(ab, "WMI management tx frame without ATH11K_SKB_CIPHER_SET");
+
+                       enctype = ath11k_dp_tx_get_encrypt_type(skb_cb->cipher);
+                       mic_len = ath11k_dp_rx_crypto_mic_len(ar, enctype);
+                       skb_put(skb, mic_len);
                }
        }