]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: ath12k: account TX stats only when ACK/BA status is present
authorSarika Sharma <sarika.sharma@oss.qualcomm.com>
Thu, 26 Feb 2026 05:19:47 +0000 (10:49 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Fri, 6 Mar 2026 20:23:15 +0000 (12:23 -0800)
The fields tx_retry_failed, tx_retry_count, and tx_duration are
currently updated outside the HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS
flag check. In certain scenarios, firmware delivers multiple PPDU
statistics for the same PPDU, first without BA/ACK information, and
later with BA/ACK status once it becomes available. As the same PPDU
is processed again, these counters are updated a second time,
resulting in duplicate TX statistics.

To address this, move the accounting of tx_retry_failed and
tx_retry_count under the ACK/BA status flag check, and similarly gate
tx_duration on the same path. This ensures that each PPDU contributes
to these counters exactly once, avoids double counting, and provides
consistent reporting in userspace tools such as station dump.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1

Fixes: a0b963e1da5b ("wifi: ath12k: fetch tx_retry and tx_failed from htt_ppdu_stats_user_cmpltn_common_tlv")
Signed-off-by: Sarika Sharma <sarika.sharma@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20260226051947.1379716-1-sarika.sharma@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_htt.c

index e71bb71a6020e018f2035536b0d8119ce6e9c33d..9c19d9707abfb564567eee2d486a390fc8b03483 100644 (file)
@@ -205,16 +205,9 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,
        if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))
                return;
 
-       if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
+       if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON))
                is_ampdu =
                        HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);
-               tx_retry_failed =
-                       __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
-                       __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
-               tx_retry_count =
-                       HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
-                       HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
-       }
 
        if (usr_stats->tlv_flags &
            BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {
@@ -223,10 +216,19 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,
                                          HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);
                tid = le32_get_bits(usr_stats->ack_ba.info,
                                    HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);
-       }
 
-       if (common->fes_duration_us)
-               tx_duration = le32_to_cpu(common->fes_duration_us);
+               if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
+                       tx_retry_failed =
+                               __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
+                               __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
+                       tx_retry_count =
+                               HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
+                               HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
+               }
+
+               if (common->fes_duration_us)
+                       tx_duration = le32_to_cpu(common->fes_duration_us);
+       }
 
        user_rate = &usr_stats->rate;
        flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);