* [PATCH ath-next v3 1/8] wifi: ath12k: fix out-of-bounds access on TX stats arrays
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 2/8] wifi: ath12k: rename wbm_status to htt_status in HTT TX completion Pardeep Kaur
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pardeep Kaur
From: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
The fw_tx_status[], tx_wbm_rel_source[], and tqm_rel_reason[] arrays
are indexed directly by values read from hardware without bounds checks.
Values at or beyond MAX_FW_TX_STATUS, HAL_WBM_REL_SRC_MODULE_MAX, or
MAX_TQM_RELEASE_REASON respectively would write past the end of the
arrays causing memory corruption.
Add likely() bounds checks before incrementing each counter. For
tx_wbm_rel_source[] and tqm_rel_reason[], add WARN_ON_ONCE() on the
out-of-bounds else branch. For fw_tx_status[], no WARN_ON_ONCE is added
since the switch statement that follows already calls ath12k_warn() in
its default: branch for unknown values, avoiding a double-warn.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6.r1-00402-QCAHKSWPL_SILICONZ-1
Fixes: c5c62287e690 ("wifi: ath12k: Add device dp stats support")
Signed-off-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
index 587d58eeccfa..3d635cac8f8c 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
@@ -582,7 +582,8 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_dp *dp, void *desc,
wbm_status = le32_get_bits(status_desc->info0,
HTT_TX_WBM_COMP_INFO0_STATUS);
- dp->device_stats.fw_tx_status[wbm_status]++;
+ if (likely(wbm_status < MAX_FW_TX_STATUS))
+ dp->device_stats.fw_tx_status[wbm_status]++;
switch (wbm_status) {
case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
@@ -984,11 +985,17 @@ void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_dp *dp, int ring_id)
/* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */
buf_rel_source = le32_get_bits(tx_status->info0,
HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE);
- dp->device_stats.tx_wbm_rel_source[buf_rel_source]++;
+ if (likely(buf_rel_source < HAL_WBM_REL_SRC_MODULE_MAX))
+ dp->device_stats.tx_wbm_rel_source[buf_rel_source]++;
+ else
+ WARN_ON_ONCE(1);
rel_status = le32_get_bits(tx_status->info0,
HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
- dp->device_stats.tqm_rel_reason[rel_status]++;
+ if (likely(rel_status < MAX_TQM_RELEASE_REASON))
+ dp->device_stats.tqm_rel_reason[rel_status]++;
+ else
+ WARN_ON_ONCE(1);
/* Release descriptor as soon as extracting necessary info
* to reduce contention
base-commit: 691e5e43b2aa
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH ath-next v3 2/8] wifi: ath12k: rename wbm_status to htt_status in HTT TX completion
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 1/8] wifi: ath12k: fix out-of-bounds access on TX stats arrays Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 3/8] wifi: ath12k: add TCL ring TX buffer allocation failure counter Pardeep Kaur
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Hariharan Ramanathan, Pardeep Kaur
From: Hariharan Ramanathan <hariharan.ramanathan@oss.qualcomm.com>
The variable wbm_status in ath12k_dp_tx_process_htt_tx_complete()
holds a value from the HTT TX WBM completion status field, not a
generic WBM status. Rename it to htt_status to accurately reflect
the field origin and improve code clarity.
Also fix ts.acked assignment inside the HAL_WBM_REL_HTT_TX_COMP_STATUS_OK
case to use true directly since the condition is always true within
that case branch.
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/wifi7/dp_tx.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
index 3d635cac8f8c..a8afc1cb0712 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
@@ -575,19 +575,19 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_dp *dp, void *desc,
{
struct htt_tx_wbm_completion *status_desc;
struct ath12k_dp_htt_wbm_tx_status ts = {};
- enum hal_wbm_htt_tx_comp_status wbm_status;
+ enum hal_wbm_htt_tx_comp_status htt_status;
u16 peer_id;
status_desc = desc;
- wbm_status = le32_get_bits(status_desc->info0,
+ htt_status = le32_get_bits(status_desc->info0,
HTT_TX_WBM_COMP_INFO0_STATUS);
- if (likely(wbm_status < MAX_FW_TX_STATUS))
- dp->device_stats.fw_tx_status[wbm_status]++;
+ if (likely(htt_status < MAX_FW_TX_STATUS))
+ dp->device_stats.fw_tx_status[htt_status]++;
- switch (wbm_status) {
+ switch (htt_status) {
case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
- ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK);
+ ts.acked = true;
ts.ack_rssi = le32_get_bits(status_desc->info2,
HTT_TX_WBM_COMP_INFO2_ACK_RSSI);
@@ -609,7 +609,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_dp *dp, void *desc,
*/
break;
default:
- ath12k_warn(dp->ab, "Unknown htt wbm tx status %d\n", wbm_status);
+ ath12k_warn(dp->ab, "Unknown htt tx status %d\n", htt_status);
break;
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH ath-next v3 3/8] wifi: ath12k: add TCL ring TX buffer allocation failure counter
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 1/8] wifi: ath12k: fix out-of-bounds access on TX stats arrays Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 2/8] wifi: ath12k: rename wbm_status to htt_status in HTT TX completion Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 4/8] wifi: ath12k: add device DP stats reset support via debugfs Pardeep Kaur
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Hariharan Ramanathan, Pardeep Kaur
From: Hariharan Ramanathan <hariharan.ramanathan@oss.qualcomm.com>
When ath12k_dp_tx_assign_buffer() fails, the TX path returns -ENOMEM
silently with no visibility into which traffic class is affected.
Without a counter, TX descriptor pool exhaustion is invisible during
debugging.
Add txbuf_na[] indexed by pool_id to ath12k_device_dp_tx_err_stats to
track TX descriptor pool allocation failures per traffic class and
increment it on assign failure in the TX path. Expose the per-pool
counts in debugfs under a new 'TX Descriptor Pool Alloc Failures'
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 | 5 +++++
drivers/net/wireless/ath/ath12k/dp.h | 2 ++
drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c | 4 +++-
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index d54995b7adb2..ec49692107a8 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1117,6 +1117,11 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
i, device_stats->tx_err.desc_na[i]);
+ len += scnprintf(buf + len, size - len, "\nTX Descriptor Pool Alloc Failures:\n");
+ for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++)
+ len += scnprintf(buf + len, size - len, "pool%d: %u\n",
+ i, device_stats->tx_err.txbuf_na[i]);
+
len += scnprintf(buf + len, size - len,
"\nMisc Transmit Failures: %d\n",
atomic_read(&device_stats->tx_err.misc_fail));
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index bef0f2ba0560..16675210806a 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -429,6 +429,8 @@ struct ath12k_dp_arch_ops {
struct ath12k_device_dp_tx_err_stats {
/* TCL Ring Descriptor unavailable */
u32 desc_na[DP_TCL_NUM_RING_MAX];
+ /* TX descriptor pool exhausted (per pool_id / traffic class) */
+ u32 txbuf_na[ATH12K_HW_MAX_QUEUES];
/* Other failures during dp_tx due to mem allocation failure
* idr unavailable etc.
*/
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
index a8afc1cb0712..11048c568331 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
@@ -167,8 +167,10 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
tx_ring = &dp->tx_ring[ti.ring_id];
tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id);
- if (!tx_desc)
+ if (!tx_desc) {
+ dp->device_stats.tx_err.txbuf_na[pool_id]++;
return -ENOMEM;
+ }
dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, arvif->link_id);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH ath-next v3 4/8] wifi: ath12k: add device DP stats reset support via debugfs
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (2 preceding siblings ...)
2026-08-10 14:44 ` [PATCH ath-next v3 3/8] wifi: ath12k: add TCL ring TX buffer allocation failure counter Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 20:12 ` Jeff Johnson
2026-08-10 14:44 ` [PATCH ath-next v3 5/8] wifi: ath12k: add WBM RX error drop statistics Pardeep Kaur
` (3 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 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
simple_write_to_buffer() to correctly handle partial writes and
non-zero ppos, consistent with ath12k_write_simulate_fw_crash() in
the same file. 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 | 36 ++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index ec49692107a8..cbda754d8656 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1220,8 +1220,42 @@ 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;
+
+ /* filter partial writes and invalid commands */
+ if (*ppos != 0 || count >= sizeof(buf) || count == 0)
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+ if (ret < 0)
+ return ret;
+
+ /* drop the possible '\n' from the end */
+ if (buf[*ppos - 1] == '\n')
+ buf[*ppos - 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 +1266,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] 11+ messages in thread* Re: [PATCH ath-next v3 4/8] wifi: ath12k: add device DP stats reset support via debugfs
2026-08-10 14:44 ` [PATCH ath-next v3 4/8] wifi: ath12k: add device DP stats reset support via debugfs Pardeep Kaur
@ 2026-08-10 20:12 ` Jeff Johnson
0 siblings, 0 replies; 11+ messages in thread
From: Jeff Johnson @ 2026-08-10 20:12 UTC (permalink / raw)
To: Pardeep Kaur, ath12k; +Cc: linux-wireless, Hariharan Ramanathan
On 8/10/2026 7:44 AM, Pardeep Kaur wrote:
> 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
> simple_write_to_buffer() to correctly handle partial writes and
> non-zero ppos, consistent with ath12k_write_simulate_fw_crash() in
> the same file. 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 | 36 ++++++++++++++++++++++-
> 1 file changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
> index ec49692107a8..cbda754d8656 100644
> --- a/drivers/net/wireless/ath/ath12k/debugfs.c
> +++ b/drivers/net/wireless/ath/ath12k/debugfs.c
> @@ -1220,8 +1220,42 @@ 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;
> +
> + /* filter partial writes and invalid commands */
> + if (*ppos != 0 || count >= sizeof(buf) || count == 0)
> + return -EINVAL;
> +
> + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
> + if (ret < 0)
> + return ret;
> +
> + /* drop the possible '\n' from the end */
> + if (buf[*ppos - 1] == '\n')
> + buf[*ppos - 1] = '\0';
> +
> + if (!strcmp(buf, "reset")) {
> + memset(device_stats, 0, sizeof(*device_stats));
> + return count;
> + }
> +
> + ath12k_warn(ab, "unsupported command: %s\n", buf);
drop this.
ath12k_warn() is used to warn about inconsistent state, not user input.
The -EINVAL return is already the correct user-facing mechanism for returning
status. Note all the other .write() functions silently return -EINVAL on an
invalid argument.
> +
> + 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 +1266,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);
> }
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH ath-next v3 5/8] wifi: ath12k: add WBM RX error drop statistics
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (3 preceding siblings ...)
2026-08-10 14:44 ` [PATCH ath-next v3 4/8] wifi: ath12k: add device DP stats reset support via debugfs Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 20:16 ` Jeff Johnson
2026-08-10 14:44 ` [PATCH ath-next v3 6/8] wifi: ath12k: track per-ring RX sent-to-stack count Pardeep Kaur
` (2 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 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 cbda754d8656..34c605b609cb 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] 11+ messages in thread* Re: [PATCH ath-next v3 5/8] wifi: ath12k: add WBM RX error drop statistics
2026-08-10 14:44 ` [PATCH ath-next v3 5/8] wifi: ath12k: add WBM RX error drop statistics Pardeep Kaur
@ 2026-08-10 20:16 ` Jeff Johnson
0 siblings, 0 replies; 11+ messages in thread
From: Jeff Johnson @ 2026-08-10 20:16 UTC (permalink / raw)
To: Pardeep Kaur, ath12k; +Cc: linux-wireless, Aniruddha Mishra
On 8/10/2026 7:44 AM, Pardeep Kaur wrote:
> diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
> index cbda754d8656..34c605b609cb 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",
nit: extra space before =
> + [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",...> 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,
nit: why aren't these two also WBM_ERR_DROP_*
> + 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 */
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH ath-next v3 6/8] wifi: ath12k: track per-ring RX sent-to-stack count
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (4 preceding siblings ...)
2026-08-10 14:44 ` [PATCH ath-next v3 5/8] wifi: ath12k: add WBM RX error drop statistics Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 7/8] wifi: ath12k: fix 1-based ring index in REO Rx Received debugfs output Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 8/8] wifi: ath12k: add WBM SW desc fallback counter Pardeep Kaur
7 siblings, 0 replies; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 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 34c605b609cb..55e3b411d108 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] 11+ messages in thread* [PATCH ath-next v3 7/8] wifi: ath12k: fix 1-based ring index in REO Rx Received debugfs output
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (5 preceding siblings ...)
2026-08-10 14:44 ` [PATCH ath-next v3 6/8] wifi: ath12k: track per-ring RX sent-to-stack count Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
2026-08-10 14:44 ` [PATCH ath-next v3 8/8] wifi: ath12k: add WBM SW desc fallback counter Pardeep Kaur
7 siblings, 0 replies; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pardeep Kaur
From: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
The REO Rx Received section in device_dp_stats debugfs uses a 1-based
ring index ("Ring1:", "Ring2:", ...) which is inconsistent with the rest
of ath12k where rings are indexed from 0. Fix it to use 0-based indexing
and lowercase "ring%d:" to match the style used by all other ring counters
in the same function.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6.r1-00402-QCAHKSWPL_SILICONZ-1
Signed-off-by: Pardeep Kaur <pardeep.kaur@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/debugfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index 55e3b411d108..fe513b3489bc 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1215,7 +1215,7 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
for (i = 0; i < DP_REO_DST_RING_MAX; i++) {
- len += scnprintf(buf + len, size - len, "Ring%d:", i + 1);
+ len += scnprintf(buf + len, size - len, "ring%d:", i);
for (j = 0; j < ab->ag->num_devices; j++) {
len += scnprintf(buf + len, size - len,
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH ath-next v3 8/8] wifi: ath12k: add WBM SW desc fallback counter
2026-08-10 14:44 [PATCH ath-next v3 0/8] wifi: ath12k: extend device DP stats for TX and RX observability Pardeep Kaur
` (6 preceding siblings ...)
2026-08-10 14:44 ` [PATCH ath-next v3 7/8] wifi: ath12k: fix 1-based ring index in REO Rx Received debugfs output Pardeep Kaur
@ 2026-08-10 14:44 ` Pardeep Kaur
7 siblings, 0 replies; 11+ messages in thread
From: Pardeep Kaur @ 2026-08-10 14:44 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Aniruddha Mishra, Pardeep Kaur
From: Aniruddha Mishra <aniruddha.mishra@oss.qualcomm.com>
When HW CC is not done, the WBM RX error path falls back to
cookie-based descriptor retrieval via ath12k_dp_get_rx_desc(). This
fallback path is taken before knowing whether the retrieval will
succeed, so it is not a drop event and should not be counted in the
drop[] array.
Add a dedicated sw_desc_fallback counter in
ath12k_device_dp_rx_wbm_err_stats to track how often the HW CC
fallback path is taken, distinct from actual packet drops. Expose
the counter in the device_dp_stats debugfs file as a separate line.
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 | 4 ++++
drivers/net/wireless/ath/ath12k/dp.h | 1 +
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 1 +
3 files changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index fe513b3489bc..d2d89a7e340d 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1122,6 +1122,10 @@ 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,
+ "\nWBM SW desc fallback (HW CC not done): %u\n",
+ device_stats->wbm_err.sw_desc_fallback);
+
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);
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 5cfe2096c633..289aede6dabb 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -442,6 +442,7 @@ 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];
+ u32 sw_desc_fallback;
};
struct ath12k_device_dp_stats {
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index 60489cfd4e54..d96d8301565c 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -1968,6 +1968,7 @@ int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
/* retry manual desc retrieval if hw cc is not done */
if (!desc_info) {
+ dp->device_stats.wbm_err.sw_desc_fallback++;
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]++;
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread