]> git.ipfire.org Git - thirdparty/kernel/stable.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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 19 Sep 2025 14:37:35 +0000 (16:37 +0200)
[ Upstream commit 3b8aa249d0fce93590888a6ed3d22b458091ecb9 ]

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>
Stable-dep-of: 82e2be57d544 ("wifi: ath12k: fix WMI TLV header misalignment")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/ath/ath12k/dp_mon.c
drivers/net/wireless/ath/ath12k/dp_rx.c
drivers/net/wireless/ath/ath12k/peer.h

index 91f4e3aff74c3804188af69fd9bb81103dc88175..6a0915a0c7aae3760ef8152570769f8f8511d434 100644 (file)
@@ -3610,7 +3610,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];
@@ -3628,8 +3627,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;
@@ -3742,7 +3746,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;
@@ -3868,8 +3871,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 bd95dc88f9b21f7afb7fdc7cd91844c4cb78da1e..e9137ffeb5ab48ec013aa068a4766d7321662e00 100644 (file)
@@ -1418,8 +1418,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;
@@ -1500,9 +1498,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_ */