wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-failed-to-remove-key-issue.patch
John Crispin b9b03a6e38 ipq95xx: add Qualcomm wifi-7 support
Signed-off-by: John Crispin <john@phrozen.org>
2023-04-10 14:25:48 +02:00

475 lines
16 KiB
Diff

From 44e945216cdc8cd5aba32a4374ab8a210619745e Mon Sep 17 00:00:00 2001
From: Sivashankari Madhavan <quic_sivamadh@quicinc.com>
Date: Mon, 26 Sep 2022 14:22:27 +0530
Subject: [PATCH] ath12k: Fix failed to remove key issue
While enabling the AP mode, driver caches the key information
which received before the vdev create events. This cached
information are used to install the keys after vdev create.
Once this key information are cached properly, then mac80211
sets KEY_FLAG_UPLOADED_TO_HARDWARE flag to the key->flags.
Based on this flag, while bringing down AP, driver tries to
disable the uninstalled keys which leads to following failuremessages.
wlan1: failed to remove key (4, ff:ff:ff:ff:ff:ff) from hardware (1)
Fix it by avoiding the irrelevant key information caching and
add support to cache the list of key information.
Signed-off-by: Sivashankari Madhavan <quic_sivamadh@quicinc.com>
---
drivers/net/wireless/ath/ath12k/core.c | 14 +--
drivers/net/wireless/ath/ath12k/core.h | 4 +-
drivers/net/wireless/ath/ath12k/dp.c | 3 +-
drivers/net/wireless/ath/ath12k/dp_tx.c | 3 +-
drivers/net/wireless/ath/ath12k/mac.c | 118 ++++++++++++++----------
drivers/net/wireless/ath/ath12k/wmi.c | 7 +-
6 files changed, 89 insertions(+), 60 deletions(-)
Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c
===================================================================
--- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c
+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c
@@ -1202,14 +1202,16 @@ int ath12k_core_qmi_firmware_ready(struc
return ret;
}
+ ag = ab->ag;
+
switch (ath12k_crypto_mode) {
case ATH12K_CRYPT_MODE_SW:
- set_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
- set_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags);
+ set_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags);
+ set_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags);
break;
case ATH12K_CRYPT_MODE_HW:
- clear_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
- clear_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags);
+ clear_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags);
+ clear_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags);
break;
default:
ath12k_info(ab, "invalid crypto_mode: %d\n", ath12k_crypto_mode);
@@ -1217,9 +1219,7 @@ int ath12k_core_qmi_firmware_ready(struc
}
if (ath12k_frame_mode == ATH12K_HW_TXRX_RAW)
- set_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags);
-
- ag = ab->ag;
+ set_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags);
mutex_lock(&ag->mutex_lock);
mutex_lock(&ab->core_lock);
Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h
===================================================================
--- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h
+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h
@@ -287,8 +287,8 @@ struct ath12k_tx_conf {
};
struct ath12k_key_conf {
- bool changed;
enum set_key_cmd cmd;
+ struct list_head list;
struct ieee80211_sta *sta;
struct ieee80211_key_conf *key;
};
@@ -938,6 +938,7 @@ struct vendor_info {
struct ath12k_hw {
struct ieee80211_hw *hw;
const struct ieee80211_ops *ops;
+ struct ath12k_hw_group *ag;
/* To synchronize concurrent synchronous mac80211 callback operations,
* concurrent debugfs configuration and concurrent FW statistics events.
Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c
===================================================================
--- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.c
+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c
@@ -352,13 +352,14 @@ static
void ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif *arvif,
u32 *bank_config)
{
+ struct ath12k_hw_group *ag = ab->ag;
enum hal_encrypt_type encrypt_type = 0;
/* Only valid for raw frames with HW crypto enabled.
* With SW crypto, mac80211 sets key per packet
*/
if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
- test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags) &&
+ test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags) &&
arvif->key_cipher != INVALID_CIPHER)
encrypt_type = ath12k_dp_tx_get_encrypt_type(arvif->key_cipher);
else
Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c
===================================================================
--- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_tx.c
+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c
@@ -113,6 +113,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru
struct ath12k_sta *arsta, struct sk_buff *skb)
{
struct ath12k_base *ab = ar->ab;
+ struct ath12k_hw_group *ag = ab->ag;
struct ath12k_dp *dp = &ab->dp;
struct hal_tx_info ti = {0};
struct ath12k_tx_desc_info *tx_desc = NULL;
@@ -202,7 +203,7 @@ tcl_ring_sel:
ath12k_dp_tx_encap_nwifi(skb);
break;
case HAL_TCL_ENCAP_TYPE_RAW:
- if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
+ if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) {
ret = -EINVAL;
goto fail_remove_tx_buf;
}
Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c
===================================================================
--- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mac.c
+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c
@@ -4349,6 +4349,7 @@ static int ath12k_install_key(struct ath
{
int ret;
struct ath12k *ar = arvif->ar;
+ struct ath12k_hw_group *ag = ar->ab->ag;
struct wmi_vdev_install_key_arg arg = {
.vdev_id = arvif->vdev_id,
.key_idx = key->keyidx,
@@ -4362,7 +4363,7 @@ static int ath12k_install_key(struct ath
reinit_completion(&ar->install_key_done);
- if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
+ if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags))
return 0;
if (cmd == DISABLE_KEY) {
@@ -4396,7 +4397,7 @@ static int ath12k_install_key(struct ath
return -EOPNOTSUPP;
}
- if (test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags))
+ if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags))
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
@@ -4476,27 +4477,6 @@ static int ath12k_mac_set_key(struct ath
ab = ar->ab;
- /* BIP needs to be done in software */
- if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
- key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
- key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
- key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) {
- ret = 1;
- goto out;
- }
-
- if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
- ret = 1;
- goto out;
- }
-
- if (key->keyidx > WMI_MAX_KEY_INDEX) {
- ret = -ENOSPC;
- goto out;
- }
-
- mutex_lock(&ar->conf_mutex);
-
if (sta)
peer_addr = sta->addr;
else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
@@ -4518,12 +4498,12 @@ static int ath12k_mac_set_key(struct ath
ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",
peer_addr);
ret = -EOPNOTSUPP;
- goto exit;
+ goto out;
} else {
/* if the peer doesn't exist there is no key to disable
* anymore
*/
- goto exit;
+ goto out;
}
}
@@ -4535,13 +4515,13 @@ static int ath12k_mac_set_key(struct ath
ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);
if (ret) {
ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret);
- goto exit;
+ goto out;
}
ret = ath12k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
if (ret) {
ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret);
- goto exit;
+ goto out;
}
spin_lock_bh(&ab->base_lock);
@@ -4587,8 +4567,6 @@ static int ath12k_mac_set_key(struct ath
spin_unlock_bh(&ab->base_lock);
-exit:
- mutex_unlock(&ar->conf_mutex);
out:
return ret;
}
@@ -4597,18 +4575,47 @@ static int ath12k_mac_op_set_key(struct
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct ath12k *ar;
struct ath12k_hw *ah = hw->priv;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_hw_group *ag = ah->ag;
+ struct ath12k_key_conf *key_conf = NULL;
+ struct ath12k *ar;
int ret;
-
+
mutex_lock(&ah->conf_mutex);
+ /* BIP needs to be done in software */
+ if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
+ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
+ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
+ key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) {
+ ret = 1;
+ goto out;
+ }
+
+ if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags)) {
+ ret = 1;
+ goto out;
+ }
+
+ if (key->keyidx > WMI_MAX_KEY_INDEX) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
if (!arvif->is_created) {
- arvif->cache.key_conf.cmd = cmd;
- arvif->cache.key_conf.sta = sta;
- arvif->cache.key_conf.key = key;
- arvif->cache.key_conf.changed = true;
+ key_conf = kzalloc(sizeof(*key_conf), GFP_ATOMIC);
+
+ if (!key_conf) {
+ ath12k_info(NULL, "failed to alloc cache key config\n");
+ goto out;
+ }
+
+ key_conf->cmd = cmd;
+ key_conf->sta = sta;
+ key_conf->key = key;
+
+ list_add_tail(&key_conf->list, &arvif->cache.key_conf.list);
ath12k_info(NULL, "set key param cached since vif not assign to radio\n");
mutex_unlock(&ah->conf_mutex);
@@ -4618,10 +4625,15 @@ static int ath12k_mac_op_set_key(struct
return 0;
}
-
+
ar = arvif->ar;
+
+ mutex_lock(&ar->conf_mutex);
+
ret = ath12k_mac_set_key(ar, cmd, vif, sta, key);
+ mutex_unlock(&ar->conf_mutex);
+out:
mutex_unlock(&ah->conf_mutex);
return ret;
}
@@ -7376,6 +7388,7 @@ static void ath12k_mac_update_vif_offloa
struct ieee80211_vif *vif)
{
struct ath12k_base *ab = ar->ab;
+ struct ath12k_hw_group *ag = ab->ag;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
u32 param_id, param_value;
int ret;
@@ -7389,7 +7402,7 @@ static void ath12k_mac_update_vif_offloa
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
- else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
+ else if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags))
arvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
else
arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
@@ -7405,7 +7418,7 @@ static void ath12k_mac_update_vif_offloa
param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
param_value = ATH12K_HW_TXRX_ETHERNET;
- else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
+ else if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags))
param_value = ATH12K_HW_TXRX_RAW;
else
param_value = ATH12K_HW_TXRX_NATIVE_WIFI;
@@ -7707,6 +7720,7 @@ static void ath12k_mac_vif_cache_flush(s
{
struct ath12k_hw *ah = ar->ah;
struct ath12k_vif *arvif = (void *)vif->drv_priv;
+ struct ath12k_key_conf *key_conf, *tmp;
int ret;
lockdep_assert_held(&ah->conf_mutex);
@@ -7717,23 +7731,30 @@ static void ath12k_mac_vif_cache_flush(s
if (ret)
ath12k_warn(ar->ab,
"unable to apply tx config parameters to vdev %d\n", ret);
+
+ memset(&arvif->cache.tx_conf, 0, sizeof(struct ath12k_tx_conf));
}
if (arvif->cache.bss_conf_changed) {
ath12k_mac_bss_info_changed(ar, vif, &vif->bss_conf,
arvif->cache.bss_conf_changed);
+
+ arvif->cache.bss_conf_changed = 0;
}
- if (arvif->cache.key_conf.changed) {
- ret = ath12k_mac_set_key(ar, arvif->cache.key_conf.cmd,
- vif, arvif->cache.key_conf.sta,
- arvif->cache.key_conf.key);
- if (ret)
- ath12k_warn(ar->ab, "unable to apply set key param to vdev %d ret %d\n",
- arvif->vdev_id, ret);
+ if (!list_empty(&arvif->cache.key_conf.list)) {
+ list_for_each_entry_safe(key_conf, tmp, &arvif->cache.key_conf.list, list) {
+ ret = ath12k_mac_set_key(ar, key_conf->cmd,
+ vif, key_conf->sta,
+ key_conf->key);
+ if (ret)
+ ath12k_warn(ar->ab, "unable to apply set key param to vdev %d ret %d\n",
+ arvif->vdev_id, ret);
+
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ }
}
-
- memset(&arvif->cache, 0, sizeof(struct ath12k_vif_cache));
}
static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
@@ -7819,6 +7840,8 @@ static int ath12k_mac_op_add_interface(s
INIT_LIST_HEAD(&arvif->list);
arvif->key_cipher = INVALID_CIPHER;
+ INIT_LIST_HEAD(&arvif->cache.key_conf.list);
+
INIT_WORK(&arvif->update_obss_color_notify_work, ath12k_update_obss_color_notify_work);
INIT_WORK(&arvif->update_bcn_template_work, ath12k_update_bcn_template_work);
@@ -7876,6 +7899,7 @@ static void ath12k_mac_op_remove_interfa
struct ath12k_hw *ah = hw->priv;
struct ath12k *ar;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_key_conf *key_conf;
struct ath12k_base *ab;
int ret;
@@ -7946,7 +7970,13 @@ err_vdev_del:
clear_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags);
ath12k_debugfs_remove_interface(arvif);
-
+
+ if (!list_empty(&arvif->cache.key_conf.list)) {
+ list_for_each_entry(key_conf, &arvif->cache.key_conf.list, list) {
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ }
+ }
/* TODO: recal traffic pause state based on the available vdevs */
mutex_unlock(&ar->conf_mutex);
@@ -11189,6 +11219,7 @@ static int ath12k_mac_hw_register(struct
struct ath12k_pdev_cap *cap;
struct ath12k_base *ab, *ab_dflt;
struct ath12k *ar;
+ struct ath12k_hw_group *ag;
struct ath12k_pdev *pdev;
int i, j, ret;
u32 antennas_rx, antennas_tx;
@@ -11212,6 +11243,7 @@ static int ath12k_mac_hw_register(struct
ar = ah->radio;
ab = ar->ab;
+ ag = ab->ag;
/* Use the first chip in group to advertise some features/info
* these are expected to be similar for chips in group
@@ -11338,7 +11370,7 @@ static int ath12k_mac_hw_register(struct
ah->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
ah->hw->wiphy->reg_notifier = ath12k_reg_notifier;
- if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab_dflt->dev_flags)) {
+ if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) {
hw->netdev_features = NETIF_F_HW_CSUM;
ieee80211_hw_set(hw, SW_CRYPTO_CONTROL);
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
@@ -11557,6 +11589,7 @@ int ath12k_mac_allocate(struct ath12k_hw
ah->ops = ops;
ah->num_radio = num_radios;
ag->ah[i] = ah;
+ ah->ag = ag;
ath12k_info(NULL,
"ath12k hw device created with %d radios in group %d with %d chips\n",
Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c
===================================================================
--- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c
+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c
@@ -150,6 +150,8 @@ static const struct wmi_tlv_policy wmi_t
static void ath12k_init_wmi_config_qcn92xx(struct ath12k_base *ab,
struct target_resource_config *config)
{
+ struct ath12k_hw_group *ag = ab->ag;
+
config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS;
if (ab->num_radios == 2) {
@@ -174,7 +176,7 @@ static void ath12k_init_wmi_config_qcn92
config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
- if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
+ if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags))
config->rx_decap_mode = TARGET_DECAP_MODE_RAW;
else
config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
@@ -1863,6 +1865,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc
struct peer_assoc_params *param)
{
struct ath12k_pdev_wmi *wmi = ar->wmi;
+ struct ath12k_hw_group *ag = ar->ab->ag;
struct wmi_peer_assoc_complete_cmd *cmd;
struct wmi_vht_rate_set *mcs;
struct wmi_he_rate_set *he_mcs;
@@ -1906,7 +1909,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc
ath12k_wmi_copy_peer_flags(cmd, param,
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED,
- &ar->ab->dev_flags));
+ &ag->dev_flags));
ether_addr_copy(cmd->peer_macaddr.addr, param->peer_mac);