]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Move DP specific link stats to DP link peer
authorHarsh Kumar Bijlani <quic_hbijlani@quicinc.com>
Mon, 3 Nov 2025 11:21:02 +0000 (16:51 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Wed, 5 Nov 2025 15:16:54 +0000 (07:16 -0800)
As part of peer modularization in the Driver Framework, the station view is as
follows:

            Common 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

Currently ath12k_link_sta has data path stats updated in tx_htt and rx monitor
path. Move those stats from ath12_link_sta to ath12k_dp_link_peer to align with
peer modularization model as shown above.

This allows datapath to use only ath12k_dp_link_peer without having to reach out
to other objects for updating stats, thereby improving the cache locality.

Add following API to fetch rate info from DP link peer:

ath12k_dp_link_peer_get_sta_rate_info_stats()

This wrapper API populates link stats in 'struct ath12k_dp_link_peer_rate_info',
which can be extended to support out-of-band retrieval of various rate stats.

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 <quic_hbijlani@quicinc.com>
Signed-off-by: Ripan Deuri <quic_rdeuri@quicinc.com>
Reviewed-by: Karthikeyan Periyasamy <karthikeyan.periyasamy@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20251103112111.2260639-4-quic_rdeuri@quicinc.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/core.h
drivers/net/wireless/ath/ath12k/debugfs_sta.c
drivers/net/wireless/ath/ath12k/dp_cmn.h
drivers/net/wireless/ath/ath12k/dp_htt.c
drivers/net/wireless/ath/ath12k/dp_mon.c
drivers/net/wireless/ath/ath12k/dp_peer.c
drivers/net/wireless/ath/ath12k/dp_peer.h
drivers/net/wireless/ath/ath12k/hal.h
drivers/net/wireless/ath/ath12k/mac.c
drivers/net/wireless/ath/ath12k/peer.c
drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c

index b6ed0e082fc64053f2b0b6b725580946f7d08400..e32fc1355c04899e5ceaf74b7ca7397c4b29b0ae 100644 (file)
@@ -395,51 +395,8 @@ struct ath12k_vif_iter {
        struct ath12k_link_vif *arvif;
 };
 
-#define HAL_AST_IDX_INVALID    0xFFFF
-#define HAL_RX_MAX_MCS         12
-#define HAL_RX_MAX_MCS_HT      31
-#define HAL_RX_MAX_MCS_VHT     9
-#define HAL_RX_MAX_MCS_HE      11
-#define HAL_RX_MAX_MCS_BE      15
-#define HAL_RX_MAX_NSS         8
-#define HAL_RX_MAX_NUM_LEGACY_RATES 12
-
 #define ATH12K_SCAN_TIMEOUT_HZ (20 * HZ)
 
-struct ath12k_rx_peer_rate_stats {
-       u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
-       u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
-       u64 he_mcs_count[HAL_RX_MAX_MCS_HE + 1];
-       u64 be_mcs_count[HAL_RX_MAX_MCS_BE + 1];
-       u64 nss_count[HAL_RX_MAX_NSS];
-       u64 bw_count[HAL_RX_BW_MAX];
-       u64 gi_count[HAL_RX_GI_MAX];
-       u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES];
-       u64 rx_rate[HAL_RX_BW_MAX][HAL_RX_GI_MAX][HAL_RX_MAX_NSS][HAL_RX_MAX_MCS_HT + 1];
-};
-
-struct ath12k_rx_peer_stats {
-       u64 num_msdu;
-       u64 num_mpdu_fcs_ok;
-       u64 num_mpdu_fcs_err;
-       u64 tcp_msdu_count;
-       u64 udp_msdu_count;
-       u64 other_msdu_count;
-       u64 ampdu_msdu_count;
-       u64 non_ampdu_msdu_count;
-       u64 stbc_count;
-       u64 beamformed_count;
-       u64 coding_count[HAL_RX_SU_MU_CODING_MAX];
-       u64 tid_count[IEEE80211_NUM_TIDS + 1];
-       u64 pream_cnt[HAL_RX_PREAMBLE_MAX];
-       u64 reception_type[HAL_RX_RECEPTION_TYPE_MAX];
-       u64 rx_duration;
-       u64 dcm_count;
-       u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX];
-       struct ath12k_rx_peer_rate_stats pkt_stats;
-       struct ath12k_rx_peer_rate_stats byte_stats;
-};
-
 #define ATH12K_HE_MCS_NUM       12
 #define ATH12K_VHT_MCS_NUM      10
 #define ATH12K_BW_NUM           5
@@ -521,12 +478,6 @@ struct ath12k_per_ppdu_tx_stats {
        u32 retry_bytes;
 };
 
-struct ath12k_wbm_tx_stats {
-       u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
-};
-
-DECLARE_EWMA(avg_rssi, 10, 8)
-
 struct ath12k_link_sta {
        struct ath12k_link_vif *arvif;
        struct ath12k_sta *ahsta;
@@ -541,15 +492,7 @@ struct ath12k_link_sta {
        u32 smps;
 
        struct wiphy_work update_wk;
-       struct rate_info txrate;
-       struct rate_info last_txrate;
-       u64 rx_duration;
-       u64 tx_duration;
-       u8 rssi_comb;
-       struct ewma_avg_rssi avg_rssi;
        u8 link_id;
-       struct ath12k_rx_peer_stats *rx_stats;
-       struct ath12k_wbm_tx_stats *wbm_tx_stats;
        u32 bw_prev;
        u32 peer_nss;
        s8 rssi_beacon;
@@ -559,8 +502,6 @@ struct ath12k_link_sta {
 
         /* for firmware use only */
        u8 link_idx;
-       u32 tx_retry_failed;
-       u32 tx_retry_count;
 
        /* peer addr based rhashtable list pointer */
        struct rhash_head rhash_addr;
index e6665fd521db81603b35835cc093d2174593162e..dde3efed4b60b91055b69aa324c5daecadc1aa15 100644 (file)
@@ -11,6 +11,7 @@
 #include "debug.h"
 #include "debugfs_htt_stats.h"
 #include "debugfs.h"
+#include "dp_cmn.h"
 
 static
 u32 ath12k_dbg_sta_dump_rate_stats(u8 *buf, u32 offset, const int size,
@@ -144,9 +145,11 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
        const int size = ATH12K_STA_RX_STATS_BUF_SIZE;
        struct ath12k_hw *ah = ahsta->ahvif->ah;
        struct ath12k_rx_peer_stats *rx_stats;
+       struct ath12k_dp_link_peer *link_peer;
        struct ath12k_link_sta *arsta;
        u8 link_id = link_sta->link_id;
        int len = 0, i, ret = 0;
+       struct ath12k_dp *dp;
        bool he_rates_avail;
        struct ath12k *ar;
 
@@ -171,9 +174,16 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
                goto out;
        }
 
-       spin_lock_bh(&ar->ab->base_lock);
+       dp = ath12k_ab_to_dp(ar->ab);
+       spin_lock_bh(&dp->dp_lock);
 
-       rx_stats = arsta->rx_stats;
+       link_peer = ath12k_dp_link_peer_find_by_addr(dp, arsta->addr);
+       if (!link_peer) {
+               ret = -ENOENT;
+               goto unlock;
+       }
+
+       rx_stats = link_peer->peer_stats.rx_stats;
        if (!rx_stats) {
                ret = -ENOENT;
                goto unlock;
@@ -238,7 +248,7 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
                                              &rx_stats->byte_stats);
 
 unlock:
-       spin_unlock_bh(&ar->ab->base_lock);
+       spin_unlock_bh(&dp->dp_lock);
 
        if (len)
                ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
@@ -261,10 +271,9 @@ static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
        struct ieee80211_link_sta *link_sta = file->private_data;
        struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
        struct ath12k_hw *ah = ahsta->ahvif->ah;
-       struct ath12k_rx_peer_stats *rx_stats;
-       struct ath12k_link_sta *arsta;
        u8 link_id = link_sta->link_id;
-       struct ath12k *ar;
+       struct ath12k_link_sta *arsta;
+       struct ath12k_dp *dp;
        bool reset;
        int ret;
 
@@ -288,19 +297,9 @@ static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
                goto out;
        }
 
-       ar = arsta->arvif->ar;
-
-       spin_lock_bh(&ar->ab->base_lock);
-
-       rx_stats = arsta->rx_stats;
-       if (!rx_stats) {
-               spin_unlock_bh(&ar->ab->base_lock);
-               ret = -ENOENT;
-               goto out;
-       }
+       dp = ath12k_ab_to_dp(arsta->arvif->ar->ab);
 
-       memset(rx_stats, 0, sizeof(*rx_stats));
-       spin_unlock_bh(&ar->ab->base_lock);
+       ath12k_dp_link_peer_reset_rx_stats(dp, arsta->addr);
 
        ret = count;
 out:
index dd10426bd12def581db6529e537fc1ebdcccf442..e17f044ff812278507e215b8434a2a15c1425139 100644 (file)
@@ -74,6 +74,14 @@ struct ath12k_dp_peer_create_params {
        bool ucast_ra_only;
 };
 
+struct ath12k_dp_link_peer_rate_info {
+       struct rate_info txrate;
+       u64 rx_duration;
+       u64 tx_duration;
+       u8 rssi_comb;
+       s8 signal_avg;
+};
+
 static inline struct ath12k_dp_link_vif *
 ath12k_dp_vif_to_dp_link_vif(struct ath12k_dp_vif *dp_vif, u8 link_id)
 {
@@ -91,4 +99,8 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
                               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);
+void
+ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr,
+                                           struct ath12k_dp_link_peer_rate_info *info);
+void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr);
 #endif
index db5ac36adf3ddabdbbfa87ed575b57e30fa53bbb..39f42cd99835baf933c90f1796e0c28ae761acbd 100644 (file)
@@ -189,7 +189,6 @@ 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_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;
        struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user];
@@ -279,66 +278,64 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,
                return;
        }
 
-       arsta = ath12k_dp_link_peer_to_link_sta(ab, peer);
-       if (!arsta) {
-               rcu_read_unlock();
-               return;
-       }
+       spin_lock_bh(&dp->dp_lock);
 
-       memset(&arsta->txrate, 0, sizeof(arsta->txrate));
+       memset(&peer->txrate, 0, sizeof(peer->txrate));
 
-       arsta->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw);
+       peer->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw);
 
        switch (flags) {
        case WMI_RATE_PREAMBLE_OFDM:
-               arsta->txrate.legacy = rate;
+               peer->txrate.legacy = rate;
                break;
        case WMI_RATE_PREAMBLE_CCK:
-               arsta->txrate.legacy = rate;
+               peer->txrate.legacy = rate;
                break;
        case WMI_RATE_PREAMBLE_HT:
-               arsta->txrate.mcs = mcs + 8 * (nss - 1);
-               arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
+               peer->txrate.mcs = mcs + 8 * (nss - 1);
+               peer->txrate.flags = RATE_INFO_FLAGS_MCS;
                if (sgi)
-                       arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+                       peer->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
                break;
        case WMI_RATE_PREAMBLE_VHT:
-               arsta->txrate.mcs = mcs;
-               arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
+               peer->txrate.mcs = mcs;
+               peer->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
                if (sgi)
-                       arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+                       peer->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
                break;
        case WMI_RATE_PREAMBLE_HE:
-               arsta->txrate.mcs = mcs;
-               arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
-               arsta->txrate.he_dcm = dcm;
-               arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
+               peer->txrate.mcs = mcs;
+               peer->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
+               peer->txrate.he_dcm = dcm;
+               peer->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
                tones = le16_to_cpu(user_rate->ru_end) -
                        le16_to_cpu(user_rate->ru_start) + 1;
                v = ath12k_he_ru_tones_to_nl80211_he_ru_alloc(tones);
-               arsta->txrate.he_ru_alloc = v;
+               peer->txrate.he_ru_alloc = v;
                if (is_ofdma)
-                       arsta->txrate.bw = RATE_INFO_BW_HE_RU;
+                       peer->txrate.bw = RATE_INFO_BW_HE_RU;
                break;
        case WMI_RATE_PREAMBLE_EHT:
-               arsta->txrate.mcs = mcs;
-               arsta->txrate.flags = RATE_INFO_FLAGS_EHT_MCS;
-               arsta->txrate.he_dcm = dcm;
-               arsta->txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(sgi);
+               peer->txrate.mcs = mcs;
+               peer->txrate.flags = RATE_INFO_FLAGS_EHT_MCS;
+               peer->txrate.he_dcm = dcm;
+               peer->txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(sgi);
                tones = le16_to_cpu(user_rate->ru_end) -
                        le16_to_cpu(user_rate->ru_start) + 1;
                v = ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(tones);
-               arsta->txrate.eht_ru_alloc = v;
+               peer->txrate.eht_ru_alloc = v;
                if (is_ofdma)
-                       arsta->txrate.bw = RATE_INFO_BW_EHT_RU;
+                       peer->txrate.bw = RATE_INFO_BW_EHT_RU;
                break;
        }
 
