* [PATCH ath-next v2 4/8] wifi: ath12k: add device DP stats reset support via debugfs
2026-08-06 12:09 [PATCH ath-next v2 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (2 preceding siblings ...)
2026-08-06 12:09 ` [PATCH ath-next v2 3/8] wifi: ath12k: add TCL ring TX buffer allocation failure counter Pardeep Kaur
@ 2026-08-06 12:09 ` Pardeep Kaur
2026-08-06 12:09 ` [PATCH ath-next v2 5/8] wifi: ath12k: add WBM RX error drop statistics Pardeep Kaur
2026-08-06 12:09 ` [PATCH ath-next v2 6/8] wifi: ath12k: track per-ring RX sent-to-stack count Pardeep Kaur
5 siblings, 0 replies; 9+ messages in thread
From: Pardeep Kaur @ 2026-08-06 12:09 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Hariharan Ramanathan, Pardeep Kaur
From: Hariharan Ramanathan <hariharan.ramanathan@oss.qualcomm.com>
There is no way to reset device DP stats counters without reloading
the driver, making it difficult to isolate issues to a specific time
window during debugging.
Add a write handler to the device_dp_stats debugfs file so that
writing 'reset' clears all device DP stats counters. Change the file
mode from 0400 to 0600 to allow write access. Use strcmp() with
newline stripping to match the input, consistent with the existing
pattern in debugfs.c. Return -EINVAL on unrecognised input.
No lock is taken around the memset since the counters are updated
locklessly in the datapath; taking dp_lock would be misleading as it
does not protect device_stats updates.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6.r1-00402-QCAHKSWPL_SILICONZ-1
Signed-off-by: Hariharan Ramanathan <hariharan.ramanathan@oss.qualcomm.com>
Co-developed-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
Signed-off-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/debugfs.c | 35 ++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index ec49692107a8..0e446a666f4c 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1220,8 +1220,41 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
return ret;
}
+static ssize_t
+ath12k_debugfs_write_device_dp_stats(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath12k_base *ab = file->private_data;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_device_dp_stats *device_stats = &dp->device_stats;
+ char buf[20] = {};
+ int ret;
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = copy_from_user(buf, user_buf, count);
+ if (ret)
+ return -EFAULT;
+
+ /* drop the possible '\n' from the end */
+ if (count > 0 && buf[count - 1] == '\n')
+ buf[count - 1] = '\0';
+
+ if (!strcmp(buf, "reset")) {
+ memset(device_stats, 0, sizeof(*device_stats));
+ return count;
+ }
+
+ ath12k_warn(ab, "unsupported command: %s\n", buf);
+
+ return -EINVAL;
+}
+
static const struct file_operations fops_device_dp_stats = {
.read = ath12k_debugfs_dump_device_dp_stats,
+ .write = ath12k_debugfs_write_device_dp_stats,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
@@ -1232,7 +1265,7 @@ void ath12k_debugfs_pdev_create(struct ath12k_base *ab)
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
&fops_simulate_fw_crash);
- debugfs_create_file("device_dp_stats", 0400, ab->debugfs_soc, ab,
+ debugfs_create_file("device_dp_stats", 0600, ab->debugfs_soc, ab,
&fops_device_dp_stats);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH ath-next v2 5/8] wifi: ath12k: add WBM RX error drop statistics
2026-08-06 12:09 [PATCH ath-next v2 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (3 preceding siblings ...)
2026-08-06 12:09 ` [PATCH ath-next v2 4/8] wifi: ath12k: add device DP stats reset support via debugfs Pardeep Kaur
@ 2026-08-06 12:09 ` Pardeep Kaur
2026-08-06 12:09 ` [PATCH ath-next v2 6/8] wifi: ath12k: track per-ring RX sent-to-stack count Pardeep Kaur
5 siblings, 0 replies; 9+ messages in thread
From: Pardeep Kaur @ 2026-08-06 12:09 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Aniruddha Mishra, Pardeep Kaur
From: Aniruddha Mishra <aniruddha.mishra@oss.qualcomm.com>
Without fine-grained drop counters, diagnosing RX failures in the
WBM error path requires intrusive debugging. Introduce per-drop-reason
counters to track exactly where and why packets are dropped during
WBM RX error handling.
Introduce a new dp_stats.h header and define ath12k_wbm_err_drop_reason
enum there covering all drop points in the WBM RX error path: descriptor
parse failures, SW descriptor retrieval errors, null partner DP,
invalid HW link ID, null pdev/ar, CAC running, scatter-gather drops,
and invalid NWifi header length. The new header is included by dp.h
which is already included by all consumers.
Add ath12k_device_dp_rx_wbm_err_stats struct grouping rxdma_error[],
reo_error[], and the new drop[] counters, replacing the flat arrays
previously in ath12k_device_dp_stats.
Add bounds checks before indexing rxdma_error[] and reo_error[] with
hardware-supplied err_code values to prevent out-of-bounds writes, using
the same likely/WARN_ON_ONCE pattern as the TX stats bounds fixes.
Add ath12k_wifi7_dp_rx_wbm_err_free_skb() helper to combine drop stat
increment and skb free at each drop site, reducing repetition. Define
the helper at the top of dp_rx.c before its first use.
Increment WBM_ERR_DROP_RXDMA_GENERIC only inside rxdma_err()'s
default: branch so it counts only unhandled RXDMA errors, not every
RXDMA drop - consistent with how WBM_ERR_DROP_REO_GENERIC is counted.
Expose WBM RX drop counts in the device_dp_stats debugfs file under a
new 'WBM Rx Drop Count' section.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6.r1-00402-QCAHKSWPL_SILICONZ-1
Signed-off-by: Aniruddha Mishra <aniruddha.mishra@oss.qualcomm.com>
Co-developed-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
Signed-off-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/debugfs.c | 23 +++++++++-
drivers/net/wireless/ath/ath12k/dp.h | 10 +++-
drivers/net/wireless/ath/ath12k/dp_stats.h | 25 ++++++++++
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 46 +++++++++++++++----
.../net/wireless/ath/ath12k/wifi7/hal_rx.c | 5 +-
5 files changed, 95 insertions(+), 14 deletions(-)
create mode 100644 drivers/net/wireless/ath/ath12k/dp_stats.h
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index 0e446a666f4c..f9653fb7b038 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1071,6 +1071,20 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
[HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET] = "PN err",
[HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED] = "Desc blocked"};
+ static const char *wbm_rx_drop[WBM_ERR_DROP_MAX] = {
+ [WBM_ERR_GET_SW_DESC] = "SW desc error",
+ [WBM_ERR_DESC_PARSE] = "Desc parse error",
+ [WBM_ERR_DROP_INV_HW_ID] = "Invalid hw id",
+ [WBM_ERR_DROP_NULL_PRTNR_DP] = "Null Partner dp",
+ [WBM_ERR_DROP_NULL_PROC_DP] = "Process Null Partner dp",
+ [WBM_ERR_DROP_NULL_PDEV] = "Null Pdev",
+ [WBM_ERR_DROP_NULL_AR] = "Null ar",
+ [WBM_ERR_DROP_CAC_RUNNING] = "CAC Running",
+ [WBM_ERR_DROP_SG] = "Scatter Gather",
+ [WBM_ERR_DROP_INV_NWIFI_HDR] = "Invalid NWifi Hdr len",
+ [WBM_ERR_DROP_REO_GENERIC] = "REO Generic",
+ [WBM_ERR_DROP_RXDMA_GENERIC] = "RXDMA Generic"};
+
static const char *wbm_rel_src[HAL_WBM_REL_SRC_MODULE_MAX] = {
[HAL_WBM_REL_SRC_MODULE_TQM] = "TQM",
[HAL_WBM_REL_SRC_MODULE_RXDMA] = "Rxdma",
@@ -1095,13 +1109,18 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
len += scnprintf(buf + len, size - len, "%s: %u\n",
- rxdma_err[i], device_stats->rxdma_error[i]);
+ rxdma_err[i], device_stats->wbm_err.rxdma_error[i]);
len += scnprintf(buf + len, size - len, "\nREO errors:\n");
for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
len += scnprintf(buf + len, size - len, "%s: %u\n",
- reo_err[i], device_stats->reo_error[i]);
+ reo_err[i], device_stats->wbm_err.reo_error[i]);
+
+ len += scnprintf(buf + len, size - len, "\nWBM Rx Drop Count:\n");
+ for (i = 0; i < WBM_ERR_DROP_MAX; i++)
+ len += scnprintf(buf + len, size - len, "%s: %u\n",
+ wbm_rx_drop[i], device_stats->wbm_err.drop[i]);
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 16675210806a..9b57b2170b60 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -7,6 +7,7 @@
#ifndef ATH12K_DP_H
#define ATH12K_DP_H
+#include "dp_stats.h"
#include "hw.h"
#include "dp_htt.h"
#include "dp_cmn.h"
@@ -437,13 +438,18 @@ struct ath12k_device_dp_tx_err_stats {
atomic_t misc_fail;
};
+struct ath12k_device_dp_rx_wbm_err_stats {
+ u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
+ u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
+ u32 drop[WBM_ERR_DROP_MAX];
+};
+
struct ath12k_device_dp_stats {
u32 err_ring_pkts;
u32 invalid_rbm;
- u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
- u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
u32 hal_reo_error[DP_REO_DST_RING_MAX];
struct ath12k_device_dp_tx_err_stats tx_err;
+ struct ath12k_device_dp_rx_wbm_err_stats wbm_err;
u32 reo_rx[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES];
u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX][ATH12K_MAX_DEVICES];
u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON];
diff --git a/drivers/net/wireless/ath/ath12k/dp_stats.h b/drivers/net/wireless/ath/ath12k/dp_stats.h
new file mode 100644
index 000000000000..04d3892acff3
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/dp_stats.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_STATS_H
+#define ATH12K_DP_STATS_H
+
+enum ath12k_wbm_err_drop_reason {
+ WBM_ERR_GET_SW_DESC,
+ WBM_ERR_DESC_PARSE,
+ WBM_ERR_DROP_INV_HW_ID,
+ WBM_ERR_DROP_NULL_PRTNR_DP,
+ WBM_ERR_DROP_NULL_PROC_DP,
+ WBM_ERR_DROP_NULL_PDEV,
+ WBM_ERR_DROP_NULL_AR,
+ WBM_ERR_DROP_CAC_RUNNING,
+ WBM_ERR_DROP_SG,
+ WBM_ERR_DROP_INV_NWIFI_HDR,
+ WBM_ERR_DROP_REO_GENERIC,
+ WBM_ERR_DROP_RXDMA_GENERIC,
+ WBM_ERR_DROP_MAX,
+};
+
+#endif /* ATH12K_DP_STATS_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index 95d87dd67872..b203513d63cc 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -12,6 +12,15 @@
#include "hal_wcn7850.h"
#include "hal_qcc2072.h"
+static void
+ath12k_wifi7_dp_rx_wbm_err_free_skb(struct ath12k_dp *dp,
+ struct sk_buff *msdu,
+ enum ath12k_wbm_err_drop_reason drop_reason)
+{
+ dp->device_stats.wbm_err.drop[drop_reason]++;
+ dev_kfree_skb_any(msdu);
+}
+
static u16 ath12k_wifi7_dp_rx_get_peer_id(struct ath12k_dp *dp,
enum ath12k_peer_metadata_version ver,
__le32 peer_metadata)
@@ -1614,6 +1623,7 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
/* First buffer will be freed by the caller, so deduct it's length */
msdu_len = msdu_len - (DP_RX_BUFFER_SIZE - hal_rx_desc_sz);
ath12k_wifi7_dp_rx_null_q_desc_sg_drop(dp, msdu_len, msdu_list);
+ dp->device_stats.wbm_err.drop[WBM_ERR_DROP_SG]++;
return -EINVAL;
}
@@ -1649,8 +1659,10 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
}
- if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu, rx_info)))
+ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu, rx_info))) {
+ dp->device_stats.wbm_err.drop[WBM_ERR_DROP_INV_NWIFI_HDR]++;
return -EINVAL;
+ }
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
@@ -1763,7 +1775,10 @@ static bool ath12k_wifi7_dp_rx_h_rxdma_err(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
bool drop = false;
- dp->device_stats.rxdma_error[rxcb->err_code]++;
+ if (likely(rxcb->err_code < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX))
+ dp->device_stats.wbm_err.rxdma_error[rxcb->err_code]++;
+ else
+ WARN_ON_ONCE(1);
switch (rxcb->err_code) {
case HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR:
@@ -1780,6 +1795,7 @@ static bool ath12k_wifi7_dp_rx_h_rxdma_err(struct ath12k_pdev_dp *dp_pdev,
/* TODO: Review other rxdma error code to check if anything is
* worth reporting to mac80211
*/
+ dp->device_stats.wbm_err.drop[WBM_ERR_DROP_RXDMA_GENERIC]++;
drop = true;
break;
}
@@ -1796,7 +1812,10 @@ static bool ath12k_wifi7_dp_rx_h_reo_err(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
bool drop = false;
- dp->device_stats.reo_error[rxcb->err_code]++;
+ if (likely(rxcb->err_code < HAL_REO_DEST_RING_ERROR_CODE_MAX))
+ dp->device_stats.wbm_err.reo_error[rxcb->err_code]++;
+ else
+ WARN_ON_ONCE(1);
switch (rxcb->err_code) {
case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
@@ -1813,6 +1832,7 @@ static bool ath12k_wifi7_dp_rx_h_reo_err(struct ath12k_pdev_dp *dp_pdev,
/* TODO: Review other errors and process them to mac80211
* as appropriate.
*/
+ dp->device_stats.wbm_err.drop[WBM_ERR_DROP_REO_GENERIC]++;
drop = true;
break;
}
@@ -1935,6 +1955,7 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
ret = ath12k_wifi7_hal_wbm_desc_parse_err(dp, rx_desc,
&err_info);
if (ret) {
+ dp->device_stats.wbm_err.drop[WBM_ERR_DESC_PARSE]++;
ath12k_warn(ab, "failed to parse rx error in wbm_rel ring desc %d\n",
ret);
continue;
@@ -1946,6 +1967,7 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
if (!desc_info) {
desc_info = ath12k_dp_get_rx_desc(dp, err_info.cookie);
if (!desc_info) {
+ dp->device_stats.wbm_err.drop[WBM_ERR_GET_SW_DESC]++;
ath12k_warn(ab, "Invalid cookie in DP WBM rx error descriptor retrieval: 0x%x\n",
err_info.cookie);
continue;
@@ -1961,7 +1983,8 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
device_id = desc_info->device_id;
partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
if (unlikely(!partner_dp)) {
- dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_wbm_err_free_skb(dp, msdu,
+ WBM_ERR_DROP_NULL_PRTNR_DP);
/* In any case continuation bit is set
* in the previous record, cleanup scatter_msdu_list
@@ -2007,7 +2030,8 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_dp->hal,
msdu_data);
if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
- dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_wbm_err_free_skb(dp, msdu,
+ WBM_ERR_DROP_INV_HW_ID);
/* In any case continuation bit is set
* in the previous record, cleanup scatter_msdu_list
@@ -2068,7 +2092,8 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
ath12k_dbg(ab, ATH12K_DBG_DATA,
"Unable to process WBM error msdu due to invalid hw link id %d device id %d\n",
hw_link_id, device_id);
- dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_wbm_err_free_skb(dp, msdu,
+ WBM_ERR_DROP_NULL_PROC_DP);
continue;
}
@@ -2077,18 +2102,21 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
dp_pdev = ath12k_dp_to_pdev_dp(partner_dp, pdev_idx);
if (!dp_pdev) {
- dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_wbm_err_free_skb(dp, msdu,
+ WBM_ERR_DROP_NULL_PDEV);
continue;
}
ar = ath12k_pdev_dp_to_ar(dp_pdev);
if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_idx])) {
- dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_wbm_err_free_skb(dp, msdu,
+ WBM_ERR_DROP_NULL_AR);
continue;
}
if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
- dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_wbm_err_free_skb(dp, msdu,
+ WBM_ERR_DROP_CAC_RUNNING);
continue;
}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c
index 49c693289709..60e7a36097f1 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c
@@ -329,7 +329,10 @@ int ath12k_wifi7_hal_desc_reo_parse_err(struct ath12k_dp *dp,
HAL_REO_DEST_RING_INFO0_PUSH_REASON);
err_code = le32_get_bits(desc->info0,
HAL_REO_DEST_RING_INFO0_ERROR_CODE);
- dp->device_stats.reo_error[err_code]++;
+ if (likely(err_code < HAL_REO_DEST_RING_ERROR_CODE_MAX))
+ dp->device_stats.wbm_err.reo_error[err_code]++;
+ else
+ WARN_ON_ONCE(1);
if (push_reason != HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED &&
push_reason != HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH ath-next v2 6/8] wifi: ath12k: track per-ring RX sent-to-stack count
2026-08-06 12:09 [PATCH ath-next v2 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (4 preceding siblings ...)
2026-08-06 12:09 ` [PATCH ath-next v2 5/8] wifi: ath12k: add WBM RX error drop statistics Pardeep Kaur
@ 2026-08-06 12:09 ` Pardeep Kaur
5 siblings, 0 replies; 9+ messages in thread
From: Pardeep Kaur @ 2026-08-06 12:09 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Hariharan Ramanathan, Pardeep Kaur
From: Hariharan Ramanathan <hariharan.ramanathan@oss.qualcomm.com>
The device DP stats provide visibility into RX errors and drops but
lack a counter for successfully delivered packets. Without this, it is
difficult to correlate REO ring activity with actual stack delivery
during debugging or performance analysis.
Add sent_to_stack[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES] to
ath12k_device_dp_stats to track successful deliveries per REO ring per
device. The counter is attributed to the ring owner's dp and indexed by
partner_dp->device_id, keeping it in the same debugfs file as reo_rx[]
for direct comparison in MLO configurations.
Increment the counter just before each MSDU is handed off to the stack
via ath12k_dp_rx_deliver_msdu(). Add a likely()/WARN_ON_ONCE() bounds
check on ring_id before indexing sent_to_stack[], consistent with all
other new stat arrays in this series.
Expose the per-ring per-device counts in the device_dp_stats debugfs
file under a new 'REO sent to stack' section.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6.r1-00402-QCAHKSWPL_SILICONZ-1
Signed-off-by: Hariharan Ramanathan <hariharan.ramanathan@oss.qualcomm.com>
Co-developed-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
Signed-off-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/debugfs.c | 10 ++++++++++
drivers/net/wireless/ath/ath12k/dp.h | 1 +
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 5 ++++-
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index f9653fb7b038..216a1af22898 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1122,6 +1122,16 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "%s: %u\n",
wbm_rx_drop[i], device_stats->wbm_err.drop[i]);
+ len += scnprintf(buf + len, size - len, "\nREO sent to stack\n");
+ for (i = 0; i < DP_REO_DST_RING_MAX; i++) {
+ len += scnprintf(buf + len, size - len, "ring%d:", i);
+ for (j = 0; j < ab->ag->num_devices; j++)
+ len += scnprintf(buf + len, size - len,
+ "\t%d:%u", j,
+ device_stats->sent_to_stack[i][j]);
+ len += scnprintf(buf + len, size - len, "\n");
+ }
+
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
for (i = 0; i < DP_REO_DST_RING_MAX; i++)
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 9b57b2170b60..5cfe2096c633 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -458,6 +458,7 @@ struct ath12k_device_dp_stats {
u32 tx_enqueued[DP_TCL_NUM_RING_MAX];
u32 tx_completed[DP_TCL_NUM_RING_MAX];
u32 reo_excep_msdu_buf_type;
+ u32 sent_to_stack[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES];
};
struct ath12k_dp {
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index b203513d63cc..60489cfd4e54 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -651,7 +651,10 @@ ath12k_wifi7_dp_rx_process_received_packets(struct ath12k_dp *dp,
dev_kfree_skb_any(msdu);
continue;
}
-
+ if (likely(ring_id < DP_REO_DST_RING_MAX))
+ dp->device_stats.sent_to_stack[ring_id][partner_dp->device_id]++;
+ else
+ WARN_ON_ONCE(1);
ath12k_dp_rx_deliver_msdu(dp_pdev, napi, msdu, &rx_info);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread