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

wifi: ath12k: Use ath12k_dp_peer in per packet Tx & Rx paths



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: 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-9-quic_rdeuri@quicinc.com


Signed-off-by: default avatarJeff Johnson <jeff.johnson@oss.qualcomm.com>
parent 5525f12f
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -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
+3 −3
Original line number Diff line number Diff line
@@ -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);
}

+5 −17
Original line number Diff line number Diff line
@@ -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);
		}
	}

+7 −6
Original line number Diff line number Diff line
@@ -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);
+42 −3
Original line number Diff line number Diff line
@@ -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);

Loading