-       arsta->tx_retry_failed += tx_retry_failed;
-       arsta->tx_retry_count += tx_retry_count;
-       arsta->txrate.nss = nss;
-       arsta->tx_duration += tx_duration;
-       memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info));
+       peer->tx_retry_failed += tx_retry_failed;
+       peer->tx_retry_count += tx_retry_count;
+       peer->txrate.nss = nss;
+       peer->tx_duration += tx_duration;
+       memcpy(&peer->last_txrate, &peer->txrate, sizeof(struct rate_info));
+
+       spin_unlock_bh(&dp->dp_lock);
 
        /* PPDU stats reported for mgmt packet doesn't have valid tx bytes.
         * So skip peer stats update for mgmt packets.
index b9ccb5462e9d0eb32785ca76c6e1107e81b82b0c..ded47015c1d0078cca4ef3fa26f86bda635dcac9 100644 (file)
@@ -3456,6 +3456,9 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
        u32 gi_idx = ppdu_info->gi;
        u32 len;
 
+       if (!rx_stats)
+               return;
+
        if (mcs_idx > HAL_RX_MAX_MCS_HT || nss_idx >= HAL_RX_MAX_NSS ||
            bw_idx >= HAL_RX_BW_MAX || gi_idx >= HAL_RX_GI_MAX) {
                return;
@@ -3476,14 +3479,14 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
        stats->rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += len;
 }
 
-static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_link_sta *arsta,
+static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_dp_link_peer *peer,
                                                  struct hal_rx_mon_ppdu_info *ppdu_info)
 {
-       struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
+       struct ath12k_rx_peer_stats *rx_stats = peer->peer_stats.rx_stats;
        u32 num_msdu;
 
-       arsta->rssi_comb = ppdu_info->rssi_comb;
-       ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb);
+       peer->rssi_comb = ppdu_info->rssi_comb;
+       ewma_avg_rssi_add(&peer->avg_rssi, ppdu_info->rssi_comb);
        if (!rx_stats)
                return;
 
@@ -3531,7 +3534,7 @@ static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_link_sta *arsta,
        rx_stats->dcm_count += ppdu_info->dcm;
 
        rx_stats->rx_duration += ppdu_info->rx_duration;
-       arsta->rx_duration = rx_stats->rx_duration;
+       peer->rx_duration = rx_stats->rx_duration;
 
        if (ppdu_info->nss > 0 && ppdu_info->nss <= HAL_RX_MAX_NSS) {
                rx_stats->pkt_stats.nss_count[ppdu_info->nss - 1] += num_msdu;
@@ -3638,7 +3641,6 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab,
                                   struct hal_rx_mon_ppdu_info *ppdu_info,
                                   u32 uid)
 {
-       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_dp_link_peer *peer;
@@ -3656,16 +3658,9 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab,
                return;
        }
 
-       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);
-               return;
-       }
-
-       arsta->rssi_comb = ppdu_info->rssi_comb;
-       ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb);
-       rx_stats = arsta->rx_stats;
+       peer->rssi_comb = ppdu_info->rssi_comb;
+       ewma_avg_rssi_add(&peer->avg_rssi, ppdu_info->rssi_comb);
+       rx_stats = peer->peer_stats.rx_stats;
        if (!rx_stats)
                return;
 
@@ -3709,7 +3704,7 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab,
                rx_stats->ru_alloc_cnt[user_stats->ul_ofdma_ru_size] += num_msdu;
 
        rx_stats->rx_duration += ppdu_info->rx_duration;
-       arsta->rx_duration = rx_stats->rx_duration;
+       peer->rx_duration = rx_stats->rx_duration;
 
        if (user_stats->nss > 0 && user_stats->nss <= HAL_RX_MAX_NSS) {
                rx_stats->pkt_stats.nss_count[user_stats->nss - 1] += num_msdu;
@@ -3774,7 +3769,6 @@ int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget,
        struct dp_srng *mon_dst_ring;
        struct hal_srng *srng;
        struct dp_rxdma_mon_ring *buf_ring;
-       struct ath12k_link_sta *arsta;
        struct ath12k_dp_link_peer *peer;
        struct sk_buff_head skb_list;
        u64 cookie;
@@ -3898,16 +3892,7 @@ move_next:
                }
 
                if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
-                       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);
-                               rcu_read_unlock();
-                               dev_kfree_skb_any(skb);
-                               continue;
-                       }
-                       ath12k_dp_mon_rx_update_peer_su_stats(arsta,
-                                                             ppdu_info);
+                       ath12k_dp_mon_rx_update_peer_su_stats(peer, ppdu_info);
                } else if ((ppdu_info->fc_valid) &&
                           (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
                        ath12k_dp_mon_rx_process_ulofdma(ppdu_info);
index a06113bedf0d7c88c1e563550a3def8806b987bb..8961c4635ed0b55c3222eda3724a40d3eda5934e 100644 (file)
@@ -7,6 +7,7 @@
 #include "core.h"
 #include "dp_peer.h"
 #include "debug.h"
+#include "debugfs.h"
 
 struct ath12k_dp_link_peer *
 ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp,
@@ -140,6 +141,8 @@ void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id)
                   peer->vdev_id, peer->addr, peer_id);
 
        list_del(&peer->list);
+
+       kfree(peer->peer_stats.rx_stats);
        kfree(peer);
        wake_up(&ab->peer_mapping_wq);
 
@@ -152,6 +155,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);
+       struct ath12k *ar;
 
        spin_lock_bh(&dp->dp_lock);
        peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, mac_addr);
@@ -165,10 +169,20 @@ 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);
+
+               rcu_read_lock();
+               ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);
+               if (ar && ath12k_debugfs_is_extd_rx_stats_enabled(ar) &&
+                   !peer->peer_stats.rx_stats) {
+                       peer->peer_stats.rx_stats =
+                               kzalloc(sizeof(*peer->peer_stats.rx_stats), GFP_ATOMIC);
+               }
+               rcu_read_unlock();
+
                list_add(&peer->list, &dp->peers);
                wake_up(&ab->peer_mapping_wq);
+               ewma_avg_rssi_init(&peer->avg_rssi);
        }
-
        ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n",
                   vdev_id, mac_addr, peer_id);
 
@@ -625,3 +639,45 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_
 
        synchronize_rcu();
 }
+
+void
+ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr,
+                                           struct ath12k_dp_link_peer_rate_info *info)
+{
+       struct ath12k_dp_link_peer *link_peer;
+
+       guard(spinlock_bh)(&dp->dp_lock);
+
+       link_peer = ath12k_dp_link_peer_find_by_addr(dp, addr);
+       if (!link_peer)
+               return;
+
+       info->rx_duration = link_peer->rx_duration;
+       info->tx_duration = link_peer->tx_duration;
+       info->txrate.legacy = link_peer->txrate.legacy;
+       info->txrate.mcs = link_peer->txrate.mcs;
+       info->txrate.nss = link_peer->txrate.nss;
+       info->txrate.bw = link_peer->txrate.bw;
+       info->txrate.he_gi = link_peer->txrate.he_gi;
+       info->txrate.he_dcm = link_peer->txrate.he_dcm;
+       info->txrate.he_ru_alloc = link_peer->txrate.he_ru_alloc;
+       info->txrate.flags = link_peer->txrate.flags;
+       info->rssi_comb = link_peer->rssi_comb;
+       info->signal_avg = ewma_avg_rssi_read(&link_peer->avg_rssi);
+}
+
+void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr)
+{
+       struct ath12k_rx_peer_stats *rx_stats;
+       struct ath12k_dp_link_peer *link_peer;
+
+       guard(spinlock_bh)(&dp->dp_lock);
+
+       link_peer = ath12k_dp_link_peer_find_by_addr(dp, addr);
+       if (!link_peer || !link_peer->peer_stats.rx_stats)
+               return;
+
+       rx_stats = link_peer->peer_stats.rx_stats;
+       if (rx_stats)
+               memset(rx_stats, 0, sizeof(*rx_stats));
+}
index f7c995e8c4e32c3a3322b71e2750e6f3468a7dfd..f9be27d86545341fb6a4d1461f459e2ee71c352a 100644 (file)
@@ -23,6 +23,51 @@ struct ppdu_user_delayba {
 
 #define ATH12K_PEER_ML_ID_VALID         BIT(13)
 
+struct ath12k_rx_peer_rate_stats {
+       u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
+       u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
+       u64 he_mcs_count[HAL_RX_MAX_MCS_HE + 1];
+       u64 be_mcs_count[HAL_RX_MAX_MCS_BE + 1];
+       u64 nss_count[HAL_RX_MAX_NSS];
+       u64 bw_count[HAL_RX_BW_MAX];
+       u64 gi_count[HAL_RX_GI_MAX];
+       u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES];
+       u64 rx_rate[HAL_RX_BW_MAX][HAL_RX_GI_MAX][HAL_RX_MAX_NSS][HAL_RX_MAX_MCS_HT + 1];
+};
+
+struct ath12k_rx_peer_stats {
+       u64 num_msdu;
+       u64 num_mpdu_fcs_ok;
+       u64 num_mpdu_fcs_err;
+       u64 tcp_msdu_count;
+       u64 udp_msdu_count;
+       u64 other_msdu_count;
+       u64 ampdu_msdu_count;
+       u64 non_ampdu_msdu_count;
+       u64 stbc_count;
+       u64 beamformed_count;
+       u64 coding_count[HAL_RX_SU_MU_CODING_MAX];
+       u64 tid_count[IEEE80211_NUM_TIDS + 1];
+       u64 pream_cnt[HAL_RX_PREAMBLE_MAX];
+       u64 reception_type[HAL_RX_RECEPTION_TYPE_MAX];
+       u64 rx_duration;
+       u64 dcm_count;
+       u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX];
+       struct ath12k_rx_peer_rate_stats pkt_stats;
+       struct ath12k_rx_peer_rate_stats byte_stats;
+};
+
+struct ath12k_wbm_tx_stats {
+       u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
+};
+
+struct ath12k_dp_peer_stats {
+       struct ath12k_rx_peer_stats *rx_stats;
+       struct ath12k_wbm_tx_stats *wbm_tx_stats;
+};
+
+DECLARE_EWMA(avg_rssi, 10, 8)
+
 struct ath12k_dp_link_peer {
        struct list_head list;
        struct ieee80211_sta *sta;
@@ -58,6 +103,17 @@ struct ath12k_dp_link_peer {
 
        u8 hw_link_id;
        u32 rx_tid_active_bitmask;
+
+       /* link stats */
+       struct rate_info txrate;
+       struct rate_info last_txrate;
+       u64 rx_duration;
+       u64 tx_duration;
+       u8 rssi_comb;
+       struct ewma_avg_rssi avg_rssi;
+       struct ath12k_dp_peer_stats peer_stats;
+       u32 tx_retry_failed;
+       u32 tx_retry_count;
 };
 
 void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id);
