wifi: ath11k: fix wrong handling of CCMP256 and GCMP ciphers
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: d5c65159f2
("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
This commit is contained in:
parent
9e32058ae6
commit
d2b0ca38d3
3 changed files with 15 additions and 6 deletions
|
@ -1877,8 +1877,7 @@ static void ath11k_dp_rx_h_csum_offload(struct ath11k *ar, struct sk_buff *msdu)
|
||||||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar,
|
int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype)
|
||||||
enum hal_encrypt_type enctype)
|
|
||||||
{
|
{
|
||||||
switch (enctype) {
|
switch (enctype) {
|
||||||
case HAL_ENCRYPT_TYPE_OPEN:
|
case HAL_ENCRYPT_TYPE_OPEN:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
* 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
|
#ifndef ATH11K_DP_RX_H
|
||||||
#define 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_start(struct ath11k_base *ab);
|
||||||
int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer);
|
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 */
|
#endif /* ATH11K_DP_RX_H */
|
||||||
|
|
|
@ -4229,6 +4229,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
|
||||||
|
|
||||||
switch (key->cipher) {
|
switch (key->cipher) {
|
||||||
case WLAN_CIPHER_SUITE_CCMP:
|
case WLAN_CIPHER_SUITE_CCMP:
|
||||||
|
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||||
arg.key_cipher = WMI_CIPHER_AES_CCM;
|
arg.key_cipher = WMI_CIPHER_AES_CCM;
|
||||||
/* TODO: Re-check if flag is valid */
|
/* TODO: Re-check if flag is valid */
|
||||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
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_txmic_len = 8;
|
||||||
arg.key_rxmic_len = 8;
|
arg.key_rxmic_len = 8;
|
||||||
break;
|
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:
|
||||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||||
arg.key_cipher = WMI_CIPHER_AES_GCM;
|
arg.key_cipher = WMI_CIPHER_AES_GCM;
|
||||||
|
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
|
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 ath11k_base *ab = ar->ab;
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
|
enum hal_encrypt_type enctype;
|
||||||
|
unsigned int mic_len;
|
||||||
dma_addr_t paddr;
|
dma_addr_t paddr;
|
||||||
int buf_id;
|
int buf_id;
|
||||||
int ret;
|
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_deauth(hdr->frame_control) ||
|
||||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||||
ieee80211_has_protected(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue