Commit ee16dcf5 authored by Harsh Kumar Bijlani's avatar Harsh Kumar Bijlani Committed by Jeff Johnson
Browse files

wifi: ath12k: Define ath12k_dp_peer structure & APIs for create & delete



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: default avatarHarsh Kumar Bijlani <quic_hbijlani@quicinc.com>
Signed-off-by: default avatarRipan Deuri <quic_rdeuri@quicinc.com>
Reviewed-by: default avatarVasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Reviewed-by: default avatarBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20251024181548.3255166-7-quic_rdeuri@quicinc.com


Signed-off-by: default avatarJeff Johnson <jeff.johnson@oss.qualcomm.com>
parent a88cf5f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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,
+1 −2
Original line number Diff line number Diff line
@@ -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 *));
+22 −0
Original line number Diff line number Diff line
@@ -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)
{
+126 −0
Original line number Diff line number Diff line
@@ -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);
}
+24 −0
Original line number Diff line number Diff line
@@ -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
Loading