index dbf07c15481b8d6d1a9e77a0bcc7f44fe393a2ab..69c2e8b318d5b483caea40f52a65896857d2667d 100644 (file)
@@ -64,6 +64,15 @@ struct ath12k_base;
 #define HAL_WBM_IDLE_SCATTER_BUF_SIZE (HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX - \
                                       HAL_WBM_IDLE_SCATTER_NEXT_PTR_SIZE)
 
+#define HAL_AST_IDX_INVALID    0xFFFF
+#define HAL_RX_MAX_MCS         12
+#define HAL_RX_MAX_MCS_HT      31
+#define HAL_RX_MAX_MCS_VHT     9
+#define HAL_RX_MAX_MCS_HE      11
+#define HAL_RX_MAX_MCS_BE      15
+#define HAL_RX_MAX_NSS         8
+#define HAL_RX_MAX_NUM_LEGACY_RATES 12
+
 enum hal_srng_ring_id {
        HAL_SRNG_RING_ID_REO2SW0 = 0,
        HAL_SRNG_RING_ID_REO2SW1,
index f55c207c496235cce5ac2a89ccf9979cbc5155b0..4972367dd1ba267b7feae85406ad54c500b2a086 100644 (file)
@@ -23,6 +23,7 @@
 #include "wow.h"
 #include "debugfs_sta.h"
 #include "dp.h"
+#include "dp_cmn.h"
 
 #define CHAN2G(_channel, _freq, _flags) { \
        .band                   = NL80211_BAND_2GHZ, \
@@ -1213,6 +1214,8 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
 
        list_for_each_entry_safe(peer, tmp, &peers, list) {
                list_del(&peer->list);
+
+               kfree(peer->peer_stats.rx_stats);
                kfree(peer);
        }
 
@@ -6375,14 +6378,13 @@ static void ath12k_mac_station_post_remove(struct ath12k *ar,
                            vif->addr, arvif->vdev_id);
                peer->sta = NULL;
                list_del(&peer->list);
+
+               kfree(peer->peer_stats.rx_stats);
                kfree(peer);
                ar->num_peers--;
        }
 
        spin_unlock_bh(&dp->dp_lock);
-
-       kfree(arsta->rx_stats);
-       arsta->rx_stats = NULL;
 }
 
 static int ath12k_mac_station_unauthorize(struct ath12k *ar,
@@ -6527,14 +6529,6 @@ static int ath12k_mac_station_add(struct ath12k *ar,
                goto exit;
        }
 
-       if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && !arsta->rx_stats) {
-               arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
-               if (!arsta->rx_stats) {
-                       ret = -ENOMEM;
-                       goto dec_num_station;
-               }
-       }
-
        spin_lock_bh(&ab->base_lock);
 
        /*
@@ -6552,7 +6546,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
        if (ret) {
                ath12k_warn(ab, "Failed to add arsta: %pM to hash table, ret: %d",
                            arsta->addr, ret);
-               goto free_rx_stats;
+               goto dec_num_station;
        }
 
        peer_param.vdev_id = arvif->vdev_id;
@@ -6598,7 +6592,6 @@ static int ath12k_mac_station_add(struct ath12k *ar,
                }
        }
 
-       ewma_avg_rssi_init(&arsta->avg_rssi);
        return 0;
 
 free_peer:
@@ -6606,9 +6599,6 @@ free_peer:
        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:
        ath12k_mac_dec_num_stations(arvif, arsta);
 exit:
@@ -12888,9 +12878,12 @@ void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
                                  struct station_info *sinfo)
 {
        struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+       struct ath12k_dp_link_peer_rate_info rate_info = {};
        struct ath12k_fw_stats_req_params params = {};
+       struct ath12k_dp_link_peer *peer;
        struct ath12k_link_sta *arsta;
        s8 signal, noise_floor;
+       struct ath12k_dp *dp;
        struct ath12k *ar;
        bool db2dbm;
 
@@ -12901,34 +12894,37 @@ void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
        if (!ar)
                return;
 
+       dp = ath12k_ab_to_dp(ar->ab);
+       ath12k_dp_link_peer_get_sta_rate_info_stats(dp, arsta->addr, &rate_info);
+
        db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
                          ar->ab->wmi_ab.svc_map);
 
-       sinfo->rx_duration = arsta->rx_duration;
+       sinfo->rx_duration = rate_info.rx_duration;
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
 
-       sinfo->tx_duration = arsta->tx_duration;
+       sinfo->tx_duration = rate_info.tx_duration;
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
 
-       if (arsta->txrate.legacy || arsta->txrate.nss) {
-               if (arsta->txrate.legacy) {
-                       sinfo->txrate.legacy = arsta->txrate.legacy;
+       if (rate_info.txrate.legacy || rate_info.txrate.nss) {
+               if (rate_info.txrate.legacy) {
+                       sinfo->txrate.legacy = rate_info.txrate.legacy;
                } else {
-                       sinfo->txrate.mcs = arsta->txrate.mcs;
-                       sinfo->txrate.nss = arsta->txrate.nss;
-                       sinfo->txrate.bw = arsta->txrate.bw;
-                       sinfo->txrate.he_gi = arsta->txrate.he_gi;
-                       sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
-                       sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
-                       sinfo->txrate.eht_gi = arsta->txrate.eht_gi;
-                       sinfo->txrate.eht_ru_alloc = arsta->txrate.eht_ru_alloc;
-               }
-               sinfo->txrate.flags = arsta->txrate.flags;
+                       sinfo->txrate.mcs = rate_info.txrate.mcs;
+                       sinfo->txrate.nss = rate_info.txrate.nss;
+                       sinfo->txrate.bw = rate_info.txrate.bw;
+                       sinfo->txrate.he_gi = rate_info.txrate.he_gi;
+                       sinfo->txrate.he_dcm = rate_info.txrate.he_dcm;
+                       sinfo->txrate.he_ru_alloc = rate_info.txrate.he_ru_alloc;
+                       sinfo->txrate.eht_gi = rate_info.txrate.eht_gi;
+                       sinfo->txrate.eht_ru_alloc = rate_info.txrate.eht_ru_alloc;
+               }
+               sinfo->txrate.flags = rate_info.txrate.flags;
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
        }
 
        /* TODO: Use real NF instead of default one. */
