* [PATCH v3] wifi: ath12k: Add WMI control path stats infra
@ 2025-01-20 18:44 Ramya Gnanasekar
2025-01-21 4:40 ` Aditya Kumar Singh
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Ramya Gnanasekar @ 2025-01-20 18:44 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Rajat Soni, Ramya Gnanasekar
From: Rajat Soni <rajat.soni@oss.qualcomm.com>
Currently, firmware stats is requested by host through HTT interface.
Since HTT interface is already overloaded for data path stats,
leveraging control path to request other stats through WMI interface.
Add debugfs to request the stats and dump the stats forwarded by firmware.
ath12k
`-- pci-0000:06:00.0
|-- mac0
`-- wmi_ctrl_stats
This patch also adds support to request PDEV Tx stats, parse and dump
the data sent from firmware.
Usage:
echo <stats id> <action> > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/wmi_ctrl_stats
Sample:
echo 1 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/wmi_ctrl_stats
cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/wmi_ctrl_stats
WMI_CTRL_PATH_PDEV_TX_STATS:
fw_tx_mgmt_subtype = 0:0, 1:2, 2:0, 3:0, 4:0, 5:37, 6:0, 7:0, 8:908, 9:0, 10:0, 11:18, 12:2, 13:3, 14:0, 15:0,
fw_rx_mgmt_subtype = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0,
scan_fail_dfs_violation_time_ms = 0
nol_chk_fail_last_chan_freq = 0
nol_chk_fail_time_stamp_ms = 0
tot_peer_create_cnt = 7
tot_peer_del_cnt = 7
tot_peer_del_resp_cnt = 7
vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt = 0
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Signed-off-by: Rajat Soni <rajat.soni@oss.qualcomm.com>
Co-developed-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
---
v3
- Rebased and modified to use wiphy lock.
v2
- Rebased on ToT. Not tagged "Acked-by" due to below changes.
- Added mutex_lock in ath12k_write_wmi_ctrl_path_stats() as subsequent
called ath12k_mac_get_target_pdev_id() has locking correctness
validator.
- Handled NULL case of ar in ath12k_wmi_ctrl_path_stats_event()
---
drivers/net/wireless/ath/ath12k/core.h | 7 +
drivers/net/wireless/ath/ath12k/debugfs.c | 158 ++++++++++-
drivers/net/wireless/ath/ath12k/wmi.c | 320 +++++++++++++++++++++-
drivers/net/wireless/ath/ath12k/wmi.h | 88 +++++-
4 files changed, 570 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index ee595794a7ae..132d198076fa 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -559,6 +559,13 @@ struct ath12k_debug {
struct dentry *debugfs_pdev;
struct dentry *debugfs_pdev_symlink;
struct ath12k_dbg_htt_stats htt_stats;
+ struct ath12k_wmi_ctrl_path_stats_list wmi_ctrl_path_stats;
+ enum wmi_tlv_tag wmi_ctrl_path_stats_tagid;
+ struct completion wmi_ctrl_path_stats_rcvd;
+ u8 wmi_ctrl_path_stats_reqid;
+ /* To protect wmi_list manipulation */
+ spinlock_t wmi_ctrl_path_stats_lock;
+ bool wmi_ctrl_path_stats_more_enabled;
};
struct ath12k_per_peer_tx_stats {
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index d4b32d1a431c..3bc44405ed01 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
+#include "debug.h"
#include "debugfs.h"
#include "debugfs_htt_stats.h"
@@ -68,6 +69,156 @@ void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
*/
}
+static ssize_t ath12k_write_wmi_ctrl_path_stats(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath12k *ar = file->private_data;
+ struct wmi_ctrl_path_stats_arg arg = {};
+ struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
+ u8 buf[128] = {0};
+ int ret;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
+ if (ret < 0)
+ return ret;
+
+ buf[ret] = '\0';
+
+ ret = sscanf(buf, "%u %u", &arg.stats_id, &arg.action);
+ if (ret != 2)
+ return -EINVAL;
+
+ if (!arg.action || arg.action > WMI_REQUEST_CTRL_PATH_STAT_RESET)
+ return -EINVAL;
+
+ guard(mutex)(&ah->hw_mutex);
+ ret = ath12k_wmi_send_wmi_ctrl_stats_cmd(ar, &arg);
+ if (ret && ret != -ETIMEDOUT) {
+ ath12k_info(ar->ab, "failed to send ctrl path stats request %d\n",
+ ret);
+ return ret;
+ }
+
+ return count;
+}
+
+static int wmi_ctrl_path_pdev_stat(struct ath12k *ar, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char fw_tx_mgmt_subtype[WMI_MAX_STRING_LEN] = {0};
+ char fw_rx_mgmt_subtype[WMI_MAX_STRING_LEN] = {0};
+ struct wmi_ctrl_path_pdev_stats *stats, *tmp;
+ u16 index_tx, index_rx;
+ const int size = 2048;
+ u8 i;
+ int len = 0;
+
+ char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ LIST_HEAD(wmi_stats_list);
+
+ spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+ list_splice_tail_init(&ar->debug.wmi_ctrl_path_stats.pdev_stats, &wmi_stats_list);
+ spin_unlock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+
+ list_for_each_entry_safe(stats, tmp, &wmi_stats_list, list) {
+ if (!stats)
+ break;
+
+ index_tx = 0;
+ index_rx = 0;
+
+ for (i = 0; i < IEEE80211_MGMT_FRAME_SUBTYPE_MAX; i++) {
+ index_tx += scnprintf(&fw_tx_mgmt_subtype[index_tx],
+ WMI_MAX_STRING_LEN - index_tx,
+ " %u:%u,", i,
+ stats->tx_mgmt_subtype[i]);
+ index_rx += scnprintf(&fw_rx_mgmt_subtype[index_rx],
+ WMI_MAX_STRING_LEN - index_rx,
+ " %u:%u,", i,
+ stats->rx_mgmt_subtype[i]);
+ }
+
+ len += scnprintf(buf + len, size - len,
+ "WMI_CTRL_PATH_PDEV_TX_STATS:\n");
+ len += scnprintf(buf + len, size - len,
+ "fw_tx_mgmt_subtype = %s\n",
+ fw_tx_mgmt_subtype);
+ len += scnprintf(buf + len, size - len,
+ "fw_rx_mgmt_subtype = %s\n",
+ fw_rx_mgmt_subtype);
+ len += scnprintf(buf + len, size - len,
+ "scan_fail_dfs_violation_time_ms = %u\n",
+ stats->scan_fail_dfs_viol_time_ms);
+ len += scnprintf(buf + len, size - len,
+ "nol_chk_fail_last_chan_freq = %u\n",
+ stats->nol_chk_fail_last_chan_freq);
+ len += scnprintf(buf + len, size - len,
+ "nol_chk_fail_time_stamp_ms = %u\n",
+ stats->nol_chk_fail_time_stamp_ms);
+ len += scnprintf(buf + len, size - len,
+ "tot_peer_create_cnt = %u\n",
+ stats->tot_peer_create_cnt);
+ len += scnprintf(buf + len, size - len,
+ "tot_peer_del_cnt = %u\n",
+ stats->tot_peer_del_cnt);
+ len += scnprintf(buf + len, size - len,
+ "tot_peer_del_resp_cnt = %u\n",
+ stats->tot_peer_del_resp_cnt);
+ len += scnprintf(buf + len, size - len,
+ "vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt = %u\n",
+ stats->sched_algo_fifo_full_cnt);
+ list_del(&stats->list);
+ kfree(stats);
+ }
+
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static ssize_t ath12k_read_wmi_ctrl_path_stats(struct file *file,
+ char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath12k *ar = file->private_data;
+ int ret;
+ enum wmi_tlv_tag tagid;
+
+ tagid = ar->debug.wmi_ctrl_path_stats_tagid;
+
+ switch (tagid) {
+ case WMI_TAG_CTRL_PATH_PDEV_STATS:
+ ret = wmi_ctrl_path_pdev_stat(ar, ubuf, count, ppos);
+ break;
+ default:
+ /* Unsupported tag */
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct file_operations ath12k_fops_wmi_ctrl_stats = {
+ .write = ath12k_write_wmi_ctrl_path_stats,
+ .open = simple_open,
+ .read = ath12k_read_wmi_ctrl_path_stats,
+};
+
+static void ath12k_debugfs_wmi_ctrl_stats_register(struct ath12k *ar)
+{
+ debugfs_create_file("wmi_ctrl_stats", 0600,
+ ar->debug.debugfs_pdev,
+ ar,
+ &ath12k_fops_wmi_ctrl_stats);
+ INIT_LIST_HEAD(&ar->debug.wmi_ctrl_path_stats.pdev_stats);
+ spin_lock_init(&ar->debug.wmi_ctrl_path_stats_lock);
+ init_completion(&ar->debug.wmi_ctrl_path_stats_rcvd);
+ ar->debug.wmi_ctrl_path_stats_more_enabled = false;
+}
+
void ath12k_debugfs_register(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
@@ -92,6 +243,11 @@ void ath12k_debugfs_register(struct ath12k *ar)
}
ath12k_debugfs_htt_stats_register(ar);
+
+ if (test_bit(WMI_TLV_SERVICE_CTRL_PATH_STATS_REQUEST,
+ ar->ab->wmi_ab.svc_map))
+ ath12k_debugfs_wmi_ctrl_stats_register(ar);
+
}
void ath12k_debugfs_unregister(struct ath12k *ar)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 4dd6cdf84571..a67adec9919a 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/skbuff.h>
#include <linux/ctype.h>
@@ -16,6 +16,7 @@
#include <linux/of.h>
#include "core.h"
#include "debug.h"
+#include "debugfs.h"
#include "mac.h"
#include "hw.h"
#include "peer.h"
@@ -7417,6 +7418,234 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
kfree(tb);
}
+#ifdef CONFIG_ATH12K_DEBUGFS
+static void
+ath12k_wmi_ctrl_path_pdev_stats_list_free(struct list_head *head)
+{
+ struct wmi_ctrl_path_pdev_stats *stats_list, *tmp;
+
+ list_for_each_entry_safe(stats_list, tmp, head, list) {
+ list_del(&stats_list->list);
+ kfree(stats_list);
+ }
+}
+
+static void
+ath12k_wmi_ctrl_path_stats_list_free(struct ath12k_wmi_ctrl_path_stats_list *param)
+{
+ ath12k_wmi_ctrl_path_pdev_stats_list_free(¶m->pdev_stats);
+}
+
+static int wmi_pull_ctrl_path_pdev_tx_stats_tlv(struct ath12k_base *ab, u16 len,
+ const void *ptr, void *data)
+{
+ struct ath12k_wmi_ctrl_path_stats_list *stats_buff = data;
+ const struct wmi_ctrl_path_pdev_stats_params *stats = ptr;
+ struct ath12k_wmi_ctrl_path_stats_list *stats_list;
+ struct wmi_ctrl_path_pdev_stats *pdev_stats =
+ kzalloc(sizeof(*pdev_stats), GFP_ATOMIC);
+ struct ath12k *ar;
+ u32 pdev_id;
+ int i;
+
+ if (!pdev_stats)
+ return -ENOMEM;
+
+ for (i = 0; i < IEEE80211_MGMT_FRAME_SUBTYPE_MAX; i++) {
+ pdev_stats->tx_mgmt_subtype[i] =
+ __le32_to_cpu(stats->tx_mgmt_subtype[i]);
+ pdev_stats->rx_mgmt_subtype[i] =
+ __le32_to_cpu(stats->rx_mgmt_subtype[i]);
+ }
+ pdev_stats->scan_fail_dfs_viol_time_ms =
+ __le32_to_cpu(stats->scan_fail_dfs_viol_time_ms);
+ pdev_stats->nol_chk_fail_last_chan_freq =
+ __le32_to_cpu(stats->nol_chk_fail_last_chan_freq);
+ pdev_stats->nol_chk_fail_time_stamp_ms =
+ __le32_to_cpu(stats->nol_chk_fail_time_stamp_ms);
+ pdev_stats->tot_peer_create_cnt =
+ __le32_to_cpu(stats->tot_peer_create_cnt);
+ pdev_stats->tot_peer_del_cnt =
+ __le32_to_cpu(stats->tot_peer_del_cnt);
+ pdev_stats->tot_peer_del_resp_cnt =
+ __le32_to_cpu(stats->tot_peer_del_resp_cnt);
+ pdev_stats->sched_algo_fifo_full_cnt =
+ __le32_to_cpu(stats->sched_algo_fifo_full_cnt);
+
+ list_add_tail(&pdev_stats->list, &stats_buff->pdev_stats);
+ pdev_id = le32_to_cpu(stats->pdev_id);
+
+ rcu_read_lock();
+ ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id + 1);
+ if (!ar) {
+ rcu_read_unlock();
+ ath12k_warn(ab, "Failed to get ar for wmi ctrl stats\n");
+ ath12k_wmi_ctrl_path_pdev_stats_list_free(&stats_buff->pdev_stats);
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+ stats_list = &ar->debug.wmi_ctrl_path_stats;
+ ath12k_wmi_ctrl_path_pdev_stats_list_free(&stats_list->pdev_stats);
+ spin_unlock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+ ar->debug.wmi_ctrl_path_stats_tagid = WMI_TAG_CTRL_PATH_PDEV_STATS;
+ stats_buff->ar = ar;
+ rcu_read_unlock();
+ return 0;
+}
+
+static int ath12k_wmi_ctrl_stats_subtlv_parser(struct ath12k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ int ret;
+
+ switch (tag) {
+ case WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM:
+ break;
+ case WMI_TAG_CTRL_PATH_PDEV_STATS:
+ ret = wmi_pull_ctrl_path_pdev_tx_stats_tlv(ab, len, ptr, data);
+ break;
+ /* Add case for newly wmi ctrl path added stats here */
+ default:
+ ath12k_warn(ab,
+ "Received invalid tag for wmi ctrl path stats in subtlvs, tag : 0x%x\n",
+ tag);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int ath12k_wmi_ctrl_stats_event_parser(struct ath12k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ int ret;
+
+ ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi ctrl path stats tag 0x%x of len %d rcvd\n",
+ tag, len);
+
+ switch (tag) {
+ case WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM:
+ /* Fixed param is already processed*/
+ ret = 0;
+ break;
+ case WMI_TAG_ARRAY_STRUCT:
+ /* len 0 is expected for array of struct when there
+ * is no content of that type to pack inside that tlv
+ */
+ if (len == 0)
+ return 0;
+
+ ret = ath12k_wmi_tlv_iter(ab, ptr, len,
+ ath12k_wmi_ctrl_stats_subtlv_parser,
+ data);
+ break;
+ default:
+ ath12k_warn(ab, "Received invalid tag for wmi ctrl path stats\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static void ath12k_wmi_ctrl_path_stats_event(struct ath12k_base *ab, struct sk_buff *skb)
+{
+ struct wmi_ctrl_path_stats_event *fixed_param;
+ struct ath12k_wmi_ctrl_path_stats_list param = {0};
+ struct ath12k_wmi_ctrl_path_stats_list *stats;
+ const struct wmi_tlv *tlv;
+ struct list_head *src, *dst;
+ struct ath12k *ar;
+ void *ptr = skb->data;
+ u16 tlv_tag, tag_id;
+ u32 more;
+ int ret;
+
+ if (!skb->data) {
+ ath12k_warn(ab, "No data present in wmi ctrl stats event\n");
+ return;
+ }
+
+ if (skb->len < (sizeof(*fixed_param) + TLV_HDR_SIZE)) {
+ ath12k_warn(ab, "wmi ctrl stats event size invalid\n");
+ return;
+ }
+
+ param.ar = NULL;
+
+ tlv = ptr;
+ tlv_tag = le32_get_bits(tlv->header, WMI_TLV_TAG);
+ ptr += sizeof(*tlv);
+
+ if (tlv_tag != WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM) {
+ ath12k_warn(ab, "wmi ctrl stats without fixed param tlv at start\n");
+ return;
+ }
+
+ INIT_LIST_HEAD(¶m.pdev_stats);
+
+ fixed_param = ptr;
+ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath12k_wmi_ctrl_stats_event_parser,
+ ¶m);
+ if (ret) {
+ ath12k_warn(ab, "failed to parse wmi_ctrl_path_stats tlv: %d\n", ret);
+ if (!param.ar)
+ return;
+ goto free;
+ }
+
+ ar = param.ar;
+ if (!ar)
+ return;
+
+ tag_id = ar->debug.wmi_ctrl_path_stats_tagid;
+ stats = &ar->debug.wmi_ctrl_path_stats;
+ more = __le32_to_cpu(fixed_param->more);
+
+ switch (tag_id) {
+ case WMI_TAG_CTRL_PATH_PDEV_STATS:
+ src = ¶m.pdev_stats;
+ dst = &stats->pdev_stats;
+ break;
+ default:
+ goto free;
+ }
+
+ spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+ if (!more) {
+ if (!ar->debug.wmi_ctrl_path_stats_more_enabled)
+ ath12k_wmi_ctrl_path_stats_list_free(stats);
+ else
+ ar->debug.wmi_ctrl_path_stats_more_enabled = false;
+
+ list_splice_tail_init(src, dst);
+ complete(&ar->debug.wmi_ctrl_path_stats_rcvd);
+ } else {
+ if (!ar->debug.wmi_ctrl_path_stats_more_enabled) {
+ ath12k_wmi_ctrl_path_stats_list_free(stats);
+ ar->debug.wmi_ctrl_path_stats_more_enabled = true;
+ }
+ list_splice_tail_init(src, dst);
+ }
+ spin_unlock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+ return;
+free:
+ spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+ ath12k_wmi_ctrl_path_stats_list_free(¶m);
+ spin_unlock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
+}
+#else
+static void ath12k_wmi_ctrl_path_stats_event(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+}
+#endif /* CONFIG_ATH12K_DEBUGFS */
+
static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@@ -7542,6 +7771,9 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
case WMI_MLO_TEARDOWN_COMPLETE_EVENTID:
ath12k_wmi_event_teardown_complete(ab, skb);
break;
+ case WMI_CTRL_PATH_STATS_EVENTID:
+ ath12k_wmi_ctrl_path_stats_event(ab, skb);
+ break;
/* add Unsupported events (rare) here */
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
@@ -7692,6 +7924,92 @@ int ath12k_wmi_simulate_radar(struct ath12k *ar)
return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args);
}
+#ifdef CONFIG_ATH12K_DEBUGFS
+int
+ath12k_wmi_send_wmi_ctrl_stats_cmd(struct ath12k *ar,
+ struct wmi_ctrl_path_stats_arg *arg)
+{
+ struct wmi_ctrl_path_stats_cmd *cmd;
+ struct ath12k_wmi_pdev *wmi = ar->wmi;
+ struct ath12k_base *ab = wmi->wmi_ab->ab;
+ struct ath12k_debug *debug = &ar->debug;
+ __le32 pdev_id;
+ struct wmi_tlv *tlv;
+ struct sk_buff *skb;
+ int len, ret;
+ void *ptr;
+ u32 stats_id;
+
+ pdev_id = cpu_to_le32(ath12k_mac_get_target_pdev_id(ar));
+ stats_id = (1 << arg->stats_id);
+
+ len = sizeof(*cmd) +
+ TLV_HDR_SIZE + sizeof(u32) +
+ TLV_HDR_SIZE + TLV_HDR_SIZE;
+
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (void *)skb->data;
+ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_CTRL_PATH_STATS_CMD_FIXED_PARAM,
+ sizeof(*cmd));
+ cmd->stats_id = cpu_to_le32(stats_id);
+ cmd->req_id = cpu_to_le32(arg->req_id);
+ cmd->action = cpu_to_le32(arg->action);
+
+ ptr = skb->data + sizeof(*cmd);
+
+ /* The below TLV arrays optionally follow this fixed param TLV structure
+ * 1. ARRAY_UINT32 pdev_ids[]
+ * If this array is present and non-zero length, stats should only
+ * be provided from the pdevs identified in the array.
+ * 2. ARRAY_UNIT32 vdev_ids[]
+ * If this array is present and non-zero length, stats should only
+ * be provided from the vdevs identified in the array.
+ * 3. ath12k_wmi_mac_addr_params peer_macaddr[];
+ * If this array is present and non-zero length, stats should only
+ * be provided from the peers with the MAC addresses specified
+ * in the array
+ */
+
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, sizeof(u32));
+ ptr += TLV_HDR_SIZE;
+ memcpy(ptr, &pdev_id, sizeof(u32));
+ ptr += sizeof(u32);
+
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0);
+ ptr += TLV_HDR_SIZE;
+
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_FIXED_STRUCT, 0);
+ ptr += TLV_HDR_SIZE;
+
+ if (arg->action == WMI_REQUEST_CTRL_PATH_STAT_GET)
+ reinit_completion(&ar->debug.wmi_ctrl_path_stats_rcvd);
+
+ ret = ath12k_wmi_cmd_send(wmi, skb,
+ WMI_REQUEST_CTRL_PATH_STATS_CMDID);
+ if (ret) {
+ dev_kfree_skb(skb);
+ ath12k_warn(ab, "Failed to send WMI_REQUEST_CTRL_PATH_STATS_CMDID: %d",
+ ret);
+ } else {
+ if (arg->action == WMI_REQUEST_CTRL_PATH_STAT_GET) {
+ if (!wait_for_completion_timeout(&debug->wmi_ctrl_path_stats_rcvd,
+ WMI_CTRL_STATS_READY_TIMEOUT)) {
+ ath12k_warn(ab, "wmi ctrl path stats timed out\n");
+ ret = -ETIMEDOUT;
+ }
+ }
+ }
+
+ return ret;
+}
+#endif
+
int ath12k_wmi_connect(struct ath12k_base *ab)
{
u32 i;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index b6a197389277..0feccdfeba9e 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_WMI_H
@@ -516,6 +516,8 @@ enum wmi_tlv_cmd_id {
WMI_REQUEST_RCPI_CMDID,
WMI_REQUEST_PEER_STATS_INFO_CMDID,
WMI_REQUEST_RADIO_CHAN_STATS_CMDID,
+ WMI_REQUEST_WLM_STATS_CMDID,
+ WMI_REQUEST_CTRL_PATH_STATS_CMDID,
WMI_SET_ARP_NS_OFFLOAD_CMDID = WMI_TLV_CMD(WMI_GRP_ARP_NS_OFL),
WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID,
WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID,
@@ -785,6 +787,8 @@ enum wmi_tlv_event_id {
WMI_UPDATE_RCPI_EVENTID,
WMI_PEER_STATS_INFO_EVENTID,
WMI_RADIO_CHAN_STATS_EVENTID,
+ WMI_WLM_STATS_EVENTID,
+ WMI_CTRL_PATH_STATS_EVENTID,
WMI_NLO_MATCH_EVENTID = WMI_TLV_CMD(WMI_GRP_NLO_OFL),
WMI_NLO_SCAN_COMPLETE_EVENTID,
WMI_APFIND_EVENTID,
@@ -1939,6 +1943,9 @@ enum wmi_tlv_tag {
WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F,
+ WMI_TAG_CTRL_PATH_STATS_CMD_FIXED_PARAM = 0x388,
+ WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM,
+ WMI_TAG_CTRL_PATH_PDEV_STATS,
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
WMI_TAG_EHT_RATE_SET = 0x3C4,
@@ -2181,6 +2188,7 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213,
WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
WMI_TLV_SERVICE_EXT2_MSG = 220,
+ WMI_TLV_SERVICE_CTRL_PATH_STATS_REQUEST = 250,
WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
WMI_MAX_EXT_SERVICE = 256,
@@ -5629,6 +5637,82 @@ enum wmi_sta_keepalive_method {
#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
+#define WMI_CTRL_STATS_READY_TIMEOUT (1 * HZ)
+
+enum wmi_ctrl_path_stats_id {
+ /* bit 0 is currently unused / reserved */
+ WMI_REQ_CTRL_PATH_PDEV_TX_STAT = 1,
+};
+
+enum wmi_ctrl_path_stats_action {
+ WMI_REQUEST_CTRL_PATH_STAT_GET = 1,
+ WMI_REQUEST_CTRL_PATH_STAT_RESET = 2,
+ WMI_REQUEST_CTRL_PATH_STAT_START = 3,
+ WMI_REQUEST_CTRL_PATH_STAT_STOP = 4,
+};
+
+struct wmi_ctrl_path_stats_cmd {
+ __le32 tlv_header;
+ __le32 stats_id;
+ __le32 req_id;
+ /* get/reset/start/stop based on stats id is defined as
+ * a part of wmi_ctrl_path_stats_action
+ */
+ __le32 action;
+} __packed;
+
+struct wmi_ctrl_path_stats_arg {
+ u32 stats_id;
+ u32 req_id;
+ u32 action;
+};
+
+struct wmi_ctrl_path_stats_event {
+ __le32 req_id;
+ /* more flag
+ * 1 - More events sent after this event.
+ * 0 - no more events after this event.
+ */
+ __le32 more;
+};
+
+/* WMI arrays of length WMI_MGMT_FRAME_SUBTYPE_MAX use the
+ * IEEE802.11 standard's enumeration of mgmt frame subtypes:
+ */
+#define IEEE80211_MGMT_FRAME_SUBTYPE_MAX 16
+#define WMI_MAX_STRING_LEN 256
+
+struct wmi_ctrl_path_pdev_stats_params {
+ __le32 pdev_id;
+ __le32 tx_mgmt_subtype[IEEE80211_MGMT_FRAME_SUBTYPE_MAX];
+ __le32 rx_mgmt_subtype[IEEE80211_MGMT_FRAME_SUBTYPE_MAX];
+ __le32 scan_fail_dfs_viol_time_ms;
+ __le32 nol_chk_fail_last_chan_freq;
+ __le32 nol_chk_fail_time_stamp_ms;
+ __le32 tot_peer_create_cnt;
+ __le32 tot_peer_del_cnt;
+ __le32 tot_peer_del_resp_cnt;
+ __le32 sched_algo_fifo_full_cnt;
+} __packed;
+
+struct ath12k_wmi_ctrl_path_stats_list {
+ struct list_head pdev_stats;
+ struct ath12k *ar;
+};
+
+struct wmi_ctrl_path_pdev_stats {
+ struct list_head list;
+ u32 tx_mgmt_subtype[IEEE80211_MGMT_FRAME_SUBTYPE_MAX];
+ u32 rx_mgmt_subtype[IEEE80211_MGMT_FRAME_SUBTYPE_MAX];
+ u32 scan_fail_dfs_viol_time_ms;
+ u32 nol_chk_fail_last_chan_freq;
+ u32 nol_chk_fail_time_stamp_ms;
+ u32 tot_peer_create_cnt;
+ u32 tot_peer_del_cnt;
+ u32 tot_peer_del_resp_cnt;
+ u32 sched_algo_fifo_full_cnt;
+};
+
void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
struct ath12k_wmi_resource_config_arg *config);
void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
@@ -5754,6 +5838,8 @@ int ath12k_wmi_set_bios_cmd(struct ath12k_base *ab, u32 param_id,
const u8 *buf, size_t buf_len);
int ath12k_wmi_set_bios_sar_cmd(struct ath12k_base *ab, const u8 *psar_table);
int ath12k_wmi_set_bios_geo_cmd(struct ath12k_base *ab, const u8 *pgeo_table);
+int ath12k_wmi_send_wmi_ctrl_stats_cmd(struct ath12k *ar,
+ struct wmi_ctrl_path_stats_arg *arg);
static inline u32
ath12k_wmi_caps_ext_get_pdev_id(const struct ath12k_wmi_caps_ext_params *param)
base-commit: d7bef42fc98f2d8f67546d1ea1a3f2c2932fd72b
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3] wifi: ath12k: Add WMI control path stats infra
2025-01-20 18:44 [PATCH v3] wifi: ath12k: Add WMI control path stats infra Ramya Gnanasekar
@ 2025-01-21 4:40 ` Aditya Kumar Singh
2025-01-22 1:39 ` kernel test robot
2025-06-06 22:45 ` Jeff Johnson
2 siblings, 0 replies; 4+ messages in thread
From: Aditya Kumar Singh @ 2025-01-21 4:40 UTC (permalink / raw)
To: Ramya Gnanasekar, ath12k; +Cc: linux-wireless, Rajat Soni
On 1/21/25 00:14, Ramya Gnanasekar wrote:
> @@ -559,6 +559,13 @@ struct ath12k_debug {
> struct dentry *debugfs_pdev;
> struct dentry *debugfs_pdev_symlink;
> struct ath12k_dbg_htt_stats htt_stats;
> + struct ath12k_wmi_ctrl_path_stats_list wmi_ctrl_path_stats;
> + enum wmi_tlv_tag wmi_ctrl_path_stats_tagid;
> + struct completion wmi_ctrl_path_stats_rcvd;
> + u8 wmi_ctrl_path_stats_reqid;
> + /* To protect wmi_list manipulation */
> + spinlock_t wmi_ctrl_path_stats_lock;
nit: extra space between type and name
@@ -92,6 +243,11 @@ void ath12k_debugfs_register(struct ath12k *ar)
> }
>
> ath12k_debugfs_htt_stats_register(ar);
> +
> + if (test_bit(WMI_TLV_SERVICE_CTRL_PATH_STATS_REQUEST,
> + ar->ab->wmi_ab.svc_map))
> + ath12k_debugfs_wmi_ctrl_stats_register(ar);
> +
> }
drivers/net/wireless/ath/ath12k/debugfs.c:251: Blank lines aren't necessary before a close brace '}'
--
Aditya
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] wifi: ath12k: Add WMI control path stats infra
2025-01-20 18:44 [PATCH v3] wifi: ath12k: Add WMI control path stats infra Ramya Gnanasekar
2025-01-21 4:40 ` Aditya Kumar Singh
@ 2025-01-22 1:39 ` kernel test robot
2025-06-06 22:45 ` Jeff Johnson
2 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2025-01-22 1:39 UTC (permalink / raw)
To: Ramya Gnanasekar, ath12k
Cc: llvm, oe-kbuild-all, linux-wireless, Rajat Soni, Ramya Gnanasekar
Hi Ramya,
kernel test robot noticed the following build warnings:
[auto build test WARNING on d7bef42fc98f2d8f67546d1ea1a3f2c2932fd72b]
url: https://github.com/intel-lab-lkp/linux/commits/Ramya-Gnanasekar/wifi-ath12k-Add-WMI-control-path-stats-infra/20250121-024618
base: d7bef42fc98f2d8f67546d1ea1a3f2c2932fd72b
patch link: https://lore.kernel.org/r/20250120184447.658660-1-ramya.gnanasekar%40oss.qualcomm.com
patch subject: [PATCH v3] wifi: ath12k: Add WMI control path stats infra
config: um-allmodconfig (https://download.01.org/0day-ci/archive/20250122/202501220916.o70hNSkA-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project c23f2417dc5f6dc371afb07af5627ec2a9d373a0)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250122/202501220916.o70hNSkA-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501220916.o70hNSkA-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from drivers/net/wireless/ath/ath12k/wmi.c:6:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:549:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
549 | val = __raw_readb(PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:567:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
567 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
| ^
In file included from drivers/net/wireless/ath/ath12k/wmi.c:6:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:585:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
585 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
| ^
In file included from drivers/net/wireless/ath/ath12k/wmi.c:6:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:601:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
601 | __raw_writeb(value, PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:616:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
616 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:631:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
631 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:724:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
724 | readsb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:737:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
737 | readsw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:750:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
750 | readsl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:764:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
764 | writesb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:778:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
778 | writesw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:792:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
792 | writesl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
>> drivers/net/wireless/ath/ath12k/wmi.c:7504:7: warning: variable 'ret' is used uninitialized whenever switch case is taken [-Wsometimes-uninitialized]
7504 | case WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM:
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath12k/wmi.c:7518:9: note: uninitialized use occurs here
7518 | return ret;
| ^~~
drivers/net/wireless/ath/ath12k/wmi.c:7501:9: note: initialize the variable 'ret' to silence this warning
7501 | int ret;
| ^
| = 0
>> drivers/net/wireless/ath/ath12k/wmi.c:7597:7: warning: variable 'ar' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
7597 | if (!param.ar)
| ^~~~~~~~~
drivers/net/wireless/ath/ath12k/wmi.c:7638:16: note: uninitialized use occurs here
7638 | spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
| ^~
drivers/net/wireless/ath/ath12k/wmi.c:7597:3: note: remove the 'if' if its condition is always true
7597 | if (!param.ar)
| ^~~~~~~~~~~~~~
7598 | return;
drivers/net/wireless/ath/ath12k/wmi.c:7562:19: note: initialize the variable 'ar' to silence this warning
7562 | struct ath12k *ar;
| ^
| = NULL
14 warnings generated.
vim +/ret +7504 drivers/net/wireless/ath/ath12k/wmi.c
7496
7497 static int ath12k_wmi_ctrl_stats_subtlv_parser(struct ath12k_base *ab,
7498 u16 tag, u16 len,
7499 const void *ptr, void *data)
7500 {
7501 int ret;
7502
7503 switch (tag) {
> 7504 case WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM:
7505 break;
7506 case WMI_TAG_CTRL_PATH_PDEV_STATS:
7507 ret = wmi_pull_ctrl_path_pdev_tx_stats_tlv(ab, len, ptr, data);
7508 break;
7509 /* Add case for newly wmi ctrl path added stats here */
7510 default:
7511 ath12k_warn(ab,
7512 "Received invalid tag for wmi ctrl path stats in subtlvs, tag : 0x%x\n",
7513 tag);
7514 ret = -EINVAL;
7515 break;
7516 }
7517
7518 return ret;
7519 }
7520
7521 static int ath12k_wmi_ctrl_stats_event_parser(struct ath12k_base *ab,
7522 u16 tag, u16 len,
7523 const void *ptr, void *data)
7524 {
7525 int ret;
7526
7527 ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi ctrl path stats tag 0x%x of len %d rcvd\n",
7528 tag, len);
7529
7530 switch (tag) {
7531 case WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM:
7532 /* Fixed param is already processed*/
7533 ret = 0;
7534 break;
7535 case WMI_TAG_ARRAY_STRUCT:
7536 /* len 0 is expected for array of struct when there
7537 * is no content of that type to pack inside that tlv
7538 */
7539 if (len == 0)
7540 return 0;
7541
7542 ret = ath12k_wmi_tlv_iter(ab, ptr, len,
7543 ath12k_wmi_ctrl_stats_subtlv_parser,
7544 data);
7545 break;
7546 default:
7547 ath12k_warn(ab, "Received invalid tag for wmi ctrl path stats\n");
7548 ret = -EINVAL;
7549 break;
7550 }
7551
7552 return ret;
7553 }
7554
7555 static void ath12k_wmi_ctrl_path_stats_event(struct ath12k_base *ab, struct sk_buff *skb)
7556 {
7557 struct wmi_ctrl_path_stats_event *fixed_param;
7558 struct ath12k_wmi_ctrl_path_stats_list param = {0};
7559 struct ath12k_wmi_ctrl_path_stats_list *stats;
7560 const struct wmi_tlv *tlv;
7561 struct list_head *src, *dst;
7562 struct ath12k *ar;
7563 void *ptr = skb->data;
7564 u16 tlv_tag, tag_id;
7565 u32 more;
7566 int ret;
7567
7568 if (!skb->data) {
7569 ath12k_warn(ab, "No data present in wmi ctrl stats event\n");
7570 return;
7571 }
7572
7573 if (skb->len < (sizeof(*fixed_param) + TLV_HDR_SIZE)) {
7574 ath12k_warn(ab, "wmi ctrl stats event size invalid\n");
7575 return;
7576 }
7577
7578 param.ar = NULL;
7579
7580 tlv = ptr;
7581 tlv_tag = le32_get_bits(tlv->header, WMI_TLV_TAG);
7582 ptr += sizeof(*tlv);
7583
7584 if (tlv_tag != WMI_TAG_CTRL_PATH_STATS_EV_FIXED_PARAM) {
7585 ath12k_warn(ab, "wmi ctrl stats without fixed param tlv at start\n");
7586 return;
7587 }
7588
7589 INIT_LIST_HEAD(¶m.pdev_stats);
7590
7591 fixed_param = ptr;
7592 ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
7593 ath12k_wmi_ctrl_stats_event_parser,
7594 ¶m);
7595 if (ret) {
7596 ath12k_warn(ab, "failed to parse wmi_ctrl_path_stats tlv: %d\n", ret);
> 7597 if (!param.ar)
7598 return;
7599 goto free;
7600 }
7601
7602 ar = param.ar;
7603 if (!ar)
7604 return;
7605
7606 tag_id = ar->debug.wmi_ctrl_path_stats_tagid;
7607 stats = &ar->debug.wmi_ctrl_path_stats;
7608 more = __le32_to_cpu(fixed_param->more);
7609
7610 switch (tag_id) {
7611 case WMI_TAG_CTRL_PATH_PDEV_STATS:
7612 src = ¶m.pdev_stats;
7613 dst = &stats->pdev_stats;
7614 break;
7615 default:
7616 goto free;
7617 }
7618
7619 spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
7620 if (!more) {
7621 if (!ar->debug.wmi_ctrl_path_stats_more_enabled)
7622 ath12k_wmi_ctrl_path_stats_list_free(stats);
7623 else
7624 ar->debug.wmi_ctrl_path_stats_more_enabled = false;
7625
7626 list_splice_tail_init(src, dst);
7627 complete(&ar->debug.wmi_ctrl_path_stats_rcvd);
7628 } else {
7629 if (!ar->debug.wmi_ctrl_path_stats_more_enabled) {
7630 ath12k_wmi_ctrl_path_stats_list_free(stats);
7631 ar->debug.wmi_ctrl_path_stats_more_enabled = true;
7632 }
7633 list_splice_tail_init(src, dst);
7634 }
7635 spin_unlock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
7636 return;
7637 free:
7638 spin_lock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
7639 ath12k_wmi_ctrl_path_stats_list_free(¶m);
7640 spin_unlock_bh(&ar->debug.wmi_ctrl_path_stats_lock);
7641 }
7642 #else
7643 static void ath12k_wmi_ctrl_path_stats_event(struct ath12k_base *ab,
7644 struct sk_buff *skb)
7645 {
7646 }
7647 #endif /* CONFIG_ATH12K_DEBUGFS */
7648
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] wifi: ath12k: Add WMI control path stats infra
2025-01-20 18:44 [PATCH v3] wifi: ath12k: Add WMI control path stats infra Ramya Gnanasekar
2025-01-21 4:40 ` Aditya Kumar Singh
2025-01-22 1:39 ` kernel test robot
@ 2025-06-06 22:45 ` Jeff Johnson
2 siblings, 0 replies; 4+ messages in thread
From: Jeff Johnson @ 2025-06-06 22:45 UTC (permalink / raw)
To: Ramya Gnanasekar, ath12k; +Cc: linux-wireless, Rajat Soni
On 1/20/2025 10:44 AM, Ramya Gnanasekar wrote:
> From: Rajat Soni <rajat.soni@oss.qualcomm.com>
>
> Currently, firmware stats is requested by host through HTT interface.
>
> Since HTT interface is already overloaded for data path stats,
> leveraging control path to request other stats through WMI interface.
>
> Add debugfs to request the stats and dump the stats forwarded by firmware.
>
> ath12k
> `-- pci-0000:06:00.0
> |-- mac0
> `-- wmi_ctrl_stats
>
> This patch also adds support to request PDEV Tx stats, parse and dump
> the data sent from firmware.
>
> Usage:
> echo <stats id> <action> > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/wmi_ctrl_stats
>
> Sample:
> echo 1 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/wmi_ctrl_stats
> cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/wmi_ctrl_stats
> WMI_CTRL_PATH_PDEV_TX_STATS:
> fw_tx_mgmt_subtype = 0:0, 1:2, 2:0, 3:0, 4:0, 5:37, 6:0, 7:0, 8:908, 9:0, 10:0, 11:18, 12:2, 13:3, 14:0, 15:0,
> fw_rx_mgmt_subtype = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0,
> scan_fail_dfs_violation_time_ms = 0
> nol_chk_fail_last_chan_freq = 0
> nol_chk_fail_time_stamp_ms = 0
> tot_peer_create_cnt = 7
> tot_peer_del_cnt = 7
> tot_peer_del_resp_cnt = 7
> vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt = 0
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
>
> Signed-off-by: Rajat Soni <rajat.soni@oss.qualcomm.com>
> Co-developed-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
> Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
There was no feedback on the v3 review comments.
--
pw-bot: cr
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-06-06 22:45 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-20 18:44 [PATCH v3] wifi: ath12k: Add WMI control path stats infra Ramya Gnanasekar
2025-01-21 4:40 ` Aditya Kumar Singh
2025-01-22 1:39 ` kernel test robot
2025-06-06 22:45 ` Jeff Johnson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).