]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Add support TX hardware queue stats
authorAaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
Fri, 23 Jan 2026 07:12:53 +0000 (12:42 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Fri, 30 Jan 2026 15:12:38 +0000 (07:12 -0800)
Add support to request and receive TX hardware queue stats using
HTT stats type 3. This stats type reports MPDU mac id and hardware
queue information, including xretry, BAR, RTS, CTS, self, and QoS-null
counts, along with underrun, flush, and filter counters.

Sample output:
-------------
echo 3 >/sys/kernel/debug/ath12k/pci-0000\:58\:00.0/mac0/htt_stats_type
cat /sys/kernel/debug/ath12k/pci-0000\:58\:00.0/mac0/htt_stats

HTT_TX_HWQ_STATS_CMN_TLV:
mac_id = 0
hwq_id = 0
xretry = 0
underrun_cnt = 0
flush_cnt = 0
filt_cnt = 0
null_mpdu_bmap = 0
user_ack_failure = 379
ack_tlv_proc = 0
sched_id_proc = 0
null_mpdu_tx_count = 0
mpdu_bmap_not_recvd = 0
num_bar = 0
rts = 0
cts2self = 0
qos_null = 0
mpdu_tried_cnt = 379
mpdu_queued_cnt = 379
mpdu_ack_fail_cnt = 0
mpdu_filt_cnt = 0
false_mpdu_ack_count = 0
txq_timeout = 0

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20260123071253.2202644-4-aaradhana.sahu@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h

index a667eb9966c9c1a51213d356c5f71544f96f942b..7f6ca07fb3359984acc08fee6dbb071adeba5a19 100644 (file)
@@ -5661,6 +5661,67 @@ ath12k_htt_print_rx_pdev_fw_stats_tlv(const void *tag_buf, u16 tag_len,
        stats_req->buf_len = len;
 }
 
+static void
+ath12k_htt_print_tx_hwq_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
+                                     struct debug_htt_stats_req *stats_req)
+{
+       const struct htt_tx_hwq_stats_cmn_tlv *htt_stats_buf = tag_buf;
+       u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+       u32 len = stats_req->buf_len;
+       u8 *buf = stats_req->buf;
+
+       if (tag_len < sizeof(*htt_stats_buf))
+               return;
+
+       len += scnprintf(buf + len, buf_len - len, "HTT_TX_HWQ_STATS_CMN_TLV:\n");
+       len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+                       le32_to_cpu(htt_stats_buf->mac_id__hwq_id__word) & 0xFF);
+       len += scnprintf(buf + len, buf_len - len, "hwq_id = %u\n",
+                       (le32_to_cpu(htt_stats_buf->mac_id__hwq_id__word) & 0xFF00) >> 8);
+       len += scnprintf(buf + len, buf_len - len, "xretry = %u\n",
+                       le32_to_cpu(htt_stats_buf->xretry));
+       len += scnprintf(buf + len, buf_len - len, "underrun_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->underrun_cnt));
+       len += scnprintf(buf + len, buf_len - len, "flush_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->flush_cnt));
+       len += scnprintf(buf + len, buf_len - len, "filt_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->filt_cnt));
+       len += scnprintf(buf + len, buf_len - len, "null_mpdu_bmap = %u\n",
+                       le32_to_cpu(htt_stats_buf->null_mpdu_bmap));
+       len += scnprintf(buf + len, buf_len - len, "user_ack_failure = %u\n",
+                       le32_to_cpu(htt_stats_buf->user_ack_failure));
+       len += scnprintf(buf + len, buf_len - len, "ack_tlv_proc = %u\n",
+                       le32_to_cpu(htt_stats_buf->ack_tlv_proc));
+       len += scnprintf(buf + len, buf_len - len, "sched_id_proc = %u\n",
+                       le32_to_cpu(htt_stats_buf->sched_id_proc));
+       len += scnprintf(buf + len, buf_len - len, "null_mpdu_tx_count = %u\n",
+                       le32_to_cpu(htt_stats_buf->null_mpdu_tx_count));
+       len += scnprintf(buf + len, buf_len - len, "mpdu_bmap_not_recvd = %u\n",
+                       le32_to_cpu(htt_stats_buf->mpdu_bmap_not_recvd));
+       len += scnprintf(buf + len, buf_len - len, "num_bar = %u\n",
+                       le32_to_cpu(htt_stats_buf->num_bar));
+       len += scnprintf(buf + len, buf_len - len, "rts = %u\n",
+                       le32_to_cpu(htt_stats_buf->rts));
+       len += scnprintf(buf + len, buf_len - len, "cts2self = %u\n",
+                       le32_to_cpu(htt_stats_buf->cts2self));
+       len += scnprintf(buf + len, buf_len - len, "qos_null = %u\n",
+                       le32_to_cpu(htt_stats_buf->qos_null));
+       len += scnprintf(buf + len, buf_len - len, "mpdu_tried_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->mpdu_tried_cnt));
+       len += scnprintf(buf + len, buf_len - len, "mpdu_queued_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->mpdu_queued_cnt));
+       len += scnprintf(buf + len, buf_len - len, "mpdu_ack_fail_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->mpdu_ack_fail_cnt));
+       len += scnprintf(buf + len, buf_len - len, "mpdu_filt_cnt = %u\n",
+                       le32_to_cpu(htt_stats_buf->mpdu_filt_cnt));
+       len += scnprintf(buf + len, buf_len - len, "false_mpdu_ack_count = %u\n",
+                       le32_to_cpu(htt_stats_buf->false_mpdu_ack_count));
+       len += scnprintf(buf + len, buf_len - len, "txq_timeout = %u\n",
+                       le32_to_cpu(htt_stats_buf->txq_timeout));
+
+       stats_req->buf_len = len;
+}
+
 static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
                                          u16 tag, u16 len, const void *tag_buf,
                                          void *user_data)
@@ -5960,6 +6021,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
        case HTT_STATS_PDEV_RTT_TBR_CMD_RESULT_STATS_TAG:
                ath12k_htt_print_pdev_rtt_tbr_cmd_res_stats_tlv(tag_buf, len, stats_req);
                break;
+       case HTT_STATS_TX_HWQ_CMN_TAG:
+               ath12k_htt_print_tx_hwq_stats_cmn_tlv(tag_buf, len, stats_req);
+               break;
        default:
                break;
        }
index a6656f20b84579a6ef4be940600b35022511bef1..bfabe6500d44d9031f8355a135462235f2504356 100644 (file)
@@ -128,6 +128,7 @@ enum ath12k_dbg_htt_ext_stats_type {
        ATH12K_DBG_HTT_EXT_STATS_RESET                          = 0,
        ATH12K_DBG_HTT_EXT_STATS_PDEV_TX                        = 1,
        ATH12K_DBG_HTT_EXT_STATS_PDEV_RX                        = 2,
+       ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ                    = 3,
        ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED                  = 4,
        ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR                     = 5,
        ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM                       = 6,
@@ -174,6 +175,7 @@ enum ath12k_dbg_htt_tlv_tag {
        HTT_STATS_TX_PDEV_SIFS_TAG                      = 2,
        HTT_STATS_TX_PDEV_FLUSH_TAG                     = 3,
        HTT_STATS_STRING_TAG                            = 5,
+       HTT_STATS_TX_HWQ_CMN_TAG                        = 6,
        HTT_STATS_TX_TQM_GEN_MPDU_TAG                   = 11,
        HTT_STATS_TX_TQM_LIST_MPDU_TAG                  = 12,
        HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG              = 13,
@@ -2130,4 +2132,28 @@ struct htt_rx_pdev_fw_stats_tlv {
        __le32 bytes_received_high_32;
 } __packed;
 
+struct htt_tx_hwq_stats_cmn_tlv {
+       __le32 mac_id__hwq_id__word;
+       __le32 xretry;
+       __le32 underrun_cnt;
+       __le32 flush_cnt;
+       __le32 filt_cnt;
+       __le32 null_mpdu_bmap;
+       __le32 user_ack_failure;
+       __le32 ack_tlv_proc;
+       __le32 sched_id_proc;
+       __le32 null_mpdu_tx_count;
+       __le32 mpdu_bmap_not_recvd;
+       __le32 num_bar;
+       __le32 rts;
+       __le32 cts2self;
+       __le32 qos_null;
+       __le32 mpdu_tried_cnt;
+       __le32 mpdu_queued_cnt;
+       __le32 mpdu_ack_fail_cnt;
+       __le32 mpdu_filt_cnt;
+       __le32 false_mpdu_ack_count;
+       __le32 txq_timeout;
+} __packed;
+
 #endif