-       signal = arsta->rssi_comb;
+       signal = rate_info.rssi_comb;
 
        params.pdev_id = ar->pdev->pdev_id;
        params.vdev_id = 0;
@@ -12948,17 +12944,26 @@ void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
        }
 
-       sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
+       sinfo->signal_avg = rate_info.signal_avg;
 
        if (!db2dbm)
                sinfo->signal_avg += noise_floor;
 
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
 
-       sinfo->tx_retries = arsta->tx_retry_count;
-       sinfo->tx_failed = arsta->tx_retry_failed;
+       spin_lock_bh(&dp->dp_lock);
+       peer = ath12k_dp_link_peer_find_by_addr(dp, arsta->addr);
+       if (!peer) {
+               spin_unlock_bh(&dp->dp_lock);
+               return;
+       }
+
+       sinfo->tx_retries = peer->tx_retry_count;
+       sinfo->tx_failed = peer->tx_retry_failed;
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+
+       spin_unlock_bh(&dp->dp_lock);
 }
 EXPORT_SYMBOL(ath12k_mac_op_sta_statistics);
 
@@ -12969,6 +12974,7 @@ void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
 {
        struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
        struct ath12k_fw_stats_req_params params = {};
+       struct ath12k_dp_link_peer *peer;
        struct ath12k_link_sta *arsta;
        struct ath12k *ar;
        s8 signal;
@@ -12988,33 +12994,40 @@ void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
        db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
                          ar->ab->wmi_ab.svc_map);
 
-       link_sinfo->rx_duration = arsta->rx_duration;
+       spin_lock_bh(&ar->ab->dp->dp_lock);
+       peer = ath12k_dp_link_peer_find_by_addr(ar->ab->dp, arsta->addr);
+       if (!peer) {
+               spin_unlock_bh(&ar->ab->dp->dp_lock);
+               return;
+       }
+
+       link_sinfo->rx_duration = peer->rx_duration;
        link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
 
-       link_sinfo->tx_duration = arsta->tx_duration;
+       link_sinfo->tx_duration = peer->tx_duration;
        link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
 
-       if (arsta->txrate.legacy || arsta->txrate.nss) {
-               if (arsta->txrate.legacy) {
-                       link_sinfo->txrate.legacy = arsta->txrate.legacy;
+       if (peer->txrate.legacy || peer->txrate.nss) {
+               if (peer->txrate.legacy) {
+                       link_sinfo->txrate.legacy = peer->txrate.legacy;
                } else {
-                       link_sinfo->txrate.mcs = arsta->txrate.mcs;
-                       link_sinfo->txrate.nss = arsta->txrate.nss;
-                       link_sinfo->txrate.bw = arsta->txrate.bw;
-                       link_sinfo->txrate.he_gi = arsta->txrate.he_gi;
-                       link_sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
+                       link_sinfo->txrate.mcs = peer->txrate.mcs;
+                       link_sinfo->txrate.nss = peer->txrate.nss;
+                       link_sinfo->txrate.bw = peer->txrate.bw;
+                       link_sinfo->txrate.he_gi = peer->txrate.he_gi;
+                       link_sinfo->txrate.he_dcm = peer->txrate.he_dcm;
                        link_sinfo->txrate.he_ru_alloc =
-                               arsta->txrate.he_ru_alloc;
-                       link_sinfo->txrate.eht_gi = arsta->txrate.eht_gi;
+                               peer->txrate.he_ru_alloc;
+                       link_sinfo->txrate.eht_gi = peer->txrate.eht_gi;
                        link_sinfo->txrate.eht_ru_alloc =
-                               arsta->txrate.eht_ru_alloc;
+                               peer->txrate.eht_ru_alloc;
                }
-               link_sinfo->txrate.flags = arsta->txrate.flags;
+               link_sinfo->txrate.flags = peer->txrate.flags;
                link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
        }
 
        /* TODO: Use real NF instead of default one. */
-       signal = arsta->rssi_comb;
+       signal = peer->rssi_comb;
 
        params.pdev_id = ar->pdev->pdev_id;
        params.vdev_id = 0;
@@ -13031,17 +13044,18 @@ void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
                link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
        }
 
-       link_sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
+       link_sinfo->signal_avg = ewma_avg_rssi_read(&peer->avg_rssi);
 
        if (!db2dbm)
                link_sinfo->signal_avg += ATH12K_DEFAULT_NOISE_FLOOR;
 
        link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
 
-       link_sinfo->tx_retries = arsta->tx_retry_count;
-       link_sinfo->tx_failed = arsta->tx_retry_failed;
+       link_sinfo->tx_retries = peer->tx_retry_count;
+       link_sinfo->tx_failed = peer->tx_retry_failed;
        link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
        link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+       spin_unlock_bh(&ar->ab->dp->dp_lock);
 }
 EXPORT_SYMBOL(ath12k_mac_op_link_sta_statistics);
 
