]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: ath12k: add link support for multi-link in arsta
authorSarika Sharma <quic_sarishar@quicinc.com>
Tue, 1 Jul 2025 10:59:24 +0000 (16:29 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Mon, 7 Jul 2025 22:34:48 +0000 (15:34 -0700)
Currently, statistics in arsta are updated at deflink for both non-ML
and multi-link(ML) station. Link statistics are not updated for
multi-link operation(MLO).

Hence, add support to correctly obtain the link ID if the peer is ML,
fetch the arsta from the appropriate link ID, and update the
statistics in the corresponding arsta.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250701105927.803342-3-quic_sarishar@quicinc.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_mon.c
drivers/net/wireless/ath/ath12k/dp_rx.c
drivers/net/wireless/ath/ath12k/peer.h

index b408103fe9d4703c44a0fde456b71bb7aaf6420c..8189e52ed00718995572ba1e1c3cc26756846d20 100644 (file)
@@ -3615,7 +3615,6 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
                                   struct hal_rx_mon_ppdu_info *ppdu_info,
                                   u32 uid)
 {
-       struct ath12k_sta *ahsta;
        struct ath12k_link_sta *arsta;
        struct ath12k_rx_peer_stats *rx_stats = NULL;
        struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid];
@@ -3633,8 +3632,13 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
                return;
        }
 
-       ahsta = ath12k_sta_to_ahsta(peer->sta);
-       arsta = &ahsta->deflink;
+       arsta = ath12k_peer_get_link_sta(ar->ab, peer);
+       if (!arsta) {
+               ath12k_warn(ar->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;
@@ -3747,7 +3751,6 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,
        struct dp_srng *mon_dst_ring;
        struct hal_srng *srng;
        struct dp_rxdma_mon_ring *buf_ring;
-       struct ath12k_sta *ahsta = NULL;
        struct ath12k_link_sta *arsta;
        struct ath12k_peer *peer;
        struct sk_buff_head skb_list;
@@ -3873,8 +3876,15 @@ move_next:
                }
 
                if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
-                       ahsta = ath12k_sta_to_ahsta(peer->sta);
-                       arsta = &ahsta->deflink;
+                       arsta = ath12k_peer_get_link_sta(ar->ab, peer);
+                       if (!arsta) {
+                               ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n",
+                                           peer->addr, peer->peer_id);
+                               spin_unlock_bh(&ab->base_lock);
+                               rcu_read_unlock();
+                               dev_kfree_skb_any(skb);
+                               continue;
+                       }
                        ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
                                                              ppdu_info);
                } else if ((ppdu_info->fc_valid) &&
index 420a9b161f4a222895036d5ba2b6849ddb7c527d..f0cfe03d74b6628aabf910a31d7f5b11a1fcb8f0 100644 (file)
@@ -1417,8 +1417,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
 {
        struct ath12k_base *ab = ar->ab;
        struct ath12k_peer *peer;
-       struct ieee80211_sta *sta;
-       struct ath12k_sta *ahsta;
        struct ath12k_link_sta *arsta;
        struct htt_ppdu_stats_user_rate *user_rate;
        struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats;
@@ -1499,9 +1497,12 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
                return;
        }
 
-       sta = peer->sta;
-       ahsta = ath12k_sta_to_ahsta(sta);
-       arsta = &ahsta->deflink;
+       arsta = ath12k_peer_get_link_sta(ab, peer);
+       if (!arsta) {
+               spin_unlock_bh(&ab->base_lock);
+               rcu_read_unlock();
+               return;
+       }
 
        memset(&arsta->txrate, 0, sizeof(arsta->txrate));
 
index f3a5e054d2b556374c0560b322e36fb26c3da3c2..92c4988df2f1658058a2e89a9bcb45b24339e801 100644 (file)
@@ -91,5 +91,31 @@ 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);
+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_ */