From: Harsh Kumar Bijlani Refactor the structures and APIs defined in files peer.h and peer.c in such a way that the APIs making use of ath12k_peer are moved to newly introduced files dp_peer.h and dp_peer.c. Have this new file dp_peer.c compiled as part of kernel module ath12k.ko. Move these APIs from peer.h and peer.c to dp_peer.h and dp_peer.c: ath12k_peer_find() ath12k_peer_find_by_pdev_idx() ath12k_peer_find_by_addr() ath12k_peer_find_by_ml_id() ath12k_peer_find_by_id() ath12k_peer_exist_by_vdev_id() ath12k_peer_find_by_ast() ath12k_peer_unmap_event() ath12k_peer_map_event() ath12k_peer_get_link_sta() Background: In current ath12k architecture, connected station is represented by struct ath12k_sta. struct ath12k_sta has an array of struct ath12k_link_sta wherein each index represents one link of the connected station. For each ath12k_link_sta, there is a corresponding data path peer which is represented by struct ath12k_peer. Diagrammatic view of the station is as below: ath12k_sta | |-> ath12k_link_sta <--> ath12k_peer | |-> ath12k_link_sta <--> ath12k_peer | |-> ath12k_link_sta <--> ath12k_peer Currently, in control path, ath12k_link_sta and ath12k_peer are used interchangeably, while the data path makes use of ath12k_peer only. For ath12k next-generation driver framework, in order to have a clean segregation between control and data path, use ath12k_link_sta only for control path operations. Station view for the data path is revamped as below: ath12k_dp_peer | |-> ath12k_dp_link_peer | |-> ath12k_dp_link_peer | |-> ath12k_dp_link_peer Introduce the structure ath12k_dp_peer to represent the data path version of corresponding ath12k_sta. This ath12k_dp_peer contains the fields used in the per packet Tx Rx paths applicable across all the links and maintains an array of ath12k_dp_link_peer. Per packet Tx and Rx path operates on ath12k_dp_peer. This ath12k_dp_peer is a standalone new object and has back pointer reference to ieee80211_sta. Rename ath12k_peer to ath12k_dp_link_peer and move the fields which are common across all the links to ath12k_dp_peer. Add the fields specific to a link which are mostly for statistics and monitor usage to ath12k_dp_link_peer. Final view of station in ath12k next-generation driver is shown as below: Control Path Data Path ------------------------------------------------------------------- ath12k_sta ath12k_dp_peer | | |-> ath12k_link_sta <----> |-> ath12k_dp_link_peer | | |-> ath12k_link_sta <----> |-> ath12k_dp_link_peer | | |-> ath12k_link_sta <----> |-> ath12k_dp_link_peer This patch and the subsequent patches in this series are meant to achieve the modularization of peer object as mentioned above. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/Makefile | 1 + drivers/net/wireless/ath/ath12k/dp_peer.c | 207 ++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/dp_peer.h | 82 +++++++++ drivers/net/wireless/ath/ath12k/peer.c | 172 ------------------ drivers/net/wireless/ath/ath12k/peer.h | 97 +--------- 5 files changed, 292 insertions(+), 267 deletions(-) create mode 100644 drivers/net/wireless/ath/ath12k/dp_peer.c create mode 100644 drivers/net/wireless/ath/ath12k/dp_peer.h diff --git a/drivers/net/wireless/ath/ath12k/Makefile b/drivers/net/wireless/ath/ath12k/Makefile index 32a0f30faf92..d397bc494cf2 100644 --- a/drivers/net/wireless/ath/ath12k/Makefile +++ b/drivers/net/wireless/ath/ath12k/Makefile @@ -11,6 +11,7 @@ ath12k-y += core.o \ dp_tx.o \ dp_rx.o \ dp_htt.o \ + dp_peer.o \ debug.o \ ce.o \ peer.o \ diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c new file mode 100644 index 000000000000..e32d3ea76a6f --- /dev/null +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +/* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "core.h" +#include "dp_peer.h" +#include "debug.h" + +struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, + const u8 *addr) +{ + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) { + if (peer->vdev_id != vdev_id) + continue; + if (!ether_addr_equal(peer->addr, addr)) + continue; + + return peer; + } + + return NULL; +} + +struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab, + u8 pdev_idx, const u8 *addr) +{ + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) { + if (peer->pdev_idx != pdev_idx) + continue; + if (!ether_addr_equal(peer->addr, addr)) + continue; + + return peer; + } + + return NULL; +} + +struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, + const u8 *addr) +{ + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) { + if (!ether_addr_equal(peer->addr, addr)) + continue; + + return peer; + } + + return NULL; +} +EXPORT_SYMBOL(ath12k_peer_find_by_addr); + +static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab, + int ml_peer_id) +{ + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) + if (ml_peer_id == peer->ml_id) + return peer; + + return NULL; +} + +struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, + int peer_id) +{ + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + if (peer_id == HAL_INVALID_PEERID) + return NULL; + + if (peer_id & ATH12K_PEER_ML_ID_VALID) + return ath12k_peer_find_by_ml_id(ab, peer_id); + + list_for_each_entry(peer, &ab->peers, list) + if (peer_id == peer->peer_id) + return peer; + + return NULL; +} + +bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id) +{ + struct ath12k_peer *peer; + + spin_lock_bh(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) { + if (vdev_id == peer->vdev_id) { + spin_unlock_bh(&ab->base_lock); + return true; + } + } + spin_unlock_bh(&ab->base_lock); + return false; +} + +struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, + int ast_hash) +{ + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) + if (ast_hash == peer->ast_hash) + return peer; + + return NULL; +} + +void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) +{ + struct ath12k_peer *peer; + + spin_lock_bh(&ab->base_lock); + + peer = ath12k_peer_find_by_id(ab, peer_id); + if (!peer) { + ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n", + peer_id); + goto exit; + } + + ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", + peer->vdev_id, peer->addr, peer_id); + + list_del(&peer->list); + kfree(peer); + wake_up(&ab->peer_mapping_wq); + +exit: + spin_unlock_bh(&ab->base_lock); +} + +void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) +{ + struct ath12k_peer *peer; + + spin_lock_bh(&ab->base_lock); + peer = ath12k_peer_find(ab, vdev_id, mac_addr); + if (!peer) { + peer = kzalloc(sizeof(*peer), GFP_ATOMIC); + if (!peer) + goto exit; + + peer->vdev_id = vdev_id; + peer->peer_id = peer_id; + peer->ast_hash = ast_hash; + peer->hw_peer_id = hw_peer_id; + ether_addr_copy(peer->addr, mac_addr); + list_add(&peer->list, &ab->peers); + wake_up(&ab->peer_mapping_wq); + } + + ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", + vdev_id, mac_addr, peer_id); + +exit: + spin_unlock_bh(&ab->base_lock); +} + +struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, + struct ath12k_peer *peer) +{ + struct ath12k_sta *ahsta; + struct ath12k_link_sta *arsta; + + if (!peer->sta) + return NULL; + + ahsta = ath12k_sta_to_ahsta(peer->sta); + if (peer->ml_id & ATH12K_PEER_ML_ID_VALID) { + if (!(ahsta->links_map & BIT(peer->link_id))) { + ath12k_warn(ab, "peer %pM id %d link_id %d can't found in STA link_map 0x%x\n", + peer->addr, peer->peer_id, peer->link_id, + ahsta->links_map); + return NULL; + } + arsta = rcu_dereference(ahsta->link[peer->link_id]); + if (!arsta) + return NULL; + } else { + arsta = &ahsta->deflink; + } + return arsta; +} diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h new file mode 100644 index 000000000000..19f01d69e5d3 --- /dev/null +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef ATH12K_DP_PEER_H +#define ATH12K_DP_PEER_H + +#include "dp_rx.h" + +struct ppdu_user_delayba { + u16 sw_peer_id; + u32 info0; + u16 ru_end; + u16 ru_start; + u32 info1; + u32 rate_flags; + u32 resp_rate_flags; +}; + +#define ATH12K_PEER_ML_ID_VALID BIT(13) + +struct ath12k_peer { + struct list_head list; + struct ieee80211_sta *sta; + int vdev_id; + u8 addr[ETH_ALEN]; + int peer_id; + u16 ast_hash; + u8 pdev_idx; + u16 hw_peer_id; + + /* protected by ab->data_lock */ + struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; + struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; + + /* Info used in MMIC verification of + * RX fragments + */ + struct crypto_shash *tfm_mmic; + u8 mcast_keyidx; + u8 ucast_keyidx; + u16 sec_type; + u16 sec_type_grp; + struct ppdu_user_delayba ppdu_stats_delayba; + bool delayba_flag; + bool is_authorized; + bool mlo; + /* protected by ab->data_lock */ + bool dp_setup_done; + + u16 ml_id; + + /* any other ML info common for all partners can be added + * here and would be same for all partner peers. + */ + u8 ml_addr[ETH_ALEN]; + + /* To ensure only certain work related to dp is done once */ + bool primary_link; + + /* for reference to ath12k_link_sta */ + u8 link_id; + bool ucast_ra_only; +}; + +void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); +void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); +struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, + const u8 *addr); +struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, + const u8 *addr); +struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); +bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id); +struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); +struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab, + u8 pdev_idx, const u8 *addr); +struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, + struct ath12k_peer *peer); +#endif diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index ce1564298656..1e2526bb1186 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -25,178 +25,6 @@ struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr) } EXPORT_SYMBOL(ath12k_peer_ml_find); -struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, - const u8 *addr) -{ - struct ath12k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) { - if (peer->vdev_id != vdev_id) - continue; - if (!ether_addr_equal(peer->addr, addr)) - continue; - - return peer; - } - - return NULL; -} - -static struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab, - u8 pdev_idx, const u8 *addr) -{ - struct ath12k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) { - if (peer->pdev_idx != pdev_idx) - continue; - if (!ether_addr_equal(peer->addr, addr)) - continue; - - return peer; - } - - return NULL; -} - -struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, - const u8 *addr) -{ - struct ath12k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) { - if (!ether_addr_equal(peer->addr, addr)) - continue; - - return peer; - } - - return NULL; -} -EXPORT_SYMBOL(ath12k_peer_find_by_addr); - -static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab, - int ml_peer_id) -{ - struct ath12k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) - if (ml_peer_id == peer->ml_id) - return peer; - - return NULL; -} - -struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, - int peer_id) -{ - struct ath12k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - if (peer_id == HAL_INVALID_PEERID) - return NULL; - - if (peer_id & ATH12K_PEER_ML_ID_VALID) - return ath12k_peer_find_by_ml_id(ab, peer_id); - - list_for_each_entry(peer, &ab->peers, list) - if (peer_id == peer->peer_id) - return peer; - - return NULL; -} - -bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id) -{ - struct ath12k_peer *peer; - - spin_lock_bh(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) { - if (vdev_id == peer->vdev_id) { - spin_unlock_bh(&ab->base_lock); - return true; - } - } - spin_unlock_bh(&ab->base_lock); - return false; -} - -struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, - int ast_hash) -{ - struct ath12k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) - if (ast_hash == peer->ast_hash) - return peer; - - return NULL; -} - -void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) -{ - struct ath12k_peer *peer; - - spin_lock_bh(&ab->base_lock); - - peer = ath12k_peer_find_by_id(ab, peer_id); - if (!peer) { - ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n", - peer_id); - goto exit; - } - - ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", - peer->vdev_id, peer->addr, peer_id); - - list_del(&peer->list); - kfree(peer); - wake_up(&ab->peer_mapping_wq); - -exit: - spin_unlock_bh(&ab->base_lock); -} - -void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) -{ - struct ath12k_peer *peer; - - spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, mac_addr); - if (!peer) { - peer = kzalloc(sizeof(*peer), GFP_ATOMIC); - if (!peer) - goto exit; - - peer->vdev_id = vdev_id; - peer->peer_id = peer_id; - peer->ast_hash = ast_hash; - peer->hw_peer_id = hw_peer_id; - ether_addr_copy(peer->addr, mac_addr); - list_add(&peer->list, &ab->peers); - wake_up(&ab->peer_mapping_wq); - } - - ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", - vdev_id, mac_addr, peer_id); - -exit: - spin_unlock_bh(&ab->base_lock); -} - static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id, const u8 *addr, bool expect_mapped) { diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h index 44afc0b7dd53..81e9bcc067ff 100644 --- a/drivers/net/wireless/ath/ath12k/peer.h +++ b/drivers/net/wireless/ath/ath12k/peer.h @@ -1,69 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2021 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. */ #ifndef ATH12K_PEER_H #define ATH12K_PEER_H -#include "dp_rx.h" - -struct ppdu_user_delayba { - u16 sw_peer_id; - u32 info0; - u16 ru_end; - u16 ru_start; - u32 info1; - u32 rate_flags; - u32 resp_rate_flags; -}; - -#define ATH12K_PEER_ML_ID_VALID BIT(13) - -struct ath12k_peer { - struct list_head list; - struct ieee80211_sta *sta; - int vdev_id; - u8 addr[ETH_ALEN]; - int peer_id; - u16 ast_hash; - u8 pdev_idx; - u16 hw_peer_id; - - /* protected by ab->data_lock */ - struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; - struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; - - /* Info used in MMIC verification of - * RX fragments - */ - struct crypto_shash *tfm_mmic; - u8 mcast_keyidx; - u8 ucast_keyidx; - u16 sec_type; - u16 sec_type_grp; - struct ppdu_user_delayba ppdu_stats_delayba; - bool delayba_flag; - bool is_authorized; - bool mlo; - /* protected by ab->data_lock */ - bool dp_setup_done; - - u16 ml_id; - - /* any other ML info common for all partners can be added - * here and would be same for all partner peers. - */ - u8 ml_addr[ETH_ALEN]; - - /* To ensure only certain work related to dp is done once */ - bool primary_link; - - /* for reference to ath12k_link_sta */ - u8 link_id; - bool ucast_ra_only; -}; +#include "dp_peer.h" struct ath12k_ml_peer { struct list_head list; @@ -71,14 +15,6 @@ struct ath12k_ml_peer { u16 id; }; -void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); -void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); -struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, - const u8 *addr); -struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, - const u8 *addr); -struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id); int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr); int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, @@ -86,38 +22,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ath12k_wmi_peer_create_arg *arg); int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, const u8 *addr); -bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id); -struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta); int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta); int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr); -static inline -struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, - struct ath12k_peer *peer) -{ - struct ath12k_sta *ahsta; - struct ath12k_link_sta *arsta; - - if (!peer->sta) - return NULL; - - ahsta = ath12k_sta_to_ahsta(peer->sta); - if (peer->ml_id & ATH12K_PEER_ML_ID_VALID) { - if (!(ahsta->links_map & BIT(peer->link_id))) { - ath12k_warn(ab, "peer %pM id %d link_id %d can't found in STA link_map 0x%x\n", - peer->addr, peer->peer_id, peer->link_id, - ahsta->links_map); - return NULL; - } - arsta = rcu_dereference(ahsta->link[peer->link_id]); - if (!arsta) - return NULL; - } else { - arsta = &ahsta->deflink; - } - return arsta; -} - #endif /* _PEER_H_ */ -- 2.34.1 From: Harsh Kumar Bijlani Rename ath12k_peer to ath12k_dp_link_peer for all instances and rename the following find APIs accordingly to reflect the API names as per the structural name change. APIs renamed: ath12k_peer_find() ath12k_peer_find_by_pdev_idx() ath12k_peer_find_by_addr() ath12k_peer_find_by_ml_id() ath12k_peer_find_by_id() ath12k_peer_find_by_ast() ath12k_peer_exist_by_vdev_id() ath12k_peer_get_link_sta() Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/dp.c | 8 +-- drivers/net/wireless/ath/ath12k/dp.h | 2 +- drivers/net/wireless/ath/ath12k/dp_htt.c | 28 ++++---- drivers/net/wireless/ath/ath12k/dp_mon.c | 16 ++--- drivers/net/wireless/ath/ath12k/dp_peer.c | 64 ++++++++++--------- drivers/net/wireless/ath/ath12k/dp_peer.h | 34 +++++----- drivers/net/wireless/ath/ath12k/dp_rx.c | 35 +++++----- drivers/net/wireless/ath/ath12k/dp_rx.h | 10 +-- drivers/net/wireless/ath/ath12k/mac.c | 48 ++++++++------ drivers/net/wireless/ath/ath12k/peer.c | 22 ++++--- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 18 +++--- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 4 +- drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c | 12 ++-- drivers/net/wireless/ath/ath12k/wifi7/hw.c | 2 +- drivers/net/wireless/ath/ath12k/wmi.c | 4 +- 15 files changed, 163 insertions(+), 144 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index 98a1c879605a..945e4965a437 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -23,12 +23,12 @@ enum ath12k_dp_desc_type { void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr) { struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; /* TODO: Any other peer specific DP cleanup */ spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, addr); if (!peer) { ath12k_warn(ab, "failed to lookup peer %pM on vdev %d\n", addr, vdev_id); @@ -50,7 +50,7 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr) int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) { struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; u32 reo_dest; int ret = 0, tid; @@ -89,7 +89,7 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) peer_clean: spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, addr); if (!peer) { ath12k_warn(ab, "failed to find the peer to del rx tid\n"); spin_unlock_bh(&ab->base_lock); diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index 8e7e4a7b582b..5cedc6603e74 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -14,7 +14,7 @@ #define MAX_RXDMA_PER_PDEV 2 struct ath12k_base; -struct ath12k_peer; +struct ath12k_dp_link_peer; struct ath12k_dp; struct ath12k_vif; struct ath12k_link_vif; diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c index 1a0d3e4ac8bb..cae5a90c1c65 100644 --- a/drivers/net/wireless/ath/ath12k/dp_htt.c +++ b/drivers/net/wireless/ath/ath12k/dp_htt.c @@ -188,7 +188,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, { struct ath12k_dp *dp = dp_pdev->dp; struct ath12k_base *ab = dp->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_link_sta *arsta; struct htt_ppdu_stats_user_rate *user_rate; struct ath12k_per_peer_tx_stats *peer_stats = &dp_pdev->peer_tx_stats; @@ -273,7 +273,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, rcu_read_lock(); spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, usr_stats->peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, usr_stats->peer_id); if (!peer || !peer->sta) { spin_unlock_bh(&ab->base_lock); @@ -281,7 +281,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, return; } - arsta = ath12k_peer_get_link_sta(ab, peer); + arsta = ath12k_dp_link_peer_to_link_sta(ab, peer); if (!arsta) { spin_unlock_bh(&ab->base_lock); rcu_read_unlock(); @@ -403,7 +403,7 @@ struct htt_ppdu_stats_info *ath12k_dp_htt_get_ppdu_desc(struct ath12k_pdev_dp *d return ppdu_info; } -static void ath12k_copy_to_delay_stats(struct ath12k_peer *peer, +static void ath12k_copy_to_delay_stats(struct ath12k_dp_link_peer *peer, struct htt_ppdu_user_stats *usr_stats) { peer->ppdu_stats_delayba.sw_peer_id = le16_to_cpu(usr_stats->rate.sw_peer_id); @@ -418,7 +418,7 @@ static void ath12k_copy_to_delay_stats(struct ath12k_peer *peer, peer->delayba_flag = true; } -static void ath12k_copy_to_bar(struct ath12k_peer *peer, +static void ath12k_copy_to_bar(struct ath12k_dp_link_peer *peer, struct htt_ppdu_user_stats *usr_stats) { usr_stats->rate.sw_peer_id = cpu_to_le16(peer->ppdu_stats_delayba.sw_peer_id); @@ -439,7 +439,7 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, struct ath12k_dp *dp = ath12k_ab_to_dp(ab); struct ath12k_htt_ppdu_stats_msg *msg; struct htt_ppdu_stats_info *ppdu_info; - struct ath12k_peer *peer = NULL; + struct ath12k_dp_link_peer *peer = NULL; struct htt_ppdu_user_stats *usr_stats = NULL; u32 peer_id = 0; struct ath12k_pdev_dp *dp_pdev; @@ -508,7 +508,7 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) { peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id; spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); if (!peer) { spin_unlock_bh(&ab->base_lock); continue; @@ -527,7 +527,7 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, for (i = 0; i < ppdu_info->bar_num_users; i++) { peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id; spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); if (!peer) { spin_unlock_bh(&ab->base_lock); continue; @@ -623,7 +623,7 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16); ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32), peer_mac_h16, mac_addr); - ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0); + ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0); break; case HTT_T2H_MSG_TYPE_PEER_MAP2: vdev_id = le32_get_bits(resp->peer_map_ev.info, @@ -638,8 +638,8 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL); hw_peer_id = le32_get_bits(resp->peer_map_ev.info1, HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID); - ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, - hw_peer_id); + ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, + hw_peer_id); break; case HTT_T2H_MSG_TYPE_PEER_MAP3: vdev_id = le32_get_bits(resp->peer_map_ev.info, @@ -654,14 +654,14 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL); hw_peer_id = le32_get_bits(resp->peer_map_ev.info2, HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID); - ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, - hw_peer_id); + ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, + hw_peer_id); break; case HTT_T2H_MSG_TYPE_PEER_UNMAP: case HTT_T2H_MSG_TYPE_PEER_UNMAP2: peer_id = le32_get_bits(resp->peer_unmap_ev.info, HTT_T2H_PEER_UNMAP_INFO_PEER_ID); - ath12k_peer_unmap_event(ab, peer_id); + ath12k_dp_link_peer_unmap_event(ab, peer_id); break; case HTT_T2H_MSG_TYPE_PPDU_STATS_IND: ath12k_htt_pull_ppdu_stats(ab, skb); diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c index aa45550301ed..9da9fc403315 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c @@ -2269,7 +2269,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct ieee80211_rx_status *rx_status; struct ieee80211_radiotap_he *he = NULL; struct ieee80211_sta *pubsta = NULL; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); struct hal_rx_desc_data rx_info; bool is_mcbc = rxcb->is_mcbc; @@ -2289,7 +2289,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, spin_lock_bh(&ab->base_lock); rx_info.addr2_present = false; - peer = ath12k_dp_rx_h_find_peer(ab, msdu, &rx_info); + peer = ath12k_dp_rx_h_find_link_peer(ab, msdu, &rx_info); if (peer && peer->sta) { pubsta = peer->sta; if (pubsta->valid_links) { @@ -3637,13 +3637,13 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab, struct ath12k_link_sta *arsta; struct ath12k_rx_peer_stats *rx_stats = NULL; struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid]; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; u32 num_msdu; if (user_stats->ast_index == 0 || user_stats->ast_index == 0xFFFF) return; - peer = ath12k_peer_find_by_ast(ab, user_stats->ast_index); + peer = ath12k_dp_link_peer_find_by_ast(ab, user_stats->ast_index); if (!peer) { ath12k_warn(ab, "peer ast idx %d can't be found\n", @@ -3651,7 +3651,7 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab, return; } - arsta = ath12k_peer_get_link_sta(ab, peer); + arsta = ath12k_dp_link_peer_to_link_sta(ab, peer); if (!arsta) { ath12k_warn(ab, "link sta not found on peer %pM id %d\n", peer->addr, peer->peer_id); @@ -3770,7 +3770,7 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, struct hal_srng *srng; struct dp_rxdma_mon_ring *buf_ring; struct ath12k_link_sta *arsta; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct sk_buff_head skb_list; u64 cookie; int num_buffs_reaped = 0, srng_id, buf_id; @@ -3885,7 +3885,7 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, rcu_read_lock(); spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, ppdu_info->peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, ppdu_info->peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DATA, "failed to find the peer with monitor peer_id %d\n", @@ -3894,7 +3894,7 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, } if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { - arsta = ath12k_peer_get_link_sta(ab, peer); + arsta = ath12k_dp_link_peer_to_link_sta(ab, peer); if (!arsta) { ath12k_warn(ab, "link sta not found on peer %pM id %d\n", peer->addr, peer->peer_id); diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index e32d3ea76a6f..843369a00d3e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -8,10 +8,11 @@ #include "dp_peer.h" #include "debug.h" -struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, - const u8 *addr) +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_base *ab, + int vdev_id, const u8 *addr) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_held(&ab->base_lock); @@ -27,10 +28,11 @@ struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, return NULL; } -struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab, - u8 pdev_idx, const u8 *addr) +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_base *ab, u8 pdev_idx, + const u8 *addr) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_held(&ab->base_lock); @@ -46,10 +48,10 @@ struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab, return NULL; } -struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, - const u8 *addr) +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_addr(struct ath12k_base *ab, const u8 *addr) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_held(&ab->base_lock); @@ -62,12 +64,12 @@ struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, return NULL; } -EXPORT_SYMBOL(ath12k_peer_find_by_addr); +EXPORT_SYMBOL(ath12k_dp_link_peer_find_by_addr); -static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab, - int ml_peer_id) +static struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_ml_id(struct ath12k_base *ab, int ml_peer_id) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_held(&ab->base_lock); @@ -78,10 +80,10 @@ static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab, return NULL; } -struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, - int peer_id) +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_id(struct ath12k_base *ab, int peer_id) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_held(&ab->base_lock); @@ -89,7 +91,7 @@ struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, return NULL; if (peer_id & ATH12K_PEER_ML_ID_VALID) - return ath12k_peer_find_by_ml_id(ab, peer_id); + return ath12k_dp_link_peer_find_by_ml_id(ab, peer_id); list_for_each_entry(peer, &ab->peers, list) if (peer_id == peer->peer_id) @@ -98,9 +100,9 @@ struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, return NULL; } -bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id) +bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; spin_lock_bh(&ab->base_lock); @@ -114,10 +116,10 @@ bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id) return false; } -struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, - int ast_hash) +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_ast(struct ath12k_base *ab, int ast_hash) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_held(&ab->base_lock); @@ -128,13 +130,13 @@ struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, return NULL; } -void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) +void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); if (!peer) { ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n", peer_id); @@ -152,13 +154,13 @@ void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) spin_unlock_bh(&ab->base_lock); } -void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) +void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, mac_addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, mac_addr); if (!peer) { peer = kzalloc(sizeof(*peer), GFP_ATOMIC); if (!peer) @@ -180,8 +182,8 @@ void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, spin_unlock_bh(&ab->base_lock); } -struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, - struct ath12k_peer *peer) +struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, + struct ath12k_dp_link_peer *peer) { struct ath12k_sta *ahsta; struct ath12k_link_sta *arsta; diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index 19f01d69e5d3..aec73d8e35ce 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -21,7 +21,7 @@ struct ppdu_user_delayba { #define ATH12K_PEER_ML_ID_VALID BIT(13) -struct ath12k_peer { +struct ath12k_dp_link_peer { struct list_head list; struct ieee80211_sta *sta; int vdev_id; @@ -65,18 +65,22 @@ struct ath12k_peer { bool ucast_ra_only; }; -void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); -void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); -struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, - const u8 *addr); -struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, - const u8 *addr); -struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); -bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id); -struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); -struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab, - u8 pdev_idx, const u8 *addr); -struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, - struct ath12k_peer *peer); +void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); +void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_base *ab, + int vdev_id, const u8 *addr); +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_addr(struct ath12k_base *ab, const u8 *addr); +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_id(struct ath12k_base *ab, int peer_id); +bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id); +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_base *ab, u8 pdev_idx, + const u8 *addr); +struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, + struct ath12k_dp_link_peer *peer); #endif diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 8e342ad4d678..f6d800c1ebf9 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -471,7 +471,7 @@ void ath12k_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid, __skb_queue_purge(&rx_tid->rx_frags); } -void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_peer *peer) +void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer *peer) { struct ath12k_dp_rx_tid *rx_tid; int i; @@ -496,7 +496,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ { struct ath12k_base *ab = ar->ab; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_sta *ahsta; struct ath12k_dp_rx_tid *rx_tid; dma_addr_t paddr_aligned; @@ -504,7 +504,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, peer_mac); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, peer_mac); if (!peer) { spin_unlock_bh(&ab->base_lock); ath12k_warn(ab, "failed to find the peer to set up rx tid\n"); @@ -626,7 +626,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, u8 link_id) { struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta); struct ath12k_link_sta *arsta; int vdev_id; @@ -644,7 +644,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, arsta->addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, arsta->addr); if (!peer) { spin_unlock_bh(&ab->base_lock); ath12k_warn(ab, "failed to find the peer to stop rx aggregation\n"); @@ -677,7 +677,7 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; struct ath12k_hal_reo_cmd cmd = {}; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_dp_rx_tid *rx_tid; u8 tid; int ret = 0; @@ -691,7 +691,8 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, + peer_addr); if (!peer) { spin_unlock_bh(&ab->base_lock); ath12k_warn(ab, "failed to find the peer %pM to configure pn replay detection\n", @@ -1036,23 +1037,23 @@ void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu } } -struct ath12k_peer * -ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu, - struct hal_rx_desc_data *rx_info) +struct ath12k_dp_link_peer * +ath12k_dp_rx_h_find_link_peer(struct ath12k_base *ab, struct sk_buff *msdu, + struct hal_rx_desc_data *rx_info) { struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); - struct ath12k_peer *peer = NULL; + struct ath12k_dp_link_peer *peer = NULL; lockdep_assert_held(&ab->base_lock); if (rxcb->peer_id) - peer = ath12k_peer_find_by_id(ab, rxcb->peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, rxcb->peer_id); if (peer) return peer; if (rx_info->addr2_present) - peer = ath12k_peer_find_by_addr(ab, rx_info->addr2); + peer = ath12k_dp_link_peer_find_by_addr(ab, rx_info->addr2); return peer; } @@ -1195,7 +1196,7 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc struct ath12k_base *ab = dp->ab; struct ieee80211_rx_status *rx_status; struct ieee80211_sta *pubsta; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); struct ieee80211_rx_status *status = rx_info->rx_status; u8 decap = rx_info->decap_type; @@ -1203,7 +1204,7 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc bool is_eapol = rxcb->is_eapol; spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info); + peer = ath12k_dp_rx_h_find_link_peer(ab, msdu, rx_info); pubsta = peer ? peer->sta : NULL; @@ -1324,7 +1325,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev { struct ath12k_base *ab = ar->ab; struct crypto_shash *tfm; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_dp_rx_tid *rx_tid; int i; @@ -1334,7 +1335,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, peer_mac); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, peer_mac); if (!peer) { spin_unlock_bh(&ab->base_lock); crypto_free_shash(tfm); diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h index 27062109a3f3..b45097855620 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/dp_rx.h @@ -206,9 +206,9 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, const u8 *peer_addr, enum set_key_cmd key_cmd, struct ieee80211_key_conf *key); -void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_peer *peer); +void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer *peer); void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar, - struct ath12k_peer *peer, u8 tid); + struct ath12k_dp_link_peer *peer, u8 tid); int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, u8 tid, u32 ba_win_sz, u16 ssn, enum hal_pn_type pn_type); @@ -229,9 +229,9 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab, struct hal_rx_desc *desc); -struct ath12k_peer * -ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu, - struct hal_rx_desc_data *rx_info); +struct ath12k_dp_link_peer * +ath12k_dp_rx_h_find_link_peer(struct ath12k_base *ab, struct sk_buff *msdu, + struct hal_rx_desc_data *rx_info); u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab, struct hal_rx_desc *desc); u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab, diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index ebe7aba92ecc..64609fffa7ce 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1147,7 +1147,7 @@ static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif) void ath12k_mac_peer_cleanup_all(struct ath12k *ar) { - struct ath12k_peer *peer, *tmp; + struct ath12k_dp_link_peer *peer, *tmp; struct ath12k_base *ab = ar->ab; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -3610,7 +3610,7 @@ static void ath12k_bss_assoc(struct ath12k *ar, struct ath12k_link_sta *arsta; struct ieee80211_sta *ap_sta; struct ath12k_sta *ahsta; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; bool is_auth = false; u32 hemode = 0; int ret; @@ -3727,7 +3727,8 @@ static void ath12k_bss_assoc(struct ath12k *ar, spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + arvif->bssid); if (peer && peer->is_authorized) is_auth = true; @@ -5436,7 +5437,7 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, { struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; int first_errno = 0; int ret; int i; @@ -5445,7 +5446,7 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, arvif->vdev_id, addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, addr); spin_unlock_bh(&ab->base_lock); if (!peer) @@ -5480,7 +5481,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, { struct ieee80211_sta *sta = NULL; struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_sta *ahsta; const u8 *peer_addr; int ret; @@ -5505,7 +5506,8 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, * we already hold wiphy lock. we just make sure its there now. */ spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, + peer_addr); spin_unlock_bh(&ab->base_lock); if (!peer) { @@ -5539,7 +5541,8 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, } spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, + peer_addr); if (peer && cmd == SET_KEY) { peer->keys[key->keyidx] = key; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { @@ -6246,7 +6249,7 @@ static void ath12k_mac_station_post_remove(struct ath12k *ar, { struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -6254,7 +6257,8 @@ static void ath12k_mac_station_post_remove(struct ath12k *ar, spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + arsta->addr); if (peer && peer->sta == sta) { ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", vif->addr, arvif->vdev_id); @@ -6274,14 +6278,15 @@ static int ath12k_mac_station_unauthorize(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ath12k_link_sta *arsta) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; int ret; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + arsta->addr); if (peer) peer->is_authorized = false; @@ -6307,7 +6312,7 @@ static int ath12k_mac_station_authorize(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ath12k_link_sta *arsta) { - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); int ret; @@ -6315,7 +6320,8 @@ static int ath12k_mac_station_authorize(struct ath12k *ar, spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + arsta->addr); if (peer) peer->is_authorized = true; @@ -7184,7 +7190,7 @@ void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw, struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k_link_sta *arsta; struct ath12k_link_vif *arvif; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; u32 bw, smps; rcu_read_lock(); @@ -7207,7 +7213,8 @@ void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw, } spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + arsta->addr); if (!peer) { spin_unlock_bh(&ar->ab->base_lock); rcu_read_unlock(); @@ -8835,7 +8842,7 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, struct sk_buff *msdu_copied; struct ath12k *ar, *tmp_ar; struct ath12k_pdev_dp *dp_pdev, *tmp_dp_pdev; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; unsigned long links_map; bool is_mcast = false; bool is_dvlan = false; @@ -8970,7 +8977,8 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, goto skip_peer_find; spin_lock_bh(&tmp_ar->ab->base_lock); - peer = ath12k_peer_find_by_addr(tmp_ar->ab, tmp_arvif->bssid); + peer = ath12k_dp_link_peer_find_by_addr(tmp_ar->ab, + tmp_arvif->bssid); if (!peer) { spin_unlock_bh(&tmp_ar->ab->base_lock); ath12k_warn(tmp_ar->ab, @@ -11571,7 +11579,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, if (ab->hw_params->vdev_start_delay && ahvif->vdev_type != WMI_VDEV_TYPE_AP && ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && - !ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) { + !ath12k_dp_link_peer_exist_by_vdev_id(ab, arvif->vdev_id)) { ret = 0; goto out; } @@ -12288,7 +12296,7 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban bool he_fixed_rate = false, vht_fixed_rate = false; const u16 *vht_mcs_mask, *he_mcs_mask; struct ieee80211_link_sta *link_sta; - struct ath12k_peer *peer, *tmp; + struct ath12k_dp_link_peer *peer, *tmp; u8 vht_nss, he_nss; int ret = true; diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 1e2526bb1186..16f4a74712d8 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -25,8 +25,8 @@ struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr) } EXPORT_SYMBOL(ath12k_peer_ml_find); -static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id, - const u8 *addr, bool expect_mapped) +static int ath12k_wait_for_dp_link_peer_common(struct ath12k_base *ab, int vdev_id, + const u8 *addr, bool expect_mapped) { int ret; @@ -34,7 +34,9 @@ static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id, bool mapped; spin_lock_bh(&ab->base_lock); - mapped = !!ath12k_peer_find(ab, vdev_id, addr); + mapped = !!ath12k_dp_link_peer_find_by_vdev_and_addr(ab, + vdev_id, + addr); spin_unlock_bh(&ab->base_lock); (mapped == expect_mapped || @@ -49,7 +51,7 @@ static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id, void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id) { - struct ath12k_peer *peer, *tmp; + struct ath12k_dp_link_peer *peer, *tmp; struct ath12k_base *ab = ar->ab; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -72,7 +74,7 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id) static int ath12k_wait_for_peer_deleted(struct ath12k *ar, int vdev_id, const u8 *addr) { - return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, false); + return ath12k_wait_for_dp_link_peer_common(ar->ab, vdev_id, addr, false); } int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, @@ -138,7 +140,7 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8 *addr) { - return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true); + return ath12k_wait_for_dp_link_peer_common(ar->ab, vdev_id, addr, true); } int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, @@ -150,7 +152,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ath12k_dp_link_vif *dp_link_vif; struct ath12k_link_sta *arsta; u8 link_id = arvif->link_id; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_sta *ahsta; u16 ml_peer_id; int ret; @@ -166,7 +168,8 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, } spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, arg->peer_addr); + peer = ath12k_dp_link_peer_find_by_pdev_and_addr(ar->ab, ar->pdev_idx, + arg->peer_addr); if (peer) { spin_unlock_bh(&ar->ab->base_lock); return -EINVAL; @@ -188,7 +191,8 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find(ar->ab, arg->vdev_id, arg->peer_addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arg->vdev_id, + arg->peer_addr); if (!peer) { spin_unlock_bh(&ar->ab->base_lock); ath12k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index eef8d2558494..4180db504c31 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -68,7 +68,7 @@ static void ath12k_wifi7_peer_rx_tid_qref_reset(struct ath12k_base *ab, } void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k *ar, - struct ath12k_peer *peer, u8 tid) + struct ath12k_dp_link_peer *peer, u8 tid) { struct ath12k_hal_reo_cmd cmd = {}; struct ath12k_dp_rx_tid *rx_tid = &peer->rx_tid[tid]; @@ -179,7 +179,7 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab, } int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k *ar, - struct ath12k_peer *peer, + struct ath12k_dp_link_peer *peer, struct ath12k_dp_rx_tid *rx_tid, u32 ba_win_sz, u16 ssn, bool update_ssn) @@ -321,7 +321,7 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, enum hal_encrypt_type enctype; bool is_decrypted = false; struct ieee80211_hdr *hdr; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ieee80211_rx_status *rx_status = rx_info->rx_status; u32 err_bitmap = rx_info->err_bitmap; @@ -333,7 +333,7 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, rxcb->peer_id = rx_info->peer_id; spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info); + peer = ath12k_dp_rx_h_find_link_peer(ab, msdu, rx_info); if (peer) { /* resetting mcbc bit because mcbc packets are unicast * packets only for AP as STA sends unicast packets. @@ -964,7 +964,7 @@ static int ath12k_wifi7_dp_rx_h_defrag_reo_reinject(struct ath12k_dp *dp, } static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev, - struct ath12k_peer *peer, + struct ath12k_dp_link_peer *peer, enum hal_encrypt_type enctype, struct sk_buff *msdu, struct hal_rx_desc_data *rx_info) @@ -1033,7 +1033,7 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev, } static int ath12k_wifi7_dp_rx_h_defrag(struct ath12k_pdev_dp *dp_pdev, - struct ath12k_peer *peer, + struct ath12k_dp_link_peer *peer, struct ath12k_dp_rx_tid *rx_tid, struct sk_buff **defrag_skb, enum hal_encrypt_type enctype, @@ -1107,7 +1107,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, { struct ath12k_dp *dp = dp_pdev->dp; struct ath12k_base *ab = dp->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_dp_rx_tid *rx_tid; struct sk_buff *defrag_skb = NULL; u32 peer_id = rx_info->peer_id; @@ -1134,7 +1134,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, return -EINVAL; spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); if (!peer) { ath12k_warn(ab, "failed to find the peer to de-fragment received fragment peer_id %d\n", peer_id); @@ -1197,7 +1197,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); if (!peer) goto err_frags_cleanup; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h index df25164e08f2..f75588519cff 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h @@ -34,7 +34,7 @@ int ath12k_wifi7_dp_rx_link_desc_return(struct ath12k_base *ab, void ath12k_wifi7_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u16 tid, dma_addr_t paddr); void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k *ar, - struct ath12k_peer *peer, u8 tid); + struct ath12k_dp_link_peer *peer, u8 tid); int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_tid *rx_tid, enum hal_reo_cmd_type type, struct ath12k_hal_reo_cmd *cmd, @@ -43,7 +43,7 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_tid void ath12k_wifi7_dp_reo_cache_flush(struct ath12k_base *ab, struct ath12k_dp_rx_tid *rx_tid); int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k *ar, - struct ath12k_peer *peer, + struct ath12k_dp_link_peer *peer, struct ath12k_dp_rx_tid *rx_tid, u32 ba_win_sz, u16 ssn, bool update_ssn); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c index 2f523ed00ded..3d06987cfc0e 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c @@ -395,7 +395,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, struct sk_buff *msdu = desc_params->skb; s32 noise_floor; struct ieee80211_tx_status status = {}; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; skb_cb = ATH12K_SKB_CB(msdu); info = IEEE80211_SKB_CB(msdu); @@ -449,7 +449,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, } rcu_read_lock(); spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DATA, "dp_tx: failed to find the peer with peer_id %d\n", peer_id); @@ -518,7 +518,7 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, { struct ath12k_dp *dp = dp_pdev->dp; struct ath12k_base *ab = dp->ab; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ieee80211_sta *sta; struct ath12k_sta *ahsta; struct ath12k_link_sta *arsta; @@ -528,7 +528,7 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, int ret; spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, ts->peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, ts->peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DP_TX, "failed to find the peer by id %u\n", ts->peer_id); @@ -649,7 +649,7 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev, s32 noise_floor; struct ieee80211_tx_status status = {}; struct ieee80211_rate_status status_rate = {}; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k_link_sta *arsta; struct ath12k_sta *ahsta; struct rate_info rate; @@ -747,7 +747,7 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev, ath12k_wifi7_dp_tx_update_txcompl(dp_pdev, ts); spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, ts->peer_id); + peer = ath12k_dp_link_peer_find_by_id(ab, ts->peer_id); if (!peer || !peer->sta) { ath12k_err(ab, "dp_tx: failed to find the peer with peer_id %d\n", diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index 01c859f35a93..a3ea42fc0933 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -119,7 +119,7 @@ ath12k_wifi7_is_frame_link_agnostic_wcn7850(struct ath12k_link_vif *arvif, __le16 fc = mgmt->frame_control; spin_lock_bh(&ab->base_lock); - if (!ath12k_peer_find_by_addr(ab, mgmt->da) && + if (!ath12k_dp_link_peer_find_by_addr(ab, mgmt->da) && !ath12k_peer_ml_find(ah, mgmt->da)) { spin_unlock_bh(&ab->base_lock); return false; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index d84a3762ca95..817f1c917320 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -7202,7 +7202,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff { struct wmi_peer_sta_kickout_arg arg = {}; struct ieee80211_sta *sta; - struct ath12k_peer *peer; + struct ath12k_dp_link_peer *peer; struct ath12k *ar; if (ath12k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) { @@ -7214,7 +7214,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_addr(ab, arg.mac_addr); + peer = ath12k_dp_link_peer_find_by_addr(ab, arg.mac_addr); if (!peer) { ath12k_warn(ab, "peer not found %pM\n", -- 2.34.1 From: Harsh Kumar Bijlani Currently ath12k_base maintains a linked list of ath12k_dp_link_peer as "peers". This linked list is used for all kinds of peer search operations. In the control path, if there is a requirement to search for ath12k_link_sta using mac address, then below sequence is to be followed: 1. Find ath12k_dp_link_peer in the linked list using mac address 2. Fetch ieee80211_sta from ath12k_dp_link_peer 3. Fetch ath12k_sta from ieee80211_sta 4. Finally fetch ath12k_link_sta from ath12k_sta using link_id In the above sequence, there are too many indirections involved. In order to simplify this, add hash table for ath12k_link_sta in ath12k_base. This hash table is lock protected by existing spinlock "base_lock" in ath12k_base as this table can be concurrently accessed in different contexts. Use this table for ath12k_link_sta search operations using mac address in the control path. Ex: For WMI interface and mac80211_ops interface in the control path, sta mac address is received and this hash table can be used to search for ath12k_link_sta directly instead of following the longer route mentioned above. Helper APIs added: - ath12k_link_sta_rhash_add() - To add arsta entry to hash table - ath12k_link_sta_rhash_delete() - To remove arsta entry from hash table - ath12k_link_sta_find_by_addr() - To find arsta from hash table using mac address Make changes in API ath12k_peer_sta_kickout_event() to find arsta using above mechanism. ath11k driver has been taken as reference for implementation of hash table. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/core.c | 10 +++ drivers/net/wireless/ath/ath12k/core.h | 7 ++ drivers/net/wireless/ath/ath12k/mac.c | 72 +++++++++++++++ drivers/net/wireless/ath/ath12k/peer.c | 116 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/peer.h | 6 ++ drivers/net/wireless/ath/ath12k/wmi.c | 14 +-- 6 files changed, 218 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 1adbdd571a0f..c5aebe66d190 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -23,6 +23,7 @@ #include "pci.h" #include "wow.h" #include "dp_cmn.h" +#include "peer.h" unsigned int ath12k_debug_mask; module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); @@ -702,6 +703,8 @@ void ath12k_core_to_group_ref_put(struct ath12k_base *ab) static void ath12k_core_stop(struct ath12k_base *ab) { + ath12k_link_sta_rhash_tbl_destroy(ab); + ath12k_core_to_group_ref_put(ab); if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) @@ -964,6 +967,12 @@ static int ath12k_core_start(struct ath12k_base *ab) /* Indicate the core start in the appropriate group */ ath12k_core_to_group_ref_get(ab); + ret = ath12k_link_sta_rhash_tbl_init(ab); + if (ret) { + ath12k_warn(ab, "failed to init peer addr rhash table %d\n", ret); + goto err_reo_cleanup; + } + return 0; err_reo_cleanup: @@ -1351,6 +1360,7 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab) int ret, total_vdev; mutex_lock(&ab->core_lock); + ath12k_link_sta_rhash_tbl_destroy(ab); ath12k_dp_pdev_free(ab); ath12k_ce_cleanup_pipes(ab); ath12k_wmi_detach(ab); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 2bbe543bcf13..8b5a0a99cd31 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "qmi.h" #include "htc.h" #include "wmi.h" @@ -560,6 +561,9 @@ struct ath12k_link_sta { u8 link_idx; u32 tx_retry_failed; u32 tx_retry_count; + + /* peer addr based rhashtable list pointer */ + struct rhash_head rhash_addr; }; struct ath12k_reoq_buf { @@ -1220,6 +1224,9 @@ struct ath12k_base { */ const struct ieee80211_ops *ath12k_ops; + struct rhashtable *rhead_sta_addr; + struct rhashtable_params rhash_sta_addr_param; + /* must be last */ u8 drv_priv[] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 64609fffa7ce..5e6e176bf6a9 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1145,6 +1145,35 @@ static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif) return 0; } +static void ath12k_mac_link_sta_rhash_cleanup(void *data, struct ieee80211_sta *sta) +{ + u8 link_id; + unsigned long links_map; + struct ath12k_sta *ahsta; + struct ath12k *ar = data; + struct ath12k_link_sta *arsta; + struct ath12k_link_vif *arvif; + struct ath12k_base *ab = ar->ab; + + ahsta = ath12k_sta_to_ahsta(sta); + links_map = ahsta->links_map; + + rcu_read_lock(); + for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { + arsta = rcu_dereference(ahsta->link[link_id]); + if (!arsta) + continue; + arvif = arsta->arvif; + if (!(arvif->ar == ar)) + continue; + + spin_lock_bh(&ab->base_lock); + ath12k_link_sta_rhash_delete(ab, arsta); + spin_unlock_bh(&ab->base_lock); + } + rcu_read_unlock(); +} + void ath12k_mac_peer_cleanup_all(struct ath12k *ar) { struct ath12k_dp_link_peer *peer, *tmp; @@ -1165,6 +1194,10 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) ar->num_peers = 0; ar->num_stations = 0; + + /* Cleanup rhash table maintained for arsta by iterating over sta */ + ieee80211_iterate_stations_mtx(ar->ah->hw, ath12k_mac_link_sta_rhash_cleanup, + ar); } static int ath12k_mac_vdev_setup_sync(struct ath12k *ar) @@ -6349,6 +6382,7 @@ static int ath12k_mac_station_remove(struct ath12k *ar, struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k_vif *ahvif = arvif->ahvif; int ret = 0; + struct ath12k_link_sta *temp_arsta; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -6377,6 +6411,15 @@ static int ath12k_mac_station_remove(struct ath12k *ar, ath12k_mac_station_post_remove(ar, arvif, arsta); + spin_lock_bh(&ar->ab->base_lock); + + /* To handle roaming and split phy scenario */ + temp_arsta = ath12k_link_sta_find_by_addr(ar->ab, arsta->addr); + if (temp_arsta && temp_arsta->arvif->ar == ar) + ath12k_link_sta_rhash_delete(ar->ab, arsta); + + spin_unlock_bh(&ar->ab->base_lock); + if (sta->valid_links) ath12k_mac_free_unassign_link_sta(ahvif->ah, arsta->ahsta, arsta->link_id); @@ -6393,6 +6436,7 @@ static int ath12k_mac_station_add(struct ath12k *ar, struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k_wmi_peer_create_arg peer_param = {}; int ret; + struct ath12k_link_sta *temp_arsta; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -6411,6 +6455,26 @@ static int ath12k_mac_station_add(struct ath12k *ar, } } + spin_lock_bh(&ab->base_lock); + + /* + * In case of Split PHY and roaming scenario, pdev idx + * might differ but both the pdev will share same rhash + * table. In that case update the rhash table if link_sta is + * already present + */ + temp_arsta = ath12k_link_sta_find_by_addr(ab, arsta->addr); + if (temp_arsta && temp_arsta->arvif->ar != ar) + ath12k_link_sta_rhash_delete(ab, temp_arsta); + + ret = ath12k_link_sta_rhash_add(ab, arsta); + spin_unlock_bh(&ab->base_lock); + if (ret) { + ath12k_warn(ab, "Failed to add arsta: %pM to hash table, ret: %d", + arsta->addr, ret); + goto free_rx_stats; + } + peer_param.vdev_id = arvif->vdev_id; peer_param.peer_addr = arsta->addr; peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; @@ -6459,6 +6523,10 @@ static int ath12k_mac_station_add(struct ath12k *ar, free_peer: ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr); + spin_lock_bh(&ab->base_lock); + ath12k_link_sta_rhash_delete(ab, arsta); + spin_unlock_bh(&ab->base_lock); +free_rx_stats: kfree(arsta->rx_stats); arsta->rx_stats = NULL; dec_num_station: @@ -6537,6 +6605,10 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif, ath12k_mac_station_post_remove(ar, arvif, arsta); + spin_lock_bh(&ar->ab->base_lock); + ath12k_link_sta_rhash_delete(ar->ab, arsta); + spin_unlock_bh(&ar->ab->base_lock); + ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id); } diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 16f4a74712d8..28801d87e6ed 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -406,3 +406,119 @@ int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_st return err_ret; } + +static int ath12k_link_sta_rhash_insert(struct ath12k_base *ab, + struct ath12k_link_sta *arsta) +{ + struct ath12k_link_sta *tmp; + + lockdep_assert_held(&ab->base_lock); + + tmp = rhashtable_lookup_get_insert_fast(ab->rhead_sta_addr, &arsta->rhash_addr, + ab->rhash_sta_addr_param); + if (!tmp) + return 0; + else if (IS_ERR(tmp)) + return PTR_ERR(tmp); + else + return -EEXIST; +} + +static int ath12k_link_sta_rhash_remove(struct ath12k_base *ab, + struct ath12k_link_sta *arsta) +{ + int ret; + + lockdep_assert_held(&ab->base_lock); + + ret = rhashtable_remove_fast(ab->rhead_sta_addr, &arsta->rhash_addr, + ab->rhash_sta_addr_param); + if (ret && ret != -ENOENT) + return ret; + + return 0; +} + +int ath12k_link_sta_rhash_add(struct ath12k_base *ab, + struct ath12k_link_sta *arsta) +{ + int ret; + + lockdep_assert_held(&ab->base_lock); + + ret = ath12k_link_sta_rhash_insert(ab, arsta); + if (ret) + ath12k_warn(ab, "failed to add arsta %pM in rhash_addr ret %d\n", + arsta->addr, ret); + + return ret; +} + +void ath12k_link_sta_rhash_delete(struct ath12k_base *ab, + struct ath12k_link_sta *arsta) +{ + /* + * Return type of this function is void since there is nothing to be + * done in failure case + */ + int ret; + + lockdep_assert_held(&ab->base_lock); + + ret = ath12k_link_sta_rhash_remove(ab, arsta); + if (ret) + ath12k_warn(ab, + "failed to remove arsta %pM in rhash_addr ret %d\n", + arsta->addr, ret); +} + +int ath12k_link_sta_rhash_tbl_init(struct ath12k_base *ab) +{ + struct rhashtable_params *param; + struct rhashtable *rhash_addr_tbl; + int ret; + + rhash_addr_tbl = kzalloc(sizeof(*ab->rhead_sta_addr), GFP_KERNEL); + if (!rhash_addr_tbl) + return -ENOMEM; + + param = &ab->rhash_sta_addr_param; + + param->key_offset = offsetof(struct ath12k_link_sta, addr); + param->head_offset = offsetof(struct ath12k_link_sta, rhash_addr); + param->key_len = sizeof_field(struct ath12k_link_sta, addr); + param->automatic_shrinking = true; + param->nelem_hint = ab->num_radios * ath12k_core_get_max_peers_per_radio(ab); + + ret = rhashtable_init(rhash_addr_tbl, param); + if (ret) { + ath12k_warn(ab, "failed to init peer addr rhash table %d\n", + ret); + goto err_free; + } + + ab->rhead_sta_addr = rhash_addr_tbl; + + return 0; + +err_free: + kfree(rhash_addr_tbl); + + return ret; +} + +void ath12k_link_sta_rhash_tbl_destroy(struct ath12k_base *ab) +{ + rhashtable_destroy(ab->rhead_sta_addr); + kfree(ab->rhead_sta_addr); + ab->rhead_sta_addr = NULL; +} + +struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab, + const u8 *addr) +{ + lockdep_assert_held(&ab->base_lock); + + return rhashtable_lookup_fast(ab->rhead_sta_addr, addr, + ab->rhash_sta_addr_param); +} diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h index 81e9bcc067ff..cf8a463d4c37 100644 --- a/drivers/net/wireless/ath/ath12k/peer.h +++ b/drivers/net/wireless/ath/ath12k/peer.h @@ -27,4 +27,10 @@ int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta); int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr); +int ath12k_link_sta_rhash_tbl_init(struct ath12k_base *ab); +void ath12k_link_sta_rhash_tbl_destroy(struct ath12k_base *ab); +void ath12k_link_sta_rhash_delete(struct ath12k_base *ab, struct ath12k_link_sta *arsta); +int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *arsta); +struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab, + const u8 *addr); #endif /* _PEER_H_ */ diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 817f1c917320..0d4a83b8005a 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -7202,7 +7202,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff { struct wmi_peer_sta_kickout_arg arg = {}; struct ieee80211_sta *sta; - struct ath12k_dp_link_peer *peer; + struct ath12k_link_sta *arsta; struct ath12k *ar; if (ath12k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) { @@ -7214,18 +7214,18 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_addr(ab, arg.mac_addr); + arsta = ath12k_link_sta_find_by_addr(ab, arg.mac_addr); - if (!peer) { - ath12k_warn(ab, "peer not found %pM\n", + if (!arsta) { + ath12k_warn(ab, "arsta not found %pM\n", arg.mac_addr); goto exit; } - ar = ath12k_mac_get_ar_by_vdev_id(ab, peer->vdev_id); + ar = arsta->arvif->ar; if (!ar) { - ath12k_warn(ab, "invalid vdev id in peer sta kickout ev %d", - peer->vdev_id); + ath12k_warn(ab, "invalid ar in peer sta kickout ev for STA %pM\n", + arg.mac_addr); goto exit; } -- 2.34.1 From: Harsh Kumar Bijlani ath12k_base maintains a linked list of ath12k_dp_link_peer. This linked list is used for all kind of peer search operations. With the modularization of device and peer objects for ath12k next-generation driver, ath12k_dp_link_peer and ath12k_dp are exclusively meant for datapath related operations. Hence move ath12k_dp_link_peer linked list from ath12k_base to ath12k_dp. This linked list is to be lock protected by newly introduced spinlock "dp_lock" defined in ath12k_dp as this list can be concurrently accessed in different contexts for insert, delete and search operations. With the above changes, update following APIs to make use of lock "dp->dp_lock" instead of lock "ab->base_lock" and also update API signatures to pass ath12k_dp pointer instead of ath12k_base pointer as the function argument. ath12k_dp_link_peer_find_by_vdev_and_addr() ath12k_dp_link_peer_find_by_id() ath12k_dp_link_peer_find_by_ast() ath12k_dp_link_peer_find_by_pdev__and_addr() ath12k_dp_link_peer_find_by_ml_id() ath12k_dp_link_peer_find_by_addr() ath12k_dp_rx_h_find_link_peer() Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/core.c | 1 - drivers/net/wireless/ath/ath12k/core.h | 1 - drivers/net/wireless/ath/ath12k/dp.c | 23 +++-- drivers/net/wireless/ath/ath12k/dp.h | 6 ++ drivers/net/wireless/ath/ath12k/dp_htt.c | 26 ++--- drivers/net/wireless/ath/ath12k/dp_mon.c | 17 ++-- drivers/net/wireless/ath/ath12k/dp_peer.c | 64 ++++++------ drivers/net/wireless/ath/ath12k/dp_peer.h | 12 +-- drivers/net/wireless/ath/ath12k/dp_rx.c | 86 ++++++++-------- drivers/net/wireless/ath/ath12k/dp_rx.h | 4 +- drivers/net/wireless/ath/ath12k/mac.c | 99 +++++++++++-------- drivers/net/wireless/ath/ath12k/peer.c | 31 +++--- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 20 ++-- drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c | 25 ++--- .../net/wireless/ath/ath12k/wifi7/hal_rx.c | 3 +- drivers/net/wireless/ath/ath12k/wifi7/hw.c | 9 +- 16 files changed, 234 insertions(+), 193 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index c5aebe66d190..2e093029c782 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -2250,7 +2250,6 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, spin_lock_init(&ab->base_lock); init_completion(&ab->reset_complete); - INIT_LIST_HEAD(&ab->peers); init_waitqueue_head(&ab->peer_mapping_wq); init_waitqueue_head(&ab->wmi_ab.tx_credits_wq); INIT_WORK(&ab->restart_work, ath12k_core_restart); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 8b5a0a99cd31..eb406fc9ab71 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -1085,7 +1085,6 @@ struct ath12k_base { struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS]; unsigned long long free_vdev_map; unsigned long long free_vdev_stats_id_map; - struct list_head peers; wait_queue_head_t peer_mapping_wq; u8 mac_addr[ETH_ALEN]; bool wmi_ready; diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index 945e4965a437..40057df4cd66 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -24,27 +24,28 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr) { struct ath12k_base *ab = ar->ab; struct ath12k_dp_link_peer *peer; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); /* TODO: Any other peer specific DP cleanup */ - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, addr); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr); if (!peer) { ath12k_warn(ab, "failed to lookup peer %pM on vdev %d\n", addr, vdev_id); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return; } if (!peer->primary_link) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return; } ath12k_dp_rx_peer_tid_cleanup(ar, peer); crypto_free_shash(peer->tfm_mmic); peer->dp_setup_done = false; - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) @@ -53,6 +54,7 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) struct ath12k_dp_link_peer *peer; u32 reo_dest; int ret = 0, tid; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ reo_dest = ar->dp.mac_id + 1; @@ -87,19 +89,19 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) return 0; peer_clean: - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr); if (!peer) { ath12k_warn(ab, "failed to find the peer to del rx tid\n"); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return -ENOENT; } for (tid--; tid >= 0; tid--) ath12k_wifi7_dp_rx_peer_tid_delete(ar, peer, tid); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return ret; } @@ -1482,6 +1484,9 @@ static int ath12k_dp_setup(struct ath12k_base *ab) INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list); spin_lock_init(&dp->reo_cmd_lock); + spin_lock_init(&dp->dp_lock); + INIT_LIST_HEAD(&dp->peers); + dp->reo_cmd_cache_flush_count = 0; dp->idle_link_rbm = ath12k_hal_get_idle_link_rbm(&ab->hal, ab->device_id); diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index 5cedc6603e74..fc87b749a040 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -471,7 +471,13 @@ struct ath12k_dp { struct ath12k_hw_group *ag; u8 device_id; + /* Lock for protection of peers */ + spinlock_t dp_lock; + struct ath12k_dp_arch_ops *ops; + + /* Linked list of struct ath12k_dp_link_peer */ + struct list_head peers; }; static inline void ath12k_dp_get_mac_addr(u32 addr_l32, u16 addr_h16, u8 *addr) diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c index cae5a90c1c65..f3dca108c614 100644 --- a/drivers/net/wireless/ath/ath12k/dp_htt.c +++ b/drivers/net/wireless/ath/ath12k/dp_htt.c @@ -272,18 +272,18 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, } rcu_read_lock(); - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, usr_stats->peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, usr_stats->peer_id); if (!peer || !peer->sta) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); return; } arsta = ath12k_dp_link_peer_to_link_sta(ab, peer); if (!arsta) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); return; } @@ -357,7 +357,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags); } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); } @@ -507,17 +507,17 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, ppdu_info->delay_ba) { for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) { peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id; - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); if (!peer) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); continue; } usr_stats = &ppdu_info->ppdu_stats.user_stats[i]; if (usr_stats->delay_ba) ath12k_copy_to_delay_stats(peer, usr_stats); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } } @@ -526,17 +526,17 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON))) { for (i = 0; i < ppdu_info->bar_num_users; i++) { peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id; - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); if (!peer) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); continue; } usr_stats = &ppdu_info->ppdu_stats.user_stats[i]; if (peer->delayba_flag) ath12k_copy_to_bar(peer, usr_stats); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } } diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c index 9da9fc403315..f65ac12d7f2b 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c @@ -2287,9 +2287,9 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, ath12k_wifi7_dp_extract_rx_desc_data(ab, &rx_info, rx_desc, rx_desc); - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); rx_info.addr2_present = false; - peer = ath12k_dp_rx_h_find_link_peer(ab, msdu, &rx_info); + peer = ath12k_dp_rx_h_find_link_peer(dp, msdu, &rx_info); if (peer && peer->sta) { pubsta = peer->sta; if (pubsta->valid_links) { @@ -2298,7 +2298,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, } } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_dbg(ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %u %s %s%s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", @@ -3639,11 +3639,12 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab, struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid]; struct ath12k_dp_link_peer *peer; u32 num_msdu; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); if (user_stats->ast_index == 0 || user_stats->ast_index == 0xFFFF) return; - peer = ath12k_dp_link_peer_find_by_ast(ab, user_stats->ast_index); + peer = ath12k_dp_link_peer_find_by_ast(dp, user_stats->ast_index); if (!peer) { ath12k_warn(ab, "peer ast idx %d can't be found\n", @@ -3884,8 +3885,8 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, goto free_skb; rcu_read_lock(); - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, ppdu_info->peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, ppdu_info->peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DATA, "failed to find the peer with monitor peer_id %d\n", @@ -3898,7 +3899,7 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, if (!arsta) { ath12k_warn(ab, "link sta not found on peer %pM id %d\n", peer->addr, peer->peer_id); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); dev_kfree_skb_any(skb); continue; @@ -3912,7 +3913,7 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, } next_skb: - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); free_skb: dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 843369a00d3e..0267f68f8573 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -9,14 +9,14 @@ #include "debug.h" struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_base *ab, +ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp, int vdev_id, const u8 *addr) { struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); - list_for_each_entry(peer, &ab->peers, list) { + list_for_each_entry(peer, &dp->peers, list) { if (peer->vdev_id != vdev_id) continue; if (!ether_addr_equal(peer->addr, addr)) @@ -29,14 +29,14 @@ ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_base *ab, } struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_base *ab, u8 pdev_idx, +ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_dp *dp, u8 pdev_idx, const u8 *addr) { struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); - list_for_each_entry(peer, &ab->peers, list) { + list_for_each_entry(peer, &dp->peers, list) { if (peer->pdev_idx != pdev_idx) continue; if (!ether_addr_equal(peer->addr, addr)) @@ -49,13 +49,13 @@ ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_base *ab, u8 pdev_idx, } struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_addr(struct ath12k_base *ab, const u8 *addr) +ath12k_dp_link_peer_find_by_addr(struct ath12k_dp *dp, const u8 *addr) { struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); - list_for_each_entry(peer, &ab->peers, list) { + list_for_each_entry(peer, &dp->peers, list) { if (!ether_addr_equal(peer->addr, addr)) continue; @@ -67,13 +67,13 @@ ath12k_dp_link_peer_find_by_addr(struct ath12k_base *ab, const u8 *addr) EXPORT_SYMBOL(ath12k_dp_link_peer_find_by_addr); static struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_ml_id(struct ath12k_base *ab, int ml_peer_id) +ath12k_dp_link_peer_find_by_ml_id(struct ath12k_dp *dp, int ml_peer_id) { struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); - list_for_each_entry(peer, &ab->peers, list) + list_for_each_entry(peer, &dp->peers, list) if (ml_peer_id == peer->ml_id) return peer; @@ -81,49 +81,49 @@ ath12k_dp_link_peer_find_by_ml_id(struct ath12k_base *ab, int ml_peer_id) } struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_id(struct ath12k_base *ab, int peer_id) +ath12k_dp_link_peer_find_by_id(struct ath12k_dp *dp, int peer_id) { struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); if (peer_id == HAL_INVALID_PEERID) return NULL; if (peer_id & ATH12K_PEER_ML_ID_VALID) - return ath12k_dp_link_peer_find_by_ml_id(ab, peer_id); + return ath12k_dp_link_peer_find_by_ml_id(dp, peer_id); - list_for_each_entry(peer, &ab->peers, list) + list_for_each_entry(peer, &dp->peers, list) if (peer_id == peer->peer_id) return peer; return NULL; } -bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id) +bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_dp *dp, int vdev_id) { struct ath12k_dp_link_peer *peer; - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - list_for_each_entry(peer, &ab->peers, list) { + list_for_each_entry(peer, &dp->peers, list) { if (vdev_id == peer->vdev_id) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return true; } } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return false; } struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_ast(struct ath12k_base *ab, int ast_hash) +ath12k_dp_link_peer_find_by_ast(struct ath12k_dp *dp, int ast_hash) { struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); - list_for_each_entry(peer, &ab->peers, list) + list_for_each_entry(peer, &dp->peers, list) if (ast_hash == peer->ast_hash) return peer; @@ -133,10 +133,11 @@ ath12k_dp_link_peer_find_by_ast(struct ath12k_base *ab, int ast_hash) void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) { struct ath12k_dp_link_peer *peer; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); if (!peer) { ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n", peer_id); @@ -151,16 +152,17 @@ void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) wake_up(&ab->peer_mapping_wq); exit: - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) { struct ath12k_dp_link_peer *peer; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, mac_addr); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, mac_addr); if (!peer) { peer = kzalloc(sizeof(*peer), GFP_ATOMIC); if (!peer) @@ -171,7 +173,7 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ peer->ast_hash = ast_hash; peer->hw_peer_id = hw_peer_id; ether_addr_copy(peer->addr, mac_addr); - list_add(&peer->list, &ab->peers); + list_add(&peer->list, &dp->peers); wake_up(&ab->peer_mapping_wq); } @@ -179,7 +181,7 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ vdev_id, mac_addr, peer_id); exit: - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index aec73d8e35ce..ecc90df05b44 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -69,17 +69,17 @@ void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_base *ab, +ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp, int vdev_id, const u8 *addr); struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_addr(struct ath12k_base *ab, const u8 *addr); +ath12k_dp_link_peer_find_by_addr(struct ath12k_dp *dp, const u8 *addr); struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_id(struct ath12k_base *ab, int peer_id); -bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id); +ath12k_dp_link_peer_find_by_id(struct ath12k_dp *dp, int peer_id); +bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_dp *dp, int vdev_id); struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); +ath12k_dp_link_peer_find_by_ast(struct ath12k_dp *dp, int ast_hash); struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_base *ab, u8 pdev_idx, +ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_dp *dp, u8 pdev_idx, const u8 *addr); struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, struct ath12k_dp_link_peer *peer); diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index f6d800c1ebf9..08dc0345a2b2 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -450,9 +450,10 @@ void ath12k_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid, bool rel_link_desc) { struct ath12k_buffer_addr *buf_addr_info; - struct ath12k_base *ab = rx_tid->ab; + struct ath12k_dp *dp = rx_tid->dp; + struct ath12k_base *ab = dp->ab; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); if (rx_tid->dst_ring_desc) { if (rel_link_desc) { @@ -475,8 +476,10 @@ void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer { struct ath12k_dp_rx_tid *rx_tid; int i; + struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); - lockdep_assert_held(&ar->ab->base_lock); + lockdep_assert_held(&dp->dp_lock); for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { rx_tid = &peer->rx_tid[i]; @@ -484,9 +487,9 @@ void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer ath12k_wifi7_dp_rx_peer_tid_delete(ar, peer, i); ath12k_dp_rx_frags_cleanup(rx_tid, true); - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); timer_delete_sync(&rx_tid->frag_timer); - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); } } @@ -502,24 +505,24 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ dma_addr_t paddr_aligned; int ret; - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, peer_mac); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac); if (!peer) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer to set up rx tid\n"); return -ENOENT; } if (ab->hw_params->dp_primary_link_only && !peer->primary_link) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return 0; } if (ab->hw_params->reoq_lut_support && (!dp->reoq_lut.vaddr || !dp->ml_reoq_lut.vaddr)) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "reo qref table is not setup\n"); return -EINVAL; } @@ -527,7 +530,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ if (peer->peer_id > DP_MAX_PEER_ID || tid > IEEE80211_NUM_TIDS) { ath12k_warn(ab, "peer id of peer %d or tid %d doesn't allow reoq setup\n", peer->peer_id, tid); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return -EINVAL; } @@ -536,7 +539,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ if (rx_tid->active) { ret = ath12k_wifi7_peer_rx_tid_reo_update(ar, peer, rx_tid, ba_win_sz, ssn, true); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); if (ret) { ath12k_warn(ab, "failed to update reo for rx tid %d\n", tid); return ret; @@ -565,7 +568,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ ahsta = ath12k_sta_to_ahsta(peer->sta); ret = ath12k_wifi7_dp_rx_assign_reoq(ab, ahsta, rx_tid, ssn, pn_type); if (ret) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to assign reoq buf for rx tid %u\n", tid); return ret; } @@ -582,9 +585,9 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ ath12k_wifi7_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr_aligned); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } else { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, paddr_aligned, tid, 1, ba_win_sz); @@ -626,6 +629,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, u8 link_id) { struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); struct ath12k_dp_link_peer *peer; struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta); struct ath12k_link_sta *arsta; @@ -642,11 +646,11 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, vdev_id = arsta->arvif->vdev_id; - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, arsta->addr); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, arsta->addr); if (!peer) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer to stop rx aggregation\n"); return -ENOENT; } @@ -654,12 +658,12 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, active = peer->rx_tid[params->tid].active; if (!active) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return 0; } ret = ath12k_wifi7_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); if (ret) { ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n", params->tid, ret); @@ -676,6 +680,7 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, { struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); struct ath12k_hal_reo_cmd cmd = {}; struct ath12k_dp_link_peer *peer; struct ath12k_dp_rx_tid *rx_tid; @@ -689,12 +694,12 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) return 0; - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, peer_addr); if (!peer) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer %pM to configure pn replay detection\n", peer_addr); return -ENOENT; @@ -717,7 +722,7 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, } } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return ret; } @@ -1038,22 +1043,22 @@ void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu } struct ath12k_dp_link_peer * -ath12k_dp_rx_h_find_link_peer(struct ath12k_base *ab, struct sk_buff *msdu, +ath12k_dp_rx_h_find_link_peer(struct ath12k_dp *dp, struct sk_buff *msdu, struct hal_rx_desc_data *rx_info) { struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); struct ath12k_dp_link_peer *peer = NULL; - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); if (rxcb->peer_id) - peer = ath12k_dp_link_peer_find_by_id(ab, rxcb->peer_id); + peer = ath12k_dp_link_peer_find_by_id(dp, rxcb->peer_id); if (peer) return peer; if (rx_info->addr2_present) - peer = ath12k_dp_link_peer_find_by_addr(ab, rx_info->addr2); + peer = ath12k_dp_link_peer_find_by_addr(dp, rx_info->addr2); return peer; } @@ -1203,8 +1208,8 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc bool is_mcbc = rxcb->is_mcbc; bool is_eapol = rxcb->is_eapol; - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_rx_h_find_link_peer(ab, msdu, rx_info); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_rx_h_find_link_peer(dp, msdu, rx_info); pubsta = peer ? peer->sta : NULL; @@ -1213,7 +1218,7 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc status->link_id = peer->link_id; } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_dbg(ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", @@ -1311,14 +1316,14 @@ static void ath12k_dp_rx_frag_timer(struct timer_list *timer) struct ath12k_dp_rx_tid *rx_tid = timer_container_of(rx_tid, timer, frag_timer); - spin_lock_bh(&rx_tid->ab->base_lock); + spin_lock_bh(&rx_tid->dp->dp_lock); if (rx_tid->last_frag_no && rx_tid->rx_frag_bitmap == GENMASK(rx_tid->last_frag_no, 0)) { - spin_unlock_bh(&rx_tid->ab->base_lock); + spin_unlock_bh(&rx_tid->dp->dp_lock); return; } ath12k_dp_rx_frags_cleanup(rx_tid, true); - spin_unlock_bh(&rx_tid->ab->base_lock); + spin_unlock_bh(&rx_tid->dp->dp_lock); } int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id) @@ -1328,37 +1333,38 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev struct ath12k_dp_link_peer *peer; struct ath12k_dp_rx_tid *rx_tid; int i; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); tfm = crypto_alloc_shash("michael_mic", 0, 0); if (IS_ERR(tfm)) return PTR_ERR(tfm); - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, vdev_id, peer_mac); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac); if (!peer) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); crypto_free_shash(tfm); ath12k_warn(ab, "failed to find the peer to set up fragment info\n"); return -ENOENT; } if (!peer->primary_link) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); crypto_free_shash(tfm); return 0; } for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { rx_tid = &peer->rx_tid[i]; - rx_tid->ab = ab; + rx_tid->dp = dp; timer_setup(&rx_tid->frag_timer, ath12k_dp_rx_frag_timer, 0); skb_queue_head_init(&rx_tid->rx_frags); } peer->tfm_mmic = tfm; peer->dp_setup_done = true; - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return 0; } diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h index b45097855620..9b0334515c6e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/dp_rx.h @@ -28,7 +28,7 @@ struct ath12k_dp_rx_tid { /* Timer info related to fragments */ struct timer_list frag_timer; - struct ath12k_base *ab; + struct ath12k_dp *dp; }; struct ath12k_dp_rx_reo_cache_flush_elem { @@ -230,7 +230,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab, struct hal_rx_desc *desc); struct ath12k_dp_link_peer * -ath12k_dp_rx_h_find_link_peer(struct ath12k_base *ab, struct sk_buff *msdu, +ath12k_dp_rx_h_find_link_peer(struct ath12k_dp *dp, struct sk_buff *msdu, struct hal_rx_desc_data *rx_info); u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab, struct hal_rx_desc *desc); diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 5e6e176bf6a9..fd6819ec390c 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1178,11 +1178,12 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) { struct ath12k_dp_link_peer *peer, *tmp; struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - spin_lock_bh(&ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ab->peers, list) { + spin_lock_bh(&dp->dp_lock); + list_for_each_entry_safe(peer, tmp, &dp->peers, list) { /* Skip Rx TID cleanup for self peer */ if (peer->sta) ath12k_dp_rx_peer_tid_cleanup(ar, peer); @@ -1190,7 +1191,7 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) list_del(&peer->list); kfree(peer); } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ar->num_peers = 0; ar->num_stations = 0; @@ -3647,6 +3648,7 @@ static void ath12k_bss_assoc(struct ath12k *ar, bool is_auth = false; u32 hemode = 0; int ret; + struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -3758,14 +3760,14 @@ static void ath12k_bss_assoc(struct ath12k *ar, "mac vdev %d up (associated) bssid %pM aid %d\n", arvif->vdev_id, bss_conf->bssid, vif->cfg.aid); - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, arvif->bssid); if (peer && peer->is_authorized) is_auth = true; - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); /* Authorize BSS Peer */ if (is_auth) { @@ -5475,15 +5477,18 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, int ret; int i; u32 flags = 0; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, addr); - spin_unlock_bh(&ab->base_lock); - - if (!peer) + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, addr); + if (!peer) { + spin_unlock_bh(&dp->dp_lock); return -ENOENT; + } + + spin_unlock_bh(&dp->dp_lock); for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { if (!peer->keys[i]) @@ -5499,9 +5504,9 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, ath12k_warn(ab, "failed to remove peer key %d: %d\n", i, ret); - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); peer->keys[i] = NULL; - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } return first_errno; @@ -5519,6 +5524,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, const u8 *peer_addr; int ret; u32 flags = 0; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -5538,12 +5544,12 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, /* the peer should not disappear in mid-way (unless FW goes awry) since * we already hold wiphy lock. we just make sure its there now. */ - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, peer_addr); - spin_unlock_bh(&ab->base_lock); - if (!peer) { + spin_unlock_bh(&dp->dp_lock); + if (cmd == SET_KEY) { ath12k_warn(ab, "cannot install key for non-existent peer %pM\n", peer_addr); @@ -5556,6 +5562,8 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, return 0; } + spin_unlock_bh(&dp->dp_lock); + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) flags = WMI_KEY_PAIRWISE; else @@ -5573,8 +5581,8 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, return ret; } - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ab, arvif->vdev_id, + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, peer_addr); if (peer && cmd == SET_KEY) { peer->keys[key->keyidx] = key; @@ -5615,7 +5623,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, } } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return 0; } @@ -6283,14 +6291,15 @@ static void ath12k_mac_station_post_remove(struct ath12k *ar, struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k_dp_link_peer *peer; + struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ath12k_mac_dec_num_stations(arvif, arsta); - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, arsta->addr); if (peer && peer->sta == sta) { ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", @@ -6301,7 +6310,7 @@ static void ath12k_mac_station_post_remove(struct ath12k *ar, ar->num_peers--; } - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); kfree(arsta->rx_stats); arsta->rx_stats = NULL; @@ -6313,17 +6322,18 @@ static int ath12k_mac_station_unauthorize(struct ath12k *ar, { struct ath12k_dp_link_peer *peer; int ret; + struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, arsta->addr); if (peer) peer->is_authorized = false; - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); /* Driver must clear the keys during the state change from * IEEE80211_STA_AUTHORIZED to IEEE80211_STA_ASSOC, since after @@ -6348,17 +6358,18 @@ static int ath12k_mac_station_authorize(struct ath12k *ar, struct ath12k_dp_link_peer *peer; struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); int ret; + struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, arsta->addr); if (peer) peer->is_authorized = true; - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) { ret = ath12k_wmi_set_peer_param(ar, arsta->addr, @@ -7264,6 +7275,7 @@ void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw, struct ath12k_link_vif *arvif; struct ath12k_dp_link_peer *peer; u32 bw, smps; + struct ath12k_dp *dp; rcu_read_lock(); arvif = rcu_dereference(ahvif->link[link_sta->link_id]); @@ -7275,6 +7287,7 @@ void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw, } ar = arvif->ar; + dp = ath12k_ab_to_dp(ar->ab); arsta = rcu_dereference(ahsta->link[link_sta->link_id]); if (!arsta) { @@ -7283,19 +7296,19 @@ void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw, link_sta->link_id, sta->addr); return; } - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arvif->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, arsta->addr); if (!peer) { - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", arsta->addr, arvif->vdev_id); return; } - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); if (arsta->link_id >= IEEE80211_MLD_MAX_NUM_LINKS) { rcu_read_unlock(); @@ -8923,6 +8936,7 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, u16 mcbc_gsn; u8 link_id; int ret; + struct ath12k_dp *tmp_dp; if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ieee80211_free_txskb(hw, skb); @@ -9048,11 +9062,12 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, if (unlikely(!ahvif->dp_vif.key_cipher)) goto skip_peer_find; - spin_lock_bh(&tmp_ar->ab->base_lock); - peer = ath12k_dp_link_peer_find_by_addr(tmp_ar->ab, + tmp_dp = ath12k_ab_to_dp(tmp_ar->ab); + spin_lock_bh(&tmp_dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_addr(tmp_dp, tmp_arvif->bssid); if (!peer) { - spin_unlock_bh(&tmp_ar->ab->base_lock); + spin_unlock_bh(&tmp_dp->dp_lock); ath12k_warn(tmp_ar->ab, "failed to find peer for vdev_id 0x%X addr %pM link_map 0x%X\n", tmp_arvif->vdev_id, tmp_arvif->bssid, @@ -9071,7 +9086,7 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); } - spin_unlock_bh(&tmp_ar->ab->base_lock); + spin_unlock_bh(&tmp_dp->dp_lock); skip_peer_find: ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif, @@ -11651,7 +11666,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, if (ab->hw_params->vdev_start_delay && ahvif->vdev_type != WMI_VDEV_TYPE_AP && ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && - !ath12k_dp_link_peer_exist_by_vdev_id(ab, arvif->vdev_id)) { + !ath12k_dp_link_peer_exist_by_vdev_id(ath12k_ab_to_dp(ab), arvif->vdev_id)) { ret = 0; goto out; } @@ -12371,6 +12386,8 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban struct ath12k_dp_link_peer *peer, *tmp; u8 vht_nss, he_nss; int ret = true; + struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); vht_mcs_mask = mask->control[band].vht_mcs; he_mcs_mask = mask->control[band].he_mcs; @@ -12388,8 +12405,8 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban he_nss = ath12k_mac_max_he_nss(he_mcs_mask); rcu_read_lock(); - spin_lock_bh(&ar->ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { + spin_lock_bh(&dp->dp_lock); + list_for_each_entry_safe(peer, tmp, &dp->peers, list) { if (peer->sta) { link_sta = rcu_dereference(peer->sta->link[link_id]); if (!link_sta) { @@ -12410,7 +12427,7 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban } } exit: - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); return ret; } diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 28801d87e6ed..68eebaa24ed9 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -29,15 +29,16 @@ static int ath12k_wait_for_dp_link_peer_common(struct ath12k_base *ab, int vdev_ const u8 *addr, bool expect_mapped) { int ret; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); ret = wait_event_timeout(ab->peer_mapping_wq, ({ bool mapped; - spin_lock_bh(&ab->base_lock); - mapped = !!ath12k_dp_link_peer_find_by_vdev_and_addr(ab, + spin_lock_bh(&dp->dp_lock); + mapped = !!ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); (mapped == expect_mapped || test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)); @@ -53,11 +54,12 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id) { struct ath12k_dp_link_peer *peer, *tmp; struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - spin_lock_bh(&ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ab->peers, list) { + spin_lock_bh(&dp->dp_lock); + list_for_each_entry_safe(peer, tmp, &dp->peers, list) { if (peer->vdev_id != vdev_id) continue; @@ -69,7 +71,7 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id) ar->num_peers--; } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); } static int ath12k_wait_for_peer_deleted(struct ath12k *ar, int vdev_id, const u8 *addr) @@ -156,6 +158,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ath12k_sta *ahsta; u16 ml_peer_id; int ret; + struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -167,14 +170,14 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, return -ENOBUFS; } - spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_dp_link_peer_find_by_pdev_and_addr(ar->ab, ar->pdev_idx, + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_pdev_and_addr(dp, ar->pdev_idx, arg->peer_addr); if (peer) { - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return -EINVAL; } - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ret = ath12k_wmi_send_peer_create_cmd(ar, arg); if (ret) { @@ -189,12 +192,12 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, if (ret) return ret; - spin_lock_bh(&ar->ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_vdev_and_addr(ar->ab, arg->vdev_id, + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arg->vdev_id, arg->peer_addr); if (!peer) { - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ath12k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", arg->peer_addr, arg->vdev_id); @@ -255,7 +258,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, ar->num_peers++; - spin_unlock_bh(&ar->ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return 0; } diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index 4180db504c31..da745566aca3 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -37,6 +37,7 @@ void ath12k_wifi7_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u1 qref->info1 = u32_encode_bits(upper_32_bits(paddr), BUFFER_ADDR_INFO1_ADDR) | u32_encode_bits(tid, DP_REO_QREF_NUM); + ath12k_hal_reo_shared_qaddr_cache_clear(ab); } @@ -316,7 +317,6 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, struct hal_rx_desc_data *rx_info) { struct ath12k_dp *dp = dp_pdev->dp; - struct ath12k_base *ab = dp->ab; struct ath12k_skb_rxcb *rxcb; enum hal_encrypt_type enctype; bool is_decrypted = false; @@ -332,8 +332,8 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, if (rxcb->is_mcbc) rxcb->peer_id = rx_info->peer_id; - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_rx_h_find_link_peer(ab, msdu, rx_info); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_rx_h_find_link_peer(dp, msdu, rx_info); if (peer) { /* resetting mcbc bit because mcbc packets are unicast * packets only for AP as STA sends unicast packets. @@ -347,7 +347,7 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, } else { enctype = HAL_ENCRYPT_TYPE_OPEN; } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap) is_decrypted = rx_info->is_decrypted; @@ -1133,8 +1133,8 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, if (WARN_ON_ONCE(!frag_no && !more_frags)) return -EINVAL; - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); if (!peer) { ath12k_warn(ab, "failed to find the peer to de-fragment received fragment peer_id %d\n", peer_id); @@ -1193,11 +1193,11 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, goto out_unlock; } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); timer_delete_sync(&rx_tid->frag_timer); - spin_lock_bh(&ab->base_lock); + spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); + peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); if (!peer) goto err_frags_cleanup; @@ -1221,7 +1221,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, dev_kfree_skb_any(defrag_skb); ath12k_dp_rx_frags_cleanup(rx_tid, true); out_unlock: - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return ret; } diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c index 3d06987cfc0e..77de02858677 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c @@ -396,6 +396,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, s32 noise_floor; struct ieee80211_tx_status status = {}; struct ath12k_dp_link_peer *peer; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); skb_cb = ATH12K_SKB_CB(msdu); info = IEEE80211_SKB_CB(msdu); @@ -448,18 +449,18 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, } } rcu_read_lock(); - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DATA, "dp_tx: failed to find the peer with peer_id %d\n", peer_id); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ieee80211_free_txskb(ath12k_ar_to_hw(ar), msdu); goto exit; } else { status.sta = peer->sta; } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); status.info = info; status.skb = msdu; @@ -527,12 +528,12 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, u8 rate_idx = 0; int ret; - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, ts->peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, ts->peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DP_TX, "failed to find the peer by id %u\n", ts->peer_id); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return; } sta = peer->sta; @@ -546,7 +547,7 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, txrate.nss = arsta->last_txrate.nss; else txrate.nss = arsta->peer_nss; - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); switch (ts->pkt_type) { case HAL_TX_RATE_STATS_PKT_TYPE_11A: @@ -746,20 +747,20 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev, ath12k_wifi7_dp_tx_update_txcompl(dp_pdev, ts); - spin_lock_bh(&ab->base_lock); - peer = ath12k_dp_link_peer_find_by_id(ab, ts->peer_id); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_id(dp, ts->peer_id); if (!peer || !peer->sta) { ath12k_err(ab, "dp_tx: failed to find the peer with peer_id %d\n", ts->peer_id); - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu); goto exit; } ahsta = ath12k_sta_to_ahsta(peer->sta); arsta = &ahsta->deflink; - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); status.sta = peer->sta; status.info = info; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c index 0f1bdd5425dc..2767d6865d70 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c @@ -956,8 +956,9 @@ void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab) { u32 val; struct ath12k_hal *hal = &ab->hal; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); - lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&dp->dp_lock); val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR(hal)); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index a3ea42fc0933..80f499b5df35 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -116,15 +116,16 @@ ath12k_wifi7_is_frame_link_agnostic_wcn7850(struct ath12k_link_vif *arvif, struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); struct ath12k_hw *ah = ath12k_ar_to_ah(arvif->ar); struct ath12k_base *ab = arvif->ar->ab; + struct ath12k_dp *dp = ath12k_ab_to_dp(ab); __le16 fc = mgmt->frame_control; - spin_lock_bh(&ab->base_lock); - if (!ath12k_dp_link_peer_find_by_addr(ab, mgmt->da) && + spin_lock_bh(&dp->dp_lock); + if (!ath12k_dp_link_peer_find_by_addr(dp, mgmt->da) && !ath12k_peer_ml_find(ah, mgmt->da)) { - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); return false; } - spin_unlock_bh(&ab->base_lock); + spin_unlock_bh(&dp->dp_lock); if (vif->type == NL80211_IFTYPE_STATION) return arvif->is_up && -- 2.34.1 From: Harsh Kumar Bijlani There is a linked list of ath12k_dp_link_peer maintained in ath12k_dp. For link peer search based on mac address, there is iteration over the list wherein the mac address are compared for each entry in the list. This search operation is a costly operation considering the time complexity involved. In order to reduce the complexity, add hash table for ath12k_dp_link_peer in ath12k_dp where mac address of the link peer is used to derive the hash index. This hash table is lock protected by spinlock "dp_lock" present in ath12k_dp. This hash table is currently used for search of link peer using mac address for any interaction between control path and data path, per packet Rx monitor path and regular multicast Tx path. Update API ath12k_dp_link_peer_find_by_addr() to make use of the hash table for search operation using mac address, while other search APIs still rely on linked list. ath11k driver has been taken as reference for implementation of hash table. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/dp.c | 14 ++- drivers/net/wireless/ath/ath12k/dp.h | 10 +- drivers/net/wireless/ath/ath12k/dp_peer.c | 138 ++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/dp_peer.h | 9 ++ drivers/net/wireless/ath/ath12k/mac.c | 2 + 5 files changed, 160 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index 40057df4cd66..676af752f069 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -1122,6 +1122,8 @@ static void ath12k_dp_cleanup(struct ath12k_base *ab) struct ath12k_dp *dp = ath12k_ab_to_dp(ab); int i; + ath12k_dp_link_peer_rhash_tbl_destroy(dp); + if (!dp->ab) return; @@ -1487,14 +1489,22 @@ static int ath12k_dp_setup(struct ath12k_base *ab) spin_lock_init(&dp->dp_lock); INIT_LIST_HEAD(&dp->peers); + mutex_init(&dp->link_peer_rhash_tbl_lock); + dp->reo_cmd_cache_flush_count = 0; dp->idle_link_rbm = ath12k_hal_get_idle_link_rbm(&ab->hal, ab->device_id); + ret = ath12k_dp_link_peer_rhash_tbl_init(dp); + if (ret) { + ath12k_warn(ab, "failed to init link_peer rhash table: %d\n", ret); + return ret; + } + ret = ath12k_wbm_idle_ring_setup(ab, &n_link_desc); if (ret) { ath12k_warn(ab, "failed to setup wbm_idle_ring: %d\n", ret); - return ret; + goto rhash_destroy; } srng = &ab->hal.srng_list[dp->wbm_idle_ring.ring_id]; @@ -1575,6 +1585,8 @@ static int ath12k_dp_setup(struct ath12k_base *ab) fail_link_desc_cleanup: ath12k_dp_link_desc_cleanup(ab, dp->link_desc_banks, HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring); +rhash_destroy: + ath12k_dp_link_peer_rhash_tbl_destroy(dp); return ret; } diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index fc87b749a040..b90725094111 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -10,6 +10,7 @@ #include "hw.h" #include "dp_htt.h" #include "dp_cmn.h" +#include #define MAX_RXDMA_PER_PDEV 2 @@ -471,13 +472,20 @@ struct ath12k_dp { struct ath12k_hw_group *ag; u8 device_id; - /* Lock for protection of peers */ + /* Lock for protection of peers and rhead_peer_addr */ spinlock_t dp_lock; struct ath12k_dp_arch_ops *ops; /* Linked list of struct ath12k_dp_link_peer */ struct list_head peers; + + /* For rhash table init and deinit protection */ + struct mutex link_peer_rhash_tbl_lock; + + /* The rhashtable containing struct ath12k_link_peer keyed by mac addr */ + struct rhashtable *rhead_peer_addr; + struct rhashtable_params rhash_peer_addr_param; }; static inline void ath12k_dp_get_mac_addr(u32 addr_l32, u16 addr_h16, u8 *addr) diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 0267f68f8573..0cf28791568e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -51,18 +51,10 @@ ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_dp *dp, u8 pdev_idx, struct ath12k_dp_link_peer * ath12k_dp_link_peer_find_by_addr(struct ath12k_dp *dp, const u8 *addr) { - struct ath12k_dp_link_peer *peer; - lockdep_assert_held(&dp->dp_lock); - list_for_each_entry(peer, &dp->peers, list) { - if (!ether_addr_equal(peer->addr, addr)) - continue; - - return peer; - } - - return NULL; + return rhashtable_lookup_fast(dp->rhead_peer_addr, addr, + dp->rhash_peer_addr_param); } EXPORT_SYMBOL(ath12k_dp_link_peer_find_by_addr); @@ -147,6 +139,7 @@ void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", peer->vdev_id, peer->addr, peer_id); + ath12k_dp_link_peer_rhash_delete(dp, peer); list_del(&peer->list); kfree(peer); wake_up(&ab->peer_mapping_wq); @@ -160,6 +153,7 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ { struct ath12k_dp_link_peer *peer; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + int ret; spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, mac_addr); @@ -173,7 +167,11 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ peer->ast_hash = ast_hash; peer->hw_peer_id = hw_peer_id; ether_addr_copy(peer->addr, mac_addr); - list_add(&peer->list, &dp->peers); + ret = ath12k_dp_link_peer_rhash_add(dp, peer); + if (!ret) + list_add(&peer->list, &dp->peers); + else + kfree(peer); wake_up(&ab->peer_mapping_wq); } @@ -209,3 +207,121 @@ struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, } return arsta; } + +static int ath12k_dp_link_peer_rhash_addr_tbl_init(struct ath12k_dp *dp) +{ + struct ath12k_base *ab = dp->ab; + struct rhashtable_params *param; + struct rhashtable *rhash_addr_tbl; + int ret; + + lockdep_assert_held(&dp->link_peer_rhash_tbl_lock); + + rhash_addr_tbl = kzalloc(sizeof(*dp->rhead_peer_addr), GFP_KERNEL); + if (!rhash_addr_tbl) + return -ENOMEM; + + param = &dp->rhash_peer_addr_param; + + param->key_offset = offsetof(struct ath12k_dp_link_peer, addr); + param->head_offset = offsetof(struct ath12k_dp_link_peer, rhash_addr); + param->key_len = sizeof_field(struct ath12k_dp_link_peer, addr); + param->automatic_shrinking = true; + param->nelem_hint = ab->num_radios * ath12k_core_get_max_peers_per_radio(ab); + + ret = rhashtable_init(rhash_addr_tbl, param); + if (ret) { + ath12k_warn(ab, "failed to init peer addr rhash table %d\n", ret); + goto err_free; + } + + dp->rhead_peer_addr = rhash_addr_tbl; + + return 0; + +err_free: + kfree(rhash_addr_tbl); + + return ret; +} + +int ath12k_dp_link_peer_rhash_tbl_init(struct ath12k_dp *dp) +{ + int ret; + + mutex_lock(&dp->link_peer_rhash_tbl_lock); + ret = ath12k_dp_link_peer_rhash_addr_tbl_init(dp); + mutex_unlock(&dp->link_peer_rhash_tbl_lock); + + return ret; +} + +void ath12k_dp_link_peer_rhash_tbl_destroy(struct ath12k_dp *dp) +{ + mutex_lock(&dp->link_peer_rhash_tbl_lock); + rhashtable_destroy(dp->rhead_peer_addr); + kfree(dp->rhead_peer_addr); + dp->rhead_peer_addr = NULL; + mutex_unlock(&dp->link_peer_rhash_tbl_lock); +} + +static int ath12k_dp_link_peer_rhash_insert(struct ath12k_dp *dp, + struct ath12k_dp_link_peer *peer) +{ + struct ath12k_dp_link_peer *tmp; + + lockdep_assert_held(&dp->dp_lock); + + tmp = rhashtable_lookup_get_insert_fast(dp->rhead_peer_addr, &peer->rhash_addr, + dp->rhash_peer_addr_param); + if (!tmp) + return 0; + else if (IS_ERR(tmp)) + return PTR_ERR(tmp); + else + return -EEXIST; +} + +static int ath12k_dp_link_peer_rhash_remove(struct ath12k_dp *dp, + struct ath12k_dp_link_peer *peer) +{ + int ret; + + lockdep_assert_held(&dp->dp_lock); + + ret = rhashtable_remove_fast(dp->rhead_peer_addr, &peer->rhash_addr, + dp->rhash_peer_addr_param); + if (ret && ret != -ENOENT) + return ret; + + return 0; +} + +int ath12k_dp_link_peer_rhash_add(struct ath12k_dp *dp, + struct ath12k_dp_link_peer *peer) +{ + int ret; + + lockdep_assert_held(&dp->dp_lock); + + ret = ath12k_dp_link_peer_rhash_insert(dp, peer); + if (ret) + ath12k_warn(dp, "failed to add peer %pM with id %d in rhash_addr ret %d\n", + peer->addr, peer->peer_id, ret); + + return ret; +} + +void ath12k_dp_link_peer_rhash_delete(struct ath12k_dp *dp, + struct ath12k_dp_link_peer *peer) +{ + /* No failure handling and hence return type is void */ + int ret; + + lockdep_assert_held(&dp->dp_lock); + + ret = ath12k_dp_link_peer_rhash_remove(dp, peer); + if (ret) + ath12k_warn(dp, "failed to remove peer %pM with id %d in rhash_addr ret %d\n", + peer->addr, peer->peer_id, ret); +} diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index ecc90df05b44..b94a9a5cb311 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -63,6 +63,9 @@ struct ath12k_dp_link_peer { /* for reference to ath12k_link_sta */ u8 link_id; bool ucast_ra_only; + + /* peer addr based rhashtable list pointer */ + struct rhash_head rhash_addr; }; void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); @@ -83,4 +86,10 @@ ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_dp *dp, u8 pdev_idx, const u8 *addr); struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, struct ath12k_dp_link_peer *peer); +int ath12k_dp_link_peer_rhash_tbl_init(struct ath12k_dp *dp); +void ath12k_dp_link_peer_rhash_tbl_destroy(struct ath12k_dp *dp); +int ath12k_dp_link_peer_rhash_add(struct ath12k_dp *dp, + struct ath12k_dp_link_peer *peer); +void ath12k_dp_link_peer_rhash_delete(struct ath12k_dp *dp, + struct ath12k_dp_link_peer *peer); #endif diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index fd6819ec390c..c7eeaf586b83 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1188,6 +1188,8 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) if (peer->sta) ath12k_dp_rx_peer_tid_cleanup(ar, peer); + ath12k_dp_link_peer_rhash_delete(dp, peer); + list_del(&peer->list); kfree(peer); } -- 2.34.1 From: Harsh Kumar Bijlani Define the structure of ath12k_dp_peer and also define APIs for creation and deletion of ath12k_dp_peer based on STA state, as the ath12k_dp_peer is intended to be used in the subsequent set of patches. Maintain ath12k_dp_peer in a linked list in ath12k_dp_hw (which is a datapath component of ath12k_hw) and protect this list using spinlock "peer_lock". Store peer id based table (array of RCU pointers) of ath12k_dp_peer in ath12k_dp_hw. Use this peer id table to refer in the per packet Tx and Rx paths as it provides faster access to ath12k_dp_peer in comparison to linked list iterative search using peer id or mac address. Add support to handle deletion of ath12k_dp_peer in case of core reset. This patch is adding and deleting ath12k_dp_peer created for MLO STA to the above mentioned RCU pointer table. Addition and deletion of ath12k_dp_peer for non-MLO STA to RCU pointer table is handled in the subsequent following patch. Structure ath12k_ml_peer is created and deleted for MLO peers at the time of connect and disconnect and there is no other use case of it. With the above design in place for ath12k_dp_peer, ath12k_ml_peer becomes redundant. Hence, remove the structure ath12k_ml_peer and the list "ml_peers" present in ath12k_hw maintaining linked list of ath12k_ml_peer. APIs removed: - ath12k_peer_ml_find() - ath12k_peer_ml_create() - ath12k_peer_ml_delete() Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/core.c | 1 + drivers/net/wireless/ath/ath12k/core.h | 3 +- drivers/net/wireless/ath/ath12k/dp_cmn.h | 22 ++++ drivers/net/wireless/ath/ath12k/dp_peer.c | 126 +++++++++++++++++++++ drivers/net/wireless/ath/ath12k/dp_peer.h | 24 ++++ drivers/net/wireless/ath/ath12k/mac.c | 115 +++++++++++++++++-- drivers/net/wireless/ath/ath12k/mac.h | 1 + drivers/net/wireless/ath/ath12k/peer.c | 81 +------------ drivers/net/wireless/ath/ath12k/peer.h | 9 +- drivers/net/wireless/ath/ath12k/wifi7/hw.c | 14 ++- 10 files changed, 291 insertions(+), 105 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 2e093029c782..3bba9c9a1a9b 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1576,6 +1576,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab) ath12k_core_halt(ar); } + ath12k_mac_dp_peer_cleanup(ah); break; case ATH12K_HW_STATE_OFF: ath12k_warn(ab, diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index eb406fc9ab71..6dc4498749c3 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -836,8 +836,7 @@ struct ath12k_hw { DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS); - /* protected by wiphy_lock() */ - struct list_head ml_peers; + struct ath12k_dp_hw dp_hw; /* Keep last */ struct ath12k radio[] __aligned(sizeof(void *)); diff --git a/drivers/net/wireless/ath/ath12k/dp_cmn.h b/drivers/net/wireless/ath/ath12k/dp_cmn.h index 243fb5a68016..52b7fa2eb138 100644 --- a/drivers/net/wireless/ath/ath12k/dp_cmn.h +++ b/drivers/net/wireless/ath/ath12k/dp_cmn.h @@ -10,6 +10,21 @@ struct ath12k_hw_group; +/* + * ML Peer IDs start from 8192, assuming max SLO clients count 1536, + * then max peer id shall be 9728, therefore rounding the peer table size + * to the nearest next power of 2 i.e 16384. + */ +#define MAX_DP_PEER_LIST_SIZE 16384 + +struct ath12k_dp_hw { + struct ath12k_dp_peer __rcu *dp_peers[MAX_DP_PEER_LIST_SIZE]; + + /* Lock for protection of dp_peer_list and peers */ + spinlock_t peer_lock; + struct list_head dp_peers_list; +}; + struct ath12k_dp_hw_group { struct ath12k_dp *dp[ATH12K_MAX_DEVICES]; }; @@ -52,6 +67,13 @@ struct ath12k_per_peer_tx_stats { bool is_ampdu; }; +struct ath12k_dp_peer_create_params { + struct ieee80211_sta *sta; + bool is_mlo; + u16 peer_id; + bool ucast_ra_only; +}; + static inline struct ath12k_dp_link_vif * ath12k_dp_vif_to_dp_link_vif(struct ath12k_dp_vif *dp_vif, u8 link_id) { diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 0cf28791568e..a2834d043dd5 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -325,3 +325,129 @@ void ath12k_dp_link_peer_rhash_delete(struct ath12k_dp *dp, ath12k_warn(dp, "failed to remove peer %pM with id %d in rhash_addr ret %d\n", peer->addr, peer->peer_id, ret); } + +struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr(struct ath12k_dp_hw *dp_hw, u8 *addr) +{ + struct ath12k_dp_peer *peer; + + lockdep_assert_held(&dp_hw->peer_lock); + + list_for_each_entry(peer, &dp_hw->dp_peers_list, list) { + if (ether_addr_equal(peer->addr, addr)) + return peer; + } + + return NULL; +} +EXPORT_SYMBOL(ath12k_dp_peer_find_by_addr); + +struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr_and_sta(struct ath12k_dp_hw *dp_hw, + u8 *addr, + struct ieee80211_sta *sta) +{ + struct ath12k_dp_peer *dp_peer; + + lockdep_assert_held(&dp_hw->peer_lock); + + list_for_each_entry(dp_peer, &dp_hw->dp_peers_list, list) { + if (ether_addr_equal(dp_peer->addr, addr) && (dp_peer->sta == sta)) + return dp_peer; + } + + return NULL; +} + +static struct ath12k_dp_peer *ath12k_dp_peer_create_find(struct ath12k_dp_hw *dp_hw, + u8 *addr, + struct ieee80211_sta *sta, + bool mlo_peer) +{ + struct ath12k_dp_peer *dp_peer; + + lockdep_assert_held(&dp_hw->peer_lock); + + list_for_each_entry(dp_peer, &dp_hw->dp_peers_list, list) { + if (ether_addr_equal(dp_peer->addr, addr)) { + if (!sta || mlo_peer || dp_peer->is_mlo || + dp_peer->sta == sta) + return dp_peer; + } + } + + return NULL; +} + +int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr, + struct ath12k_dp_peer_create_params *params) +{ + struct ath12k_dp_peer *dp_peer; + + spin_lock_bh(&dp_hw->peer_lock); + dp_peer = ath12k_dp_peer_create_find(dp_hw, addr, params->sta, params->is_mlo); + if (dp_peer) { + spin_unlock_bh(&dp_hw->peer_lock); + return -EEXIST; + } + spin_unlock_bh(&dp_hw->peer_lock); + + dp_peer = kzalloc(sizeof(*dp_peer), GFP_ATOMIC); + if (!dp_peer) + return -ENOMEM; + + ether_addr_copy(dp_peer->addr, addr); + dp_peer->sta = params->sta; + dp_peer->is_mlo = params->is_mlo; + + /* + * For MLO client, the host assigns the ML peer ID, so set peer_id in dp_peer + * For non-MLO client, host gets link peer ID from firmware and will be + * assigned at the time of link peer creation + */ + dp_peer->peer_id = params->is_mlo ? params->peer_id : ATH12K_DP_PEER_ID_INVALID; + dp_peer->ucast_ra_only = params->ucast_ra_only; + + dp_peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; + dp_peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; + + spin_lock_bh(&dp_hw->peer_lock); + + list_add(&dp_peer->list, &dp_hw->dp_peers_list); + + /* + * For MLO client, the peer_id for ath12k_dp_peer is allocated by host + * and that peer_id is known at this point, and hence this ath12k_dp_peer + * can be added to the RCU table using the peer_id. + * For non-MLO client, this addition to RCU table shall be done at the + * time of assignment of ath12k_dp_link_peer to ath12k_dp_peer. + */ + if (dp_peer->is_mlo) + rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], dp_peer); + + spin_unlock_bh(&dp_hw->peer_lock); + + return 0; +} + +void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr, + struct ieee80211_sta *sta) +{ + struct ath12k_dp_peer *dp_peer; + + spin_lock_bh(&dp_hw->peer_lock); + + dp_peer = ath12k_dp_peer_find_by_addr_and_sta(dp_hw, addr, sta); + if (!dp_peer) { + spin_unlock_bh(&dp_hw->peer_lock); + return; + } + + if (dp_peer->is_mlo) + rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL); + + list_del(&dp_peer->list); + + spin_unlock_bh(&dp_hw->peer_lock); + + synchronize_rcu(); + kfree(dp_peer); +} diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index b94a9a5cb311..b4aa4f09337e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -9,6 +9,8 @@ #include "dp_rx.h" +#define ATH12K_DP_PEER_ID_INVALID 0x3FFF + struct ppdu_user_delayba { u16 sw_peer_id; u32 info0; @@ -71,6 +73,20 @@ struct ath12k_dp_link_peer { void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); + +struct ath12k_dp_peer { + struct list_head list; + struct ieee80211_sta *sta; + int peer_id; + u8 addr[ETH_ALEN]; + bool is_mlo; + + u16 sec_type; + u16 sec_type_grp; + + bool ucast_ra_only; +}; + struct ath12k_dp_link_peer * ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp, int vdev_id, const u8 *addr); @@ -92,4 +108,12 @@ int ath12k_dp_link_peer_rhash_add(struct ath12k_dp *dp, struct ath12k_dp_link_peer *peer); void ath12k_dp_link_peer_rhash_delete(struct ath12k_dp *dp, struct ath12k_dp_link_peer *peer); +int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr, + struct ath12k_dp_peer_create_params *params); +void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr, + struct ieee80211_sta *sta); +struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr(struct ath12k_dp_hw *dp_hw, u8 *addr); +struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr_and_sta(struct ath12k_dp_hw *dp_hw, + u8 *addr, + struct ieee80211_sta *sta); #endif diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index c7eeaf586b83..42fbfb13f23f 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1179,6 +1179,8 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) struct ath12k_dp_link_peer *peer, *tmp; struct ath12k_base *ab = ar->ab; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + struct ath12k_link_vif *arvif, *tmp_vif; + struct ath12k_dp_hw *dp_hw = &ar->ah->dp_hw; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -1201,6 +1203,42 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) /* Cleanup rhash table maintained for arsta by iterating over sta */ ieee80211_iterate_stations_mtx(ar->ah->hw, ath12k_mac_link_sta_rhash_cleanup, ar); + + /* Delete all the self dp_peers on asserted radio */ + list_for_each_entry_safe_reverse(arvif, tmp_vif, &ar->arvifs, list) { + if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + ath12k_dp_peer_delete(dp_hw, arvif->bssid, NULL); + arvif->num_stations = 0; + } + } +} + +void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah) +{ + struct list_head peers; + struct ath12k_dp_peer *dp_peer, *tmp; + struct ath12k_dp_hw *dp_hw = &ah->dp_hw; + + INIT_LIST_HEAD(&peers); + + spin_lock_bh(&dp_hw->peer_lock); + list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) { + if (dp_peer->is_mlo) { + rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL); + clear_bit(dp_peer->peer_id, ah->free_ml_peer_id_map); + } + + list_move(&dp_peer->list, &peers); + } + + spin_unlock_bh(&dp_hw->peer_lock); + + synchronize_rcu(); + + list_for_each_entry_safe(dp_peer, tmp, &peers, list) { + list_del(&dp_peer->list); + kfree(dp_peer); + } } static int ath12k_mac_vdev_setup_sync(struct ath12k *ar) @@ -3969,6 +4007,8 @@ static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, if (ret) ath12k_warn(ar->ab, "failed to submit AP self-peer removal on vdev %d link id %d: %d", arvif->vdev_id, arvif->link_id, ret); + + ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL); } ath12k_mac_vdev_delete(ar, arvif); } @@ -6625,7 +6665,10 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif, ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id); } - ath12k_peer_ml_delete(ah, sta); + if (sta->mlo) { + clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map); + ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; + } } static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw, @@ -7064,7 +7107,8 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, u16 selected_links = 0; u8 link_id = 0, i; struct ath12k *ar; - int ret; + int ret = -EINVAL; + struct ath12k_dp_peer_create_params dp_params = {}; lockdep_assert_wiphy(hw->wiphy); @@ -7087,12 +7131,28 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, /* ML sta */ if (sta->mlo && !ahsta->links_map && (hweight16(sta->valid_links) == 1)) { - ret = ath12k_peer_ml_create(ah, sta); - if (ret) { - ath12k_hw_warn(ah, "unable to create ML peer for sta %pM", + ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah); + if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { + ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM", sta->addr); goto exit; } + + dp_params.is_mlo = true; + dp_params.peer_id = ahsta->ml_peer_id | ATH12K_PEER_ML_ID_VALID; + } + + dp_params.sta = sta; + + if (vif->type == NL80211_IFTYPE_AP) + dp_params.ucast_ra_only = true; + + ret = ath12k_dp_peer_create(&ah->dp_hw, sta->addr, &dp_params); + if (ret) { + ath12k_hw_warn(ah, "unable to create ath12k_dp_peer for sta %pM, ret: %d", + sta->addr, ret); + + goto ml_peer_id_clear; } ret = ath12k_mac_assign_link_sta(ah, ahsta, arsta, ahvif, @@ -7100,7 +7160,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, if (ret) { ath12k_hw_warn(ah, "unable assign link %d for sta %pM", link_id, sta->addr); - goto exit; + goto peer_delete; } /* above arsta will get memset, hence do this after assign @@ -7170,7 +7230,12 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, if (ret) { ath12k_hw_warn(ah, "unable to move link sta %d of sta %pM from state %d to %d", link_id, arsta->addr, old_state, new_state); - goto exit; + + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) + goto peer_delete; + else + goto exit; } } @@ -7198,11 +7263,23 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, * handler below */ if (old_state == IEEE80211_STA_NONE && - new_state == IEEE80211_STA_NOTEXIST && sta->mlo) - ath12k_mac_ml_station_remove(ahvif, ahsta); + new_state == IEEE80211_STA_NOTEXIST) { + if (sta->mlo) + ath12k_mac_ml_station_remove(ahvif, ahsta); + + ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta); + } ret = 0; + goto exit; +peer_delete: + ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta); +ml_peer_id_clear: + if (sta->mlo) { + clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map); + ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; + } exit: /* update the state if everything went well */ if (!ret) @@ -9827,6 +9904,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) int ret, vdev_id; u8 link_id; struct ath12k_dp_link_vif *dp_link_vif = NULL; + struct ath12k_dp_peer_create_params params = {}; lockdep_assert_wiphy(hw->wiphy); @@ -9910,6 +9988,15 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) switch (ahvif->vdev_type) { case WMI_VDEV_TYPE_AP: + params.ucast_ra_only = true; + + ret = ath12k_dp_peer_create(&ah->dp_hw, arvif->bssid, ¶ms); + if (ret) { + ath12k_warn(ab, "failed to vdev %d create dp_peer for AP: %d\n", + arvif->vdev_id, ret); + goto err_vdev_del; + } + peer_param.vdev_id = arvif->vdev_id; peer_param.peer_addr = arvif->bssid; peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; @@ -9917,7 +10004,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) if (ret) { ath12k_warn(ab, "failed to vdev %d create peer for AP: %d\n", arvif->vdev_id, ret); - goto err_vdev_del; + goto err_dp_peer_del; } ret = ath12k_mac_set_kickout(arvif); @@ -10022,6 +10109,10 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) ar->num_peers--; } +err_dp_peer_del: + if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) + ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL); + err_vdev_del: if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ar->monitor_vdev_id = -1; @@ -14349,7 +14440,9 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag, ah->num_radio = num_pdev_map; mutex_init(&ah->hw_mutex); - INIT_LIST_HEAD(&ah->ml_peers); + + spin_lock_init(&ah->dp_hw.peer_lock); + INIT_LIST_HEAD(&ah->dp_hw.dp_peers_list); for (i = 0; i < num_pdev_map; i++) { ab = pdev_map[i].ab; diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 107ce6da2f64..f785a81860ce 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -157,6 +157,7 @@ struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id) void ath12k_mac_drain_tx(struct ath12k *ar); void ath12k_mac_peer_cleanup_all(struct ath12k *ar); +void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah); int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); enum rate_info_bw ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw); enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw); diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 68eebaa24ed9..691314efe23f 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -8,23 +8,6 @@ #include "peer.h" #include "debug.h" -struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr) -{ - struct ath12k_ml_peer *ml_peer; - - lockdep_assert_wiphy(ah->hw->wiphy); - - list_for_each_entry(ml_peer, &ah->ml_peers, list) { - if (!ether_addr_equal(ml_peer->addr, addr)) - continue; - - return ml_peer; - } - - return NULL; -} -EXPORT_SYMBOL(ath12k_peer_ml_find); - static int ath12k_wait_for_dp_link_peer_common(struct ath12k_base *ab, int vdev_id, const u8 *addr, bool expect_mapped) { @@ -263,7 +246,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, return 0; } -static u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah) +u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah) { u16 ml_peer_id; @@ -283,68 +266,6 @@ static u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah) return ml_peer_id; } -int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta) -{ - struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); - struct ath12k_ml_peer *ml_peer; - - lockdep_assert_wiphy(ah->hw->wiphy); - - if (!sta->mlo) - return -EINVAL; - - ml_peer = ath12k_peer_ml_find(ah, sta->addr); - if (ml_peer) { - ath12k_hw_warn(ah, "ML peer %d exists already, unable to add new entry for %pM", - ml_peer->id, sta->addr); - return -EEXIST; - } - - ml_peer = kzalloc(sizeof(*ml_peer), GFP_ATOMIC); - if (!ml_peer) - return -ENOMEM; - - ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah); - - if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { - ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM", - sta->addr); - kfree(ml_peer); - return -ENOMEM; - } - - ether_addr_copy(ml_peer->addr, sta->addr); - ml_peer->id = ahsta->ml_peer_id; - list_add(&ml_peer->list, &ah->ml_peers); - - return 0; -} - -int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta) -{ - struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); - struct ath12k_ml_peer *ml_peer; - - lockdep_assert_wiphy(ah->hw->wiphy); - - if (!sta->mlo) - return -EINVAL; - - clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map); - ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; - - ml_peer = ath12k_peer_ml_find(ah, sta->addr); - if (!ml_peer) { - ath12k_hw_warn(ah, "ML peer for %pM not found", sta->addr); - return -EINVAL; - } - - list_del(&ml_peer->list); - kfree(ml_peer); - - return 0; -} - int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta) { struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta); diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h index cf8a463d4c37..49d89796bc46 100644 --- a/drivers/net/wireless/ath/ath12k/peer.h +++ b/drivers/net/wireless/ath/ath12k/peer.h @@ -9,12 +9,6 @@ #include "dp_peer.h" -struct ath12k_ml_peer { - struct list_head list; - u8 addr[ETH_ALEN]; - u16 id; -}; - void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id); int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr); int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, @@ -22,8 +16,6 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ath12k_wmi_peer_create_arg *arg); int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, const u8 *addr); -int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta); -int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta); int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr); @@ -33,4 +25,5 @@ void ath12k_link_sta_rhash_delete(struct ath12k_base *ab, struct ath12k_link_sta int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *arsta); struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab, const u8 *addr); +u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah); #endif /* _PEER_H_ */ diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index 80f499b5df35..946771b96fb5 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -117,13 +117,19 @@ ath12k_wifi7_is_frame_link_agnostic_wcn7850(struct ath12k_link_vif *arvif, struct ath12k_hw *ah = ath12k_ar_to_ah(arvif->ar); struct ath12k_base *ab = arvif->ar->ab; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + struct ath12k_dp_peer *peer; __le16 fc = mgmt->frame_control; spin_lock_bh(&dp->dp_lock); - if (!ath12k_dp_link_peer_find_by_addr(dp, mgmt->da) && - !ath12k_peer_ml_find(ah, mgmt->da)) { - spin_unlock_bh(&dp->dp_lock); - return false; + if (!ath12k_dp_link_peer_find_by_addr(dp, mgmt->da)) { + spin_lock_bh(&ah->dp_hw.peer_lock); + peer = ath12k_dp_peer_find_by_addr(&ah->dp_hw, mgmt->da); + if (!peer || (peer && !peer->is_mlo)) { + spin_unlock_bh(&ah->dp_hw.peer_lock); + spin_unlock_bh(&dp->dp_lock); + return false; + } + spin_unlock_bh(&ah->dp_hw.peer_lock); } spin_unlock_bh(&dp->dp_lock); -- 2.34.1 From: Harsh Kumar Bijlani Introduce explicit attach/detach of ath12k_dp_link_peer objects to their parent ath12k_dp_peer to formalize the data path station hierarchy: ath12k_dp_peer | |--> ath12k_dp_link_peer | |--> ath12k_dp_link_peer | |--> ath12k_dp_link_peer ath12k_dp_peer maintains an array of RCU-protected pointers "link_peers[ATH12K_NUM_MAX_LINKS]" to ath12k_dp_link_peer indexed by its protocol_link_id, and each ath12k_dp_link_peer holds a back pointer to its parent ath12k_dp_peer. Attach is performed after link peer creation, and detach occurs before link peer deletion. This ensures consistent lifetime management and safe concurrent access. ath12k_dp_peer also maintains an array "hw_links[ATH12K_GROUP_MAX_RADIO]" to store the mapping between hw_link_id and protocol_link_id for each of the ath12k_dp_link_peer. RCU locking/unlocking rules: - Readers must hold rcu_read_lock() and fetch the pointer with rcu_dereference(dp_peer->link[link_id]); drop with rcu_read_unlock() when done. - Writers publish with rcu_assign_pointer() and reclaim only after synchronize_rcu(). Handle the case of detachment of link peer from ath12k_dp_peer in case of core reset. Ensure the following order of locks to be followed for attach and detach: - Lock dp->dp_lock - Lock dp_hw->peer_lock - Unlock dp_hw->peer_lock - Unlock dp->dp_lock Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/dp.c | 1 + drivers/net/wireless/ath/ath12k/dp.h | 1 + drivers/net/wireless/ath/ath12k/dp_cmn.h | 6 +- drivers/net/wireless/ath/ath12k/dp_peer.c | 146 ++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/dp_peer.h | 7 ++ drivers/net/wireless/ath/ath12k/mac.c | 21 +++- drivers/net/wireless/ath/ath12k/peer.c | 17 ++- 7 files changed, 189 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index 676af752f069..e682c0cd18ad 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -887,6 +887,7 @@ int ath12k_dp_pdev_alloc(struct ath12k_base *ab) dp_pdev->hw = ar->ah->hw; dp_pdev->dp = dp; dp_pdev->hw_link_id = ar->hw_link_id; + dp_pdev->dp_hw = &ar->ah->dp_hw; ret = ath12k_dp_rx_pdev_alloc(ab, i); if (ret) { diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index b90725094111..1ffa3066ade5 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -158,6 +158,7 @@ struct ath12k_pdev_dp { struct ath12k_dp *dp; struct ieee80211_hw *hw; u8 hw_link_id; + struct ath12k_dp_hw *dp_hw; /* Protects ppdu stats */ spinlock_t ppdu_list_lock; diff --git a/drivers/net/wireless/ath/ath12k/dp_cmn.h b/drivers/net/wireless/ath/ath12k/dp_cmn.h index 52b7fa2eb138..dd10426bd12d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_cmn.h +++ b/drivers/net/wireless/ath/ath12k/dp_cmn.h @@ -86,5 +86,9 @@ void ath12k_dp_cmn_hw_group_unassign(struct ath12k_dp *dp, struct ath12k_hw_group *ag); void ath12k_dp_cmn_hw_group_assign(struct ath12k_dp *dp, struct ath12k_hw_group *ag); - +int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, + u8 vdev_id, struct ieee80211_sta *sta, u8 *addr, + u8 link_id, u32 hw_link_id); +void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, + u8 vdev_id, u8 *addr, u32 hw_link_id); #endif diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index a2834d043dd5..fe4748648a84 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -139,7 +139,6 @@ void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", peer->vdev_id, peer->addr, peer_id); - ath12k_dp_link_peer_rhash_delete(dp, peer); list_del(&peer->list); kfree(peer); wake_up(&ab->peer_mapping_wq); @@ -153,7 +152,6 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ { struct ath12k_dp_link_peer *peer; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); - int ret; spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, mac_addr); @@ -167,11 +165,7 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ peer->ast_hash = ast_hash; peer->hw_peer_id = hw_peer_id; ether_addr_copy(peer->addr, mac_addr); - ret = ath12k_dp_link_peer_rhash_add(dp, peer); - if (!ret) - list_add(&peer->list, &dp->peers); - else - kfree(peer); + list_add(&peer->list, &dp->peers); wake_up(&ab->peer_mapping_wq); } @@ -377,6 +371,23 @@ static struct ath12k_dp_peer *ath12k_dp_peer_create_find(struct ath12k_dp_hw *dp return NULL; } +/* + * Index of ath12k_dp_peer for MLO client is same as peer id of ath12k_dp_peer, + * while for ath12k_dp_link_peer(mlo and non-mlo) and ath12k_dp_peer for + * Non-MLO client it is derived as ((DEVICE_ID << 10) | (10 bits of peer id)). + * + * This is done because ml_peer_id and peer_id_table are at hw granularity, + * while link_peer_id is at device granularity, hence in order to avoid + * conflict this approach is followed. + */ +#define ATH12K_DP_PEER_TABLE_DEVICE_ID_SHIFT 10 + +u16 ath12k_dp_peer_get_peerid_index(struct ath12k_dp *dp, u16 peer_id) +{ + return (peer_id & ATH12K_PEER_ML_ID_VALID) ? peer_id : + ((dp->device_id << ATH12K_DP_PEER_TABLE_DEVICE_ID_SHIFT) | peer_id); +} + int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr, struct ath12k_dp_peer_create_params *params) { @@ -451,3 +462,124 @@ void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr, synchronize_rcu(); kfree(dp_peer); } + +int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, + u8 vdev_id, struct ieee80211_sta *sta, u8 *addr, + u8 link_id, u32 hw_link_id) +{ + struct ath12k_dp_peer *dp_peer; + struct ath12k_dp_link_peer *peer, *temp_peer; + u16 peerid_index; + int ret = -EINVAL; + u8 *dp_peer_mac = !sta ? addr : sta->addr; + + spin_lock_bh(&dp->dp_lock); + + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr); + if (!peer) { + ath12k_warn(dp, "failed to find dp_link_peer with mac %pM on vdev %u\n", + addr, vdev_id); + ret = -ENOENT; + goto err_peer; + } + + spin_lock_bh(&dp_hw->peer_lock); + + dp_peer = ath12k_dp_peer_find_by_addr_and_sta(dp_hw, dp_peer_mac, sta); + if (!dp_peer) { + ath12k_warn(dp, "failed to find dp_peer with mac %pM\n", dp_peer_mac); + ret = -ENOENT; + goto err_dp_peer; + } + + /* + * Set peer_id in dp_peer for non-mlo client, peer_id for mlo client is + * set during dp_peer create + */ + if (!dp_peer->is_mlo) + dp_peer->peer_id = peer->peer_id; + + peer->dp_peer = dp_peer; + peer->hw_link_id = hw_link_id; + + dp_peer->hw_links[peer->hw_link_id] = link_id; + + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer); + + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer); + + spin_unlock_bh(&dp_hw->peer_lock); + + /* + * In case of Split PHY and roaming scenario, pdev idx + * might differ but both the pdev will share same rhash + * table. In that case update the rhash table if link_peer is + * already present + */ + temp_peer = ath12k_dp_link_peer_find_by_addr(dp, addr); + if (temp_peer && temp_peer->hw_link_id != hw_link_id) + ath12k_dp_link_peer_rhash_delete(dp, temp_peer); + + ret = ath12k_dp_link_peer_rhash_add(dp, peer); + if (ret) { + /* + * If new entry addition failed, add back old entry + * If old entry addition also fails, then nothing + * can be done, simply proceed + */ + if (temp_peer) + ath12k_dp_link_peer_rhash_add(dp, temp_peer); + } + + spin_unlock_bh(&dp->dp_lock); + + return ret; + +err_dp_peer: + spin_unlock_bh(&dp_hw->peer_lock); + +err_peer: + spin_unlock_bh(&dp->dp_lock); + + return ret; +} + +void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, + u8 vdev_id, u8 *addr, u32 hw_link_id) +{ + struct ath12k_dp_peer *dp_peer; + struct ath12k_dp_link_peer *peer, *temp_peer; + u16 peerid_index; + + spin_lock_bh(&dp->dp_lock); + + peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr); + if (!peer || !peer->dp_peer) { + spin_unlock_bh(&dp->dp_lock); + return; + } + + spin_lock_bh(&dp_hw->peer_lock); + + dp_peer = peer->dp_peer; + dp_peer->hw_links[peer->hw_link_id] = 0; + + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); + + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + + spin_unlock_bh(&dp_hw->peer_lock); + + /* To handle roaming and split phy scenario */ + temp_peer = ath12k_dp_link_peer_find_by_addr(dp, addr); + if (temp_peer && temp_peer->hw_link_id == hw_link_id) + ath12k_dp_link_peer_rhash_delete(dp, peer); + + spin_unlock_bh(&dp->dp_lock); + + synchronize_rcu(); +} diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index b4aa4f09337e..36cce6620310 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -26,6 +26,7 @@ struct ppdu_user_delayba { struct ath12k_dp_link_peer { struct list_head list; struct ieee80211_sta *sta; + struct ath12k_dp_peer *dp_peer; int vdev_id; u8 addr[ETH_ALEN]; int peer_id; @@ -68,6 +69,8 @@ struct ath12k_dp_link_peer { /* peer addr based rhashtable list pointer */ struct rhash_head rhash_addr; + + u8 hw_link_id; }; void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); @@ -81,10 +84,13 @@ struct ath12k_dp_peer { u8 addr[ETH_ALEN]; bool is_mlo; + struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS]; + u16 sec_type; u16 sec_type_grp; bool ucast_ra_only; + u8 hw_links[ATH12K_GROUP_MAX_RADIO]; }; struct ath12k_dp_link_peer * @@ -116,4 +122,5 @@ struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr(struct ath12k_dp_hw *dp_hw, u struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr_and_sta(struct ath12k_dp_hw *dp_hw, u8 *addr, struct ieee80211_sta *sta); +u16 ath12k_dp_peer_get_peerid_index(struct ath12k_dp *dp, u16 peer_id); #endif diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 42fbfb13f23f..02168a857e0a 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1181,6 +1181,11 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) struct ath12k_dp *dp = ath12k_ab_to_dp(ab); struct ath12k_link_vif *arvif, *tmp_vif; struct ath12k_dp_hw *dp_hw = &ar->ah->dp_hw; + struct ath12k_dp_peer *dp_peer = NULL; + u16 peerid_index; + struct list_head peers; + + INIT_LIST_HEAD(&peers); lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -1190,12 +1195,26 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) if (peer->sta) ath12k_dp_rx_peer_tid_cleanup(ar, peer); + /* cleanup dp peer */ + spin_lock_bh(&dp_hw->peer_lock); + dp_peer = peer->dp_peer; + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + spin_unlock_bh(&dp_hw->peer_lock); + ath12k_dp_link_peer_rhash_delete(dp, peer); + list_move(&peer->list, &peers); + } + spin_unlock_bh(&dp->dp_lock); + + synchronize_rcu(); + + list_for_each_entry_safe(peer, tmp, &peers, list) { list_del(&peer->list); kfree(peer); } - spin_unlock_bh(&dp->dp_lock); ar->num_peers = 0; ar->num_stations = 0; diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 691314efe23f..8b6fea685a70 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -110,6 +110,10 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + ath12k_dp_link_peer_unassign(ath12k_ab_to_dp(ar->ab), + &(ath12k_ar_to_ah(ar)->dp_hw), vdev_id, + addr, ar->hw_link_id); + ret = ath12k_peer_delete_send(ar, vdev_id, addr); if (ret) return ret; @@ -243,7 +247,13 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, spin_unlock_bh(&dp->dp_lock); - return 0; + ret = ath12k_dp_link_peer_assign(ath12k_ab_to_dp(ar->ab), + &(ath12k_ar_to_ah(ar)->dp_hw), + arvif->vdev_id, sta, + (u8 *)arg->peer_addr, link_id, + ar->hw_link_id); + + return ret; } u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah) @@ -298,6 +308,11 @@ int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_st ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr); + ath12k_dp_link_peer_unassign(ath12k_ab_to_dp(ar->ab), + &(ath12k_ar_to_ah(ar)->dp_hw), + arvif->vdev_id, arsta->addr, + ar->hw_link_id); + ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr); if (ret) { ath12k_warn(ar->ab, -- 2.34.1 From: Harsh Kumar Bijlani Move link agnostic data path parameters (keys, rx_tid, reorder buffers, MIC context etc) from ath12k_sta and ath12k_dp_link_peer into ath12k_dp_peer. These parameters are shared across MLO links and should be managed at the peer level. Configure them only when the link peer is primary to avoid redundancy and ensure consistent setup. Switch per-packet Tx/Rx paths and monitor paths to look up ath12k_dp_peer and ath12k_dp_link_peer via peer_id. Helper APIs added: - ath12k_dp_peer_find_by_peerid() - ath12k_dp_link_peer_find_by_peerid() Ensure RCU read lock is held when using these helpers APIs. With the above API ath12k_dp_link_peer_find_by_peerid() being used to find ath12k_dp_link_peer, existing API ath12k_dp_link_peer_find_by_id() is required only at the time of unmap event from firmware since it fetches the ath12k_dp_link_peer from linked list. In order to restrict the usage of API ath12k_dp_link_peer_find_by_id(), make it static and also rename it to ath12k_dp_link_peer_search_by_id(). Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Harsh Kumar Bijlani Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/core.h | 8 --- drivers/net/wireless/ath/ath12k/dp.c | 6 +- drivers/net/wireless/ath/ath12k/dp_htt.c | 22 ++----- drivers/net/wireless/ath/ath12k/dp_mon.c | 13 +++-- drivers/net/wireless/ath/ath12k/dp_peer.c | 45 +++++++++++++- drivers/net/wireless/ath/ath12k/dp_peer.h | 45 +++++++------- drivers/net/wireless/ath/ath12k/dp_rx.c | 58 +++++++++++-------- drivers/net/wireless/ath/ath12k/dp_rx.h | 9 ++- drivers/net/wireless/ath/ath12k/mac.c | 54 +++++++++-------- drivers/net/wireless/ath/ath12k/peer.c | 6 -- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 30 +++++----- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 2 +- drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c | 23 +++----- .../net/wireless/ath/ath12k/wifi7/hal_rx.c | 2 + .../net/wireless/ath/ath12k/wifi7/hal_rx.h | 1 + 15 files changed, 175 insertions(+), 149 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 6dc4498749c3..bc1d94963251 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -566,12 +566,6 @@ struct ath12k_link_sta { struct rhash_head rhash_addr; }; -struct ath12k_reoq_buf { - void *vaddr; - dma_addr_t paddr_aligned; - u32 size; -}; - struct ath12k_sta { struct ath12k_vif *ahvif; enum hal_pn_type pn_type; @@ -584,8 +578,6 @@ struct ath12k_sta { u8 num_peer; enum ieee80211_sta_state state; - - struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1]; }; #define ATH12K_HALF_20MHZ_BW 10 diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index e682c0cd18ad..ff914c0e125f 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -30,7 +30,7 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr) spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr); - if (!peer) { + if (!peer || !peer->dp_peer) { ath12k_warn(ab, "failed to lookup peer %pM on vdev %d\n", addr, vdev_id); spin_unlock_bh(&dp->dp_lock); @@ -43,8 +43,8 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr) } ath12k_dp_rx_peer_tid_cleanup(ar, peer); - crypto_free_shash(peer->tfm_mmic); - peer->dp_setup_done = false; + crypto_free_shash(peer->dp_peer->tfm_mmic); + peer->dp_peer->dp_setup_done = false; spin_unlock_bh(&dp->dp_lock); } diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c index f3dca108c614..db5ac36adf3d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_htt.c +++ b/drivers/net/wireless/ath/ath12k/dp_htt.c @@ -272,18 +272,15 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, } rcu_read_lock(); - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, usr_stats->peer_id); + peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, usr_stats->peer_id); if (!peer || !peer->sta) { - spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); return; } arsta = ath12k_dp_link_peer_to_link_sta(ab, peer); if (!arsta) { - spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); return; } @@ -357,7 +354,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags); } - spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); } @@ -507,17 +503,13 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, ppdu_info->delay_ba) { for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) { peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id; - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); - if (!peer) { - spin_unlock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id); + if (!peer) continue; - } usr_stats = &ppdu_info->ppdu_stats.user_stats[i]; if (usr_stats->delay_ba) ath12k_copy_to_delay_stats(peer, usr_stats); - spin_unlock_bh(&dp->dp_lock); } } @@ -526,17 +518,13 @@ static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab, (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON))) { for (i = 0; i < ppdu_info->bar_num_users; i++) { peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id; - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); - if (!peer) { - spin_unlock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id); + if (!peer) continue; - } usr_stats = &ppdu_info->ppdu_stats.user_stats[i]; if (peer->delayba_flag) ath12k_copy_to_bar(peer, usr_stats); - spin_unlock_bh(&dp->dp_lock); } } diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c index f65ac12d7f2b..b9ccb5462e9d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c @@ -2275,6 +2275,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, bool is_mcbc = rxcb->is_mcbc; bool is_eapol_tkip = rxcb->is_eapol; struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data; + u8 addr[ETH_ALEN] = {}; status->link_valid = 0; @@ -2287,11 +2288,13 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, ath12k_wifi7_dp_extract_rx_desc_data(ab, &rx_info, rx_desc, rx_desc); + rcu_read_lock(); spin_lock_bh(&dp->dp_lock); rx_info.addr2_present = false; - peer = ath12k_dp_rx_h_find_link_peer(dp, msdu, &rx_info); + peer = ath12k_dp_rx_h_find_link_peer(dp_pdev, msdu, &rx_info); if (peer && peer->sta) { pubsta = peer->sta; + memcpy(addr, peer->addr, ETH_ALEN); if (pubsta->valid_links) { status->link_valid = 1; status->link_id = peer->link_id; @@ -2299,12 +2302,13 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, } spin_unlock_bh(&dp->dp_lock); + rcu_read_unlock(); ath12k_dbg(ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %u %s %s%s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", msdu, msdu->len, - peer ? peer->addr : NULL, + addr, rxcb->tid, (is_mcbc) ? "mcast" : "ucast", (status->encoding == RX_ENC_LEGACY) ? "legacy" : "", @@ -3885,8 +3889,7 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, goto free_skb; rcu_read_lock(); - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, ppdu_info->peer_id); + peer = ath12k_dp_link_peer_find_by_peerid(pdev_dp, ppdu_info->peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DATA, "failed to find the peer with monitor peer_id %d\n", @@ -3899,7 +3902,6 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, if (!arsta) { ath12k_warn(ab, "link sta not found on peer %pM id %d\n", peer->addr, peer->peer_id); - spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); dev_kfree_skb_any(skb); continue; @@ -3913,7 +3915,6 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget, } next_skb: - spin_unlock_bh(&dp->dp_lock); rcu_read_unlock(); free_skb: dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index fe4748648a84..61478e66d9af 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -72,8 +72,8 @@ ath12k_dp_link_peer_find_by_ml_id(struct ath12k_dp *dp, int ml_peer_id) return NULL; } -struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_id(struct ath12k_dp *dp, int peer_id) +static struct ath12k_dp_link_peer * +ath12k_dp_link_peer_search_by_id(struct ath12k_dp *dp, int peer_id) { struct ath12k_dp_link_peer *peer; @@ -129,7 +129,7 @@ void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); + peer = ath12k_dp_link_peer_search_by_id(dp, peer_id); if (!peer) { ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n", peer_id); @@ -388,6 +388,44 @@ u16 ath12k_dp_peer_get_peerid_index(struct ath12k_dp *dp, u16 peer_id) ((dp->device_id << ATH12K_DP_PEER_TABLE_DEVICE_ID_SHIFT) | peer_id); } +struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, + u16 peer_id) +{ + u16 index; + struct ath12k_dp *dp = dp_pdev->dp; + + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "ath12k dp peer find by peerid index called without rcu lock"); + + if (!peer_id || peer_id >= ATH12K_DP_PEER_ID_INVALID) + return NULL; + + index = ath12k_dp_peer_get_peerid_index(dp, peer_id); + + return rcu_dereference(dp_pdev->dp_hw->dp_peers[index]); +} + +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id) +{ + struct ath12k_dp_peer *dp_peer = NULL; + u8 link_id; + + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "ath12k dp link peer find by peerid index called without rcu lock"); + + if (dp_pdev->hw_link_id >= ATH12K_GROUP_MAX_RADIO) + return NULL; + + dp_peer = ath12k_dp_peer_find_by_peerid(dp_pdev, peer_id); + if (!dp_peer) + return NULL; + + link_id = dp_peer->hw_links[dp_pdev->hw_link_id]; + + return rcu_dereference(dp_peer->link_peers[link_id]); +} + int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr, struct ath12k_dp_peer_create_params *params) { @@ -419,6 +457,7 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr, dp_peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; dp_peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; + dp_peer->ucast_ra_only = params->ucast_ra_only; spin_lock_bh(&dp_hw->peer_lock); diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index 36cce6620310..f7c995e8c4e3 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -34,24 +34,11 @@ struct ath12k_dp_link_peer { u8 pdev_idx; u16 hw_peer_id; - /* protected by ab->data_lock */ - struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; - struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; - - /* Info used in MMIC verification of - * RX fragments - */ - struct crypto_shash *tfm_mmic; - u8 mcast_keyidx; - u8 ucast_keyidx; - u16 sec_type; - u16 sec_type_grp; struct ppdu_user_delayba ppdu_stats_delayba; bool delayba_flag; bool is_authorized; bool mlo; /* protected by ab->data_lock */ - bool dp_setup_done; u16 ml_id; @@ -65,12 +52,12 @@ struct ath12k_dp_link_peer { /* for reference to ath12k_link_sta */ u8 link_id; - bool ucast_ra_only; /* peer addr based rhashtable list pointer */ struct rhash_head rhash_addr; u8 hw_link_id; + u32 rx_tid_active_bitmask; }; void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); @@ -79,18 +66,28 @@ void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_ struct ath12k_dp_peer { struct list_head list; - struct ieee80211_sta *sta; - int peer_id; - u8 addr[ETH_ALEN]; bool is_mlo; + bool dp_setup_done; - struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS]; - - u16 sec_type; - u16 sec_type_grp; + u8 ucast_keyidx; + u8 addr[ETH_ALEN]; + u8 mcast_keyidx; bool ucast_ra_only; + int peer_id; + struct ieee80211_sta *sta; + u8 hw_links[ATH12K_GROUP_MAX_RADIO]; + + u16 sec_type_grp; + u16 sec_type; + + /* Info used in MMIC verification of * RX fragments */ + struct crypto_shash *tfm_mmic; + struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; + struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS]; + struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1]; + struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; }; struct ath12k_dp_link_peer * @@ -98,8 +95,6 @@ ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp, int vdev_id, const u8 *addr); struct ath12k_dp_link_peer * ath12k_dp_link_peer_find_by_addr(struct ath12k_dp *dp, const u8 *addr); -struct ath12k_dp_link_peer * -ath12k_dp_link_peer_find_by_id(struct ath12k_dp *dp, int peer_id); bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_dp *dp, int vdev_id); struct ath12k_dp_link_peer * ath12k_dp_link_peer_find_by_ast(struct ath12k_dp *dp, int ast_hash); @@ -123,4 +118,8 @@ struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr_and_sta(struct ath12k_dp_hw * u8 *addr, struct ieee80211_sta *sta); u16 ath12k_dp_peer_get_peerid_index(struct ath12k_dp *dp, u16 peer_id); +struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, + u16 peer_id); +struct ath12k_dp_link_peer * +ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id); #endif diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 08dc0345a2b2..12ad62b0ff5d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -481,8 +481,11 @@ void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer lockdep_assert_held(&dp->dp_lock); + if (!peer->primary_link) + return; + for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { - rx_tid = &peer->rx_tid[i]; + rx_tid = &peer->dp_peer->rx_tid[i]; ath12k_wifi7_dp_rx_peer_tid_delete(ar, peer, i); ath12k_dp_rx_frags_cleanup(rx_tid, true); @@ -500,7 +503,6 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ struct ath12k_base *ab = ar->ab; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); struct ath12k_dp_link_peer *peer; - struct ath12k_sta *ahsta; struct ath12k_dp_rx_tid *rx_tid; dma_addr_t paddr_aligned; int ret; @@ -508,7 +510,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer to set up rx tid\n"); return -ENOENT; @@ -534,9 +536,9 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ return -EINVAL; } - rx_tid = &peer->rx_tid[tid]; + rx_tid = &peer->dp_peer->rx_tid[tid]; /* Update the tid queue if it is already setup */ - if (rx_tid->active) { + if (peer->rx_tid_active_bitmask & (1 << tid)) { ret = ath12k_wifi7_peer_rx_tid_reo_update(ar, peer, rx_tid, ba_win_sz, ssn, true); spin_unlock_bh(&dp->dp_lock); @@ -565,14 +567,15 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ rx_tid->ba_win_sz = ba_win_sz; - ahsta = ath12k_sta_to_ahsta(peer->sta); - ret = ath12k_wifi7_dp_rx_assign_reoq(ab, ahsta, rx_tid, ssn, pn_type); + ret = ath12k_wifi7_dp_rx_assign_reoq(ab, peer->dp_peer, rx_tid, ssn, pn_type); if (ret) { spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to assign reoq buf for rx tid %u\n", tid); return ret; } + peer->rx_tid_active_bitmask |= (1 << tid); + paddr_aligned = rx_tid->qbuf.paddr_aligned; if (ab->hw_params->reoq_lut_support) { /* Update the REO queue LUT at the corresponding peer id @@ -649,20 +652,26 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, arsta->addr); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer to stop rx aggregation\n"); return -ENOENT; } - active = peer->rx_tid[params->tid].active; + if (ab->hw_params->dp_primary_link_only && + !peer->primary_link) { + spin_unlock_bh(&dp->dp_lock); + return 0; + } + active = peer->rx_tid_active_bitmask & (1 << params->tid); if (!active) { spin_unlock_bh(&dp->dp_lock); return 0; } - ret = ath12k_wifi7_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false); + ret = ath12k_wifi7_peer_rx_tid_reo_update(ar, peer, peer->dp_peer->rx_tid, + 1, 0, false); spin_unlock_bh(&dp->dp_lock); if (ret) { ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n", @@ -698,7 +707,7 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, peer_addr); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer %pM to configure pn replay detection\n", peer_addr); @@ -706,10 +715,11 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, } for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { - rx_tid = &peer->rx_tid[tid]; - if (!rx_tid->active) + if (!(peer->rx_tid_active_bitmask & (1 << tid))) continue; + rx_tid = &peer->dp_peer->rx_tid[tid]; + ath12k_wifi7_dp_setup_pn_check_reo_cmd(&cmd, rx_tid, key->cipher, key_cmd); ret = ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid, @@ -1043,16 +1053,17 @@ void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu } struct ath12k_dp_link_peer * -ath12k_dp_rx_h_find_link_peer(struct ath12k_dp *dp, struct sk_buff *msdu, +ath12k_dp_rx_h_find_link_peer(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu, struct hal_rx_desc_data *rx_info) { struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); struct ath12k_dp_link_peer *peer = NULL; + struct ath12k_dp *dp = dp_pdev->dp; lockdep_assert_held(&dp->dp_lock); if (rxcb->peer_id) - peer = ath12k_dp_link_peer_find_by_id(dp, rxcb->peer_id); + peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, rxcb->peer_id); if (peer) return peer; @@ -1201,25 +1212,22 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc struct ath12k_base *ab = dp->ab; struct ieee80211_rx_status *rx_status; struct ieee80211_sta *pubsta; - struct ath12k_dp_link_peer *peer; + struct ath12k_dp_peer *peer; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); struct ieee80211_rx_status *status = rx_info->rx_status; u8 decap = rx_info->decap_type; bool is_mcbc = rxcb->is_mcbc; bool is_eapol = rxcb->is_eapol; - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_rx_h_find_link_peer(dp, msdu, rx_info); + peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rx_info->peer_id); pubsta = peer ? peer->sta : NULL; if (pubsta && pubsta->valid_links) { status->link_valid = 1; - status->link_id = peer->link_id; + status->link_id = peer->hw_links[rxcb->hw_link_id]; } - spin_unlock_bh(&dp->dp_lock); - ath12k_dbg(ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", msdu, @@ -1342,7 +1350,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&dp->dp_lock); crypto_free_shash(tfm); ath12k_warn(ab, "failed to find the peer to set up fragment info\n"); @@ -1356,14 +1364,14 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev } for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { - rx_tid = &peer->rx_tid[i]; + rx_tid = &peer->dp_peer->rx_tid[i]; rx_tid->dp = dp; timer_setup(&rx_tid->frag_timer, ath12k_dp_rx_frag_timer, 0); skb_queue_head_init(&rx_tid->rx_frags); } - peer->tfm_mmic = tfm; - peer->dp_setup_done = true; + peer->dp_peer->tfm_mmic = tfm; + peer->dp_peer->dp_setup_done = true; spin_unlock_bh(&dp->dp_lock); return 0; diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h index 9b0334515c6e..1ad798fe1cb8 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/dp_rx.h @@ -12,10 +12,15 @@ #define DP_MAX_NWIFI_HDR_LEN 30 +struct ath12k_reoq_buf { + void *vaddr; + dma_addr_t paddr_aligned; + u32 size; +}; + struct ath12k_dp_rx_tid { u8 tid; u32 ba_win_sz; - bool active; struct ath12k_reoq_buf qbuf; /* Info related to rx fragments */ @@ -230,7 +235,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab, struct hal_rx_desc *desc); struct ath12k_dp_link_peer * -ath12k_dp_rx_h_find_link_peer(struct ath12k_dp *dp, struct sk_buff *msdu, +ath12k_dp_rx_h_find_link_peer(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu, struct hal_rx_desc_data *rx_info); u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab, struct hal_rx_desc *desc); diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 02168a857e0a..f55c207c4962 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1192,7 +1192,7 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) spin_lock_bh(&dp->dp_lock); list_for_each_entry_safe(peer, tmp, &dp->peers, list) { /* Skip Rx TID cleanup for self peer */ - if (peer->sta) + if (peer->sta && peer->dp_peer) ath12k_dp_rx_peer_tid_cleanup(ar, peer); /* cleanup dp peer */ @@ -5536,27 +5536,37 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, struct ath12k_dp_link_peer *peer; int first_errno = 0; int ret; - int i; + int i, len; u32 flags = 0; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1] = {}; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, addr); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&dp->dp_lock); return -ENOENT; } + len = ARRAY_SIZE(peer->dp_peer->keys); + for (i = 0; i < len; i++) { + if (!peer->dp_peer->keys[i]) + continue; + + keys[i] = peer->dp_peer->keys[i]; + peer->dp_peer->keys[i] = NULL; + } + spin_unlock_bh(&dp->dp_lock); - for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { - if (!peer->keys[i]) + for (i = 0; i < len; i++) { + if (!keys[i]) continue; /* key flags are not required to delete the key */ - ret = ath12k_install_key(arvif, peer->keys[i], + ret = ath12k_install_key(arvif, keys[i], DISABLE_KEY, addr, flags); if (ret < 0 && first_errno == 0) first_errno = ret; @@ -5564,10 +5574,6 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, if (ret < 0) ath12k_warn(ab, "failed to remove peer key %d: %d\n", i, ret); - - spin_lock_bh(&dp->dp_lock); - peer->keys[i] = NULL; - spin_unlock_bh(&dp->dp_lock); } return first_errno; @@ -5608,7 +5614,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, peer_addr); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&dp->dp_lock); if (cmd == SET_KEY) { @@ -5645,21 +5651,23 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, peer_addr); - if (peer && cmd == SET_KEY) { - peer->keys[key->keyidx] = key; + if (peer && peer->dp_peer && cmd == SET_KEY) { + peer->dp_peer->keys[key->keyidx] = key; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { - peer->ucast_keyidx = key->keyidx; - peer->sec_type = ath12k_dp_tx_get_encrypt_type(key->cipher); + peer->dp_peer->ucast_keyidx = key->keyidx; + peer->dp_peer->sec_type = + ath12k_dp_tx_get_encrypt_type(key->cipher); } else { - peer->mcast_keyidx = key->keyidx; - peer->sec_type_grp = ath12k_dp_tx_get_encrypt_type(key->cipher); + peer->dp_peer->mcast_keyidx = key->keyidx; + peer->dp_peer->sec_type_grp = + ath12k_dp_tx_get_encrypt_type(key->cipher); } - } else if (peer && cmd == DISABLE_KEY) { - peer->keys[key->keyidx] = NULL; + } else if (peer && peer->dp_peer && cmd == DISABLE_KEY) { + peer->dp_peer->keys[key->keyidx] = NULL; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) - peer->ucast_keyidx = 0; + peer->dp_peer->ucast_keyidx = 0; else - peer->mcast_keyidx = 0; + peer->dp_peer->mcast_keyidx = 0; } else if (!peer) /* impossible unless FW goes crazy */ ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr); @@ -9164,7 +9172,7 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, spin_lock_bh(&tmp_dp->dp_lock); peer = ath12k_dp_link_peer_find_by_addr(tmp_dp, tmp_arvif->bssid); - if (!peer) { + if (!peer || !peer->dp_peer) { spin_unlock_bh(&tmp_dp->dp_lock); ath12k_warn(tmp_ar->ab, "failed to find peer for vdev_id 0x%X addr %pM link_map 0x%X\n", @@ -9174,7 +9182,7 @@ void ath12k_mac_op_tx(struct ieee80211_hw *hw, continue; } - key = peer->keys[peer->mcast_keyidx]; + key = peer->dp_peer->keys[peer->dp_peer->mcast_keyidx]; if (key) { skb_cb->cipher = key->cipher; skb_cb->flags |= ATH12K_SKB_CIPHER_SET; diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 8b6fea685a70..812247decab4 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -214,9 +214,6 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, dp_link_vif->ast_idx = peer->hw_peer_id; } - if (vif->type == NL80211_IFTYPE_AP) - peer->ucast_ra_only = true; - if (sta) { ahsta = ath12k_sta_to_ahsta(sta); arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy, @@ -240,9 +237,6 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, } } - peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; - peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; - ar->num_peers++; spin_unlock_bh(&dp->dp_lock); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index da745566aca3..87875486fb4a 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -72,10 +72,10 @@ void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k *ar, struct ath12k_dp_link_peer *peer, u8 tid) { struct ath12k_hal_reo_cmd cmd = {}; - struct ath12k_dp_rx_tid *rx_tid = &peer->rx_tid[tid]; + struct ath12k_dp_rx_tid *rx_tid = &peer->dp_peer->rx_tid[tid]; int ret; - if (!rx_tid->active) + if (!(peer->rx_tid_active_bitmask & (1 << tid))) return; cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; @@ -99,7 +99,7 @@ void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k *ar, else ath12k_wifi7_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid); - rx_tid->active = false; + peer->rx_tid_active_bitmask &= ~(1 << tid); } int ath12k_wifi7_dp_rx_link_desc_return(struct ath12k_base *ab, @@ -253,7 +253,7 @@ void ath12k_wifi7_dp_reo_cache_flush(struct ath12k_base *ab, } } -int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_sta *ahsta, +int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_dp_peer *dp_peer, struct ath12k_dp_rx_tid *rx_tid, u16 ssn, enum hal_pn_type pn_type) { @@ -265,7 +265,7 @@ int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_sta *ah u32 hw_desc_sz; int ret; - buf = &ahsta->reoq_bufs[tid]; + buf = &dp_peer->reoq_bufs[tid]; if (!buf->vaddr) { /* TODO: Optimize the memory allocation for qos tid based on * the actual BA window size in REO tid update path. @@ -299,7 +299,6 @@ int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_sta *ah } rx_tid->qbuf = *buf; - rx_tid->active = true; return 0; } @@ -316,12 +315,11 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, struct hal_rx_desc *rx_desc, struct hal_rx_desc_data *rx_info) { - struct ath12k_dp *dp = dp_pdev->dp; struct ath12k_skb_rxcb *rxcb; enum hal_encrypt_type enctype; bool is_decrypted = false; struct ieee80211_hdr *hdr; - struct ath12k_dp_link_peer *peer; + struct ath12k_dp_peer *peer; struct ieee80211_rx_status *rx_status = rx_info->rx_status; u32 err_bitmap = rx_info->err_bitmap; @@ -332,8 +330,7 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, if (rxcb->is_mcbc) rxcb->peer_id = rx_info->peer_id; - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_rx_h_find_link_peer(dp, msdu, rx_info); + peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id); if (peer) { /* resetting mcbc bit because mcbc packets are unicast * packets only for AP as STA sends unicast packets. @@ -347,7 +344,6 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, } else { enctype = HAL_ENCRYPT_TYPE_OPEN; } - spin_unlock_bh(&dp->dp_lock); if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap) is_decrypted = rx_info->is_decrypted; @@ -964,7 +960,7 @@ static int ath12k_wifi7_dp_rx_h_defrag_reo_reinject(struct ath12k_dp *dp, } static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev, - struct ath12k_dp_link_peer *peer, + struct ath12k_dp_peer *peer, enum hal_encrypt_type enctype, struct sk_buff *msdu, struct hal_rx_desc_data *rx_info) @@ -1033,7 +1029,7 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev, } static int ath12k_wifi7_dp_rx_h_defrag(struct ath12k_pdev_dp *dp_pdev, - struct ath12k_dp_link_peer *peer, + struct ath12k_dp_peer *peer, struct ath12k_dp_rx_tid *rx_tid, struct sk_buff **defrag_skb, enum hal_encrypt_type enctype, @@ -1107,7 +1103,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, { struct ath12k_dp *dp = dp_pdev->dp; struct ath12k_base *ab = dp->ab; - struct ath12k_dp_link_peer *peer; + struct ath12k_dp_peer *peer; struct ath12k_dp_rx_tid *rx_tid; struct sk_buff *defrag_skb = NULL; u32 peer_id = rx_info->peer_id; @@ -1134,7 +1130,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, return -EINVAL; spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); + peer = ath12k_dp_peer_find_by_peerid(dp_pdev, peer_id); if (!peer) { ath12k_warn(ab, "failed to find the peer to de-fragment received fragment peer_id %d\n", peer_id); @@ -1197,7 +1193,7 @@ static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev, timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); + peer = ath12k_dp_peer_find_by_peerid(dp_pdev, peer_id); if (!peer) goto err_frags_cleanup; @@ -1831,6 +1827,8 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_base *ab, rxcb->is_last_msdu = err_info.last_msdu; rxcb->is_continuation = err_info.continuation; rxcb->rx_desc = msdu_data; + rxcb->peer_id = ath12k_dp_rx_get_peer_id(ab, dp->peer_metadata_ver, + err_info.peer_metadata); if (err_info.continuation) { __skb_queue_tail(&scatter_msdu_list, msdu); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h index f75588519cff..ba319ff506f2 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h @@ -25,7 +25,7 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab); void ath12k_wifi7_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd, struct ath12k_dp_rx_tid *rx_tid, u32 cipher, enum set_key_cmd key_cmd); -int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_sta *ahsta, +int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_dp_peer *dp_peer, struct ath12k_dp_rx_tid *rx_tid, u16 ssn, enum hal_pn_type pn_type); int ath12k_wifi7_dp_rx_link_desc_return(struct ath12k_base *ab, diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c index 77de02858677..950614a217a0 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c @@ -396,12 +396,13 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, s32 noise_floor; struct ieee80211_tx_status status = {}; struct ath12k_dp_link_peer *peer; - struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + struct ath12k_pdev_dp *dp_pdev; skb_cb = ATH12K_SKB_CB(msdu); info = IEEE80211_SKB_CB(msdu); ar = skb_cb->ar; + dp_pdev = &ar->dp; ab->device_stats.tx_completed[tx_ring->tcl_data_ring_id]++; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) @@ -449,18 +450,15 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, } } rcu_read_lock(); - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, peer_id); + peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DATA, "dp_tx: failed to find the peer with peer_id %d\n", peer_id); - spin_unlock_bh(&dp->dp_lock); ieee80211_free_txskb(ath12k_ar_to_hw(ar), msdu); goto exit; } else { status.sta = peer->sta; } - spin_unlock_bh(&dp->dp_lock); status.info = info; status.skb = msdu; @@ -519,7 +517,7 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, { struct ath12k_dp *dp = dp_pdev->dp; struct ath12k_base *ab = dp->ab; - struct ath12k_dp_link_peer *peer; + struct ath12k_dp_peer *peer; struct ieee80211_sta *sta; struct ath12k_sta *ahsta; struct ath12k_link_sta *arsta; @@ -528,12 +526,10 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, u8 rate_idx = 0; int ret; - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, ts->peer_id); + peer = ath12k_dp_peer_find_by_peerid(dp_pdev, ts->peer_id); if (!peer || !peer->sta) { ath12k_dbg(ab, ATH12K_DBG_DP_TX, "failed to find the peer by id %u\n", ts->peer_id); - spin_unlock_bh(&dp->dp_lock); return; } sta = peer->sta; @@ -547,7 +543,6 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev, txrate.nss = arsta->last_txrate.nss; else txrate.nss = arsta->peer_nss; - spin_unlock_bh(&dp->dp_lock); switch (ts->pkt_type) { case HAL_TX_RATE_STATS_PKT_TYPE_11A: @@ -650,7 +645,7 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev, s32 noise_floor; struct ieee80211_tx_status status = {}; struct ieee80211_rate_status status_rate = {}; - struct ath12k_dp_link_peer *peer; + struct ath12k_dp_peer *peer; struct ath12k_link_sta *arsta; struct ath12k_sta *ahsta; struct rate_info rate; @@ -747,21 +742,17 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev, ath12k_wifi7_dp_tx_update_txcompl(dp_pdev, ts); - spin_lock_bh(&dp->dp_lock); - peer = ath12k_dp_link_peer_find_by_id(dp, ts->peer_id); + peer = ath12k_dp_peer_find_by_peerid(dp_pdev, ts->peer_id); if (!peer || !peer->sta) { ath12k_err(ab, "dp_tx: failed to find the peer with peer_id %d\n", ts->peer_id); - spin_unlock_bh(&dp->dp_lock); ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu); goto exit; } ahsta = ath12k_sta_to_ahsta(peer->sta); arsta = &ahsta->deflink; - spin_unlock_bh(&dp->dp_lock); - status.sta = peer->sta; status.info = info; status.skb = msdu; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c index 2767d6865d70..09a41e110e08 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c @@ -439,6 +439,8 @@ int ath12k_wifi7_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc, HAL_WBM_RELEASE_INFO0_RXDMA_ERROR_CODE); } + rel_info->peer_metadata = wbm_desc->info2; + return 0; } diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h index c4fa2bee97b5..23da5b871983 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h @@ -21,6 +21,7 @@ struct hal_rx_wbm_rel_info { bool continuation; void *rx_desc; bool hw_cc_done; + __le32 peer_metadata; }; #define HAL_RX_MPDU_INFO_PN_GET_BYTE1(__val) \ -- 2.34.1 Add RCU_LOCKDEP_WARN() in following functions: - ath12k_dp_link_peer_to_link_sta() - ath12k_wifi7_dp_rx_h_mpdu() Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ripan Deuri --- drivers/net/wireless/ath/ath12k/dp_peer.c | 3 +++ drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 61478e66d9af..a06113bedf0d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -182,6 +182,9 @@ struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab, struct ath12k_sta *ahsta; struct ath12k_link_sta *arsta; + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "ath12k_dp_link_peer to ath12k_link_sta called without rcu lock"); + if (!peer->sta) return NULL; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index 87875486fb4a..d24d0f12742e 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -323,6 +323,9 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev, struct ieee80211_rx_status *rx_status = rx_info->rx_status; u32 err_bitmap = rx_info->err_bitmap; + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "dp_rx_h_mpdu called without rcu lock"); + /* PN for multicast packets will be checked in mac80211 */ rxcb = ATH12K_SKB_RXCB(msdu); rxcb->is_mcbc = rx_info->is_mcbc; -- 2.34.1