index 812247decab4323413617b0be31d73521853de67..9c100ecea798e3f9a536c907a6cdf89898ffae70 100644 (file)
@@ -7,6 +7,7 @@
 #include "core.h"
 #include "peer.h"
 #include "debug.h"
+#include "debugfs.h"
 
 static int ath12k_wait_for_dp_link_peer_common(struct ath12k_base *ab, int vdev_id,
                                               const u8 *addr, bool expect_mapped)
@@ -50,6 +51,8 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id)
                            peer->addr, vdev_id);
 
                list_del(&peer->list);
+
+               kfree(peer->peer_stats.rx_stats);
                kfree(peer);
                ar->num_peers--;
        }
index 454d5a7532cfdd0135eea45a7254a180012e5b12..737651341afcd85f4f06d3fd230bfa0f5a963244 100644 (file)
@@ -517,31 +517,36 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev,
                                              struct hal_tx_status *ts)
 {
        struct ath12k_dp *dp = dp_pdev->dp;
+       struct ath12k_dp_link_peer *peer;
        struct ath12k_base *ab = dp->ab;
-       struct ath12k_dp_peer *peer;
-       struct ieee80211_sta *sta;
-       struct ath12k_sta *ahsta;
        struct ath12k_link_sta *arsta;
        struct rate_info txrate = {};
+       struct ieee80211_sta *sta;
+       struct ath12k_sta *ahsta;
        u16 rate, ru_tones;
        u8 rate_idx = 0;
        int ret;
 
-       peer = ath12k_dp_peer_find_by_peerid(dp_pdev, ts->peer_id);
+       peer = ath12k_dp_link_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);
                return;
        }
+
+       spin_lock_bh(&dp->dp_lock);
+
        sta = peer->sta;
        ahsta = ath12k_sta_to_ahsta(sta);
        arsta = &ahsta->deflink;
 
+       spin_unlock_bh(&dp->dp_lock);
+
        /* This is to prefer choose the real NSS value arsta->last_txrate.nss,
         * if it is invalid, then choose the NSS value while assoc.
         */
-       if (arsta->last_txrate.nss)
-               txrate.nss = arsta->last_txrate.nss;
+       if (peer->last_txrate.nss)
+               txrate.nss = peer->last_txrate.nss;
        else
                txrate.nss = arsta->peer_nss;
 
@@ -625,9 +630,9 @@ static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev,
                        ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(ts->tones);
        }
 
-       spin_lock_bh(&ab->base_lock);
-       arsta->txrate = txrate;
-       spin_unlock_bh(&ab->base_lock);
+       spin_lock_bh(&dp->dp_lock);
+       peer->txrate = txrate;
+       spin_unlock_bh(&dp->dp_lock);
 }
 
 static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev,
@@ -646,9 +651,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_peer *peer;
-       struct ath12k_link_sta *arsta;
-       struct ath12k_sta *ahsta;
+       struct ath12k_dp_link_peer *peer;
        struct rate_info rate;
 
        if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
@@ -743,7 +746,7 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev,
 
        ath12k_wifi7_dp_tx_update_txcompl(dp_pdev, ts);
 
-       peer = ath12k_dp_peer_find_by_peerid(dp_pdev, ts->peer_id);
+       peer = ath12k_dp_link_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",
@@ -751,13 +754,11 @@ static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev,
                ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
                goto exit;
        }
-       ahsta = ath12k_sta_to_ahsta(peer->sta);
-       arsta = &ahsta->deflink;
 
        status.sta = peer->sta;
        status.info = info;
        status.skb = msdu;
-       rate = arsta->last_txrate;
+       rate = peer->last_txrate;
 
        status_rate.rate_idx = rate;
        status_rate.try_count = 1;