wifi: ath12k: Add helpers for multi link peer creation and deletion

Add helper functions for multi link peer addition and deletion. And add address
validation to ensure we are not creating link peers (belonging to different
clients) with same MLD address. To aid in this validation for faster lookup,
add a new list of ML peers to struct ath12k_hw::ml_peers and use the same for
parsing for the above address validation use cases.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-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: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Link: https://patch.msgid.link/20241101151705.165987-6-kvalo@kernel.org
Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
This commit is contained in:
Sriram R
2024-11-01 17:17:02 +02:00
committed by Jeff Johnson
parent a2189d2b80
commit 7fd8b4cbde
4 changed files with 121 additions and 0 deletions

View File

@@ -63,6 +63,13 @@
#define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
#define ATH12K_MAX_SOCS 3
#define ATH12K_INVALID_GROUP_ID 0xFF
#define ATH12K_INVALID_DEVICE_ID 0xFF
#define ATH12K_MAX_MLO_PEERS 256
#define ATH12K_MLO_PEER_ID_INVALID 0xFFFF
enum ath12k_bdf_search {
ATH12K_BDF_SEARCH_DEFAULT,
ATH12K_BDF_SEARCH_BUS_AND_BOARD,
@@ -496,6 +503,7 @@ struct ath12k_sta {
struct ath12k_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
/* indicates bitmap of link sta created in FW */
u16 links_map;
u16 ml_peer_id;
};
#define ATH12K_MIN_5G_FREQ 4150
@@ -703,6 +711,11 @@ struct ath12k_hw {
u8 num_radio;
DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS);
/* protected by wiphy_lock() */
struct list_head ml_peers;
/* Keep last */
struct ath12k radio[] __aligned(sizeof(void *));
};

View File

@@ -5091,6 +5091,7 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
ahsta->links_map = BIT(arsta->link_id);
arsta->ahsta = ahsta;
arsta->arvif = arvif;
ether_addr_copy(arsta->addr, sta->addr);
wiphy_work_init(&arsta->update_wk, ath12k_sta_rc_update_wk);
synchronize_rcu();
@@ -10110,6 +10111,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
ah->num_radio = num_pdev_map;
mutex_init(&ah->hw_mutex);
INIT_LIST_HEAD(&ah->ml_peers);
for (i = 0; i < num_pdev_map; i++) {
ab = pdev_map[i].ab;

View File

@@ -8,6 +8,22 @@
#include "peer.h"
#include "debug.h"
static 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;
}
struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id,
const u8 *addr)
{
@@ -341,3 +357,85 @@ 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 ml_peer_id;
lockdep_assert_wiphy(ah->hw->wiphy);
for (ml_peer_id = 0; ml_peer_id < ATH12K_MAX_MLO_PEERS; ml_peer_id++) {
if (test_bit(ml_peer_id, ah->free_ml_peer_id_map))
continue;
set_bit(ml_peer_id, ah->free_ml_peer_id_map);
break;
}
if (ml_peer_id == ATH12K_MAX_MLO_PEERS)
ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
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;
}

View File

@@ -49,6 +49,12 @@ struct ath12k_peer {
bool dp_setup_done;
};
struct ath12k_ml_peer {
struct list_head list;
u8 addr[ETH_ALEN];
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);
@@ -66,5 +72,7 @@ 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);
#endif /* _PEER_H_ */