mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 02:53:36 +02:00
wifi: ath12k: Add htt_stats_dump file ops support
Add dump_htt_stats file operation to dump the stats value requested
for the requested stats_type.
Stats sent from firmware will be cumulative. Hence add debugfs to reset
the requested stats type.
Example with one ath12k device:
ath12k
`-- pci-0000:06:00.0
|-- mac0
`-- htt_stats
|-- htt_stats_type
|-- htt_stats_reset
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: Dinesh Karthikeyan <quic_dinek@quicinc.com>
Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com>
Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20240626085854.2500681-3-quic_rgnanase@quicinc.com
This commit is contained in:
parent
3f73c24f28
commit
ad201b35d3
|
|
@ -485,6 +485,8 @@ struct ath12k_fw_stats {
|
|||
struct ath12k_dbg_htt_stats {
|
||||
enum ath12k_dbg_htt_ext_stats_type type;
|
||||
u32 cfg_param[4];
|
||||
u8 reset;
|
||||
struct debug_htt_stats_req *stats_req;
|
||||
};
|
||||
|
||||
struct ath12k_debug {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
#include "dp_tx.h"
|
||||
|
||||
static ssize_t ath12k_read_htt_stats_type(struct file *file,
|
||||
char __user *user_buf,
|
||||
|
|
@ -74,8 +75,212 @@ static const struct file_operations fops_htt_stats_type = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int ath12k_debugfs_htt_stats_req(struct ath12k *ar)
|
||||
{
|
||||
struct debug_htt_stats_req *stats_req = ar->debug.htt_stats.stats_req;
|
||||
enum ath12k_dbg_htt_ext_stats_type type = stats_req->type;
|
||||
u64 cookie;
|
||||
int ret, pdev_id;
|
||||
struct htt_ext_stats_cfg_params cfg_params = { 0 };
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
init_completion(&stats_req->htt_stats_rcvd);
|
||||
|
||||
pdev_id = ath12k_mac_get_target_pdev_id(ar);
|
||||
stats_req->done = false;
|
||||
stats_req->pdev_id = pdev_id;
|
||||
|
||||
cookie = u64_encode_bits(ATH12K_HTT_STATS_MAGIC_VALUE,
|
||||
ATH12K_HTT_STATS_COOKIE_MSB);
|
||||
cookie |= u64_encode_bits(pdev_id, ATH12K_HTT_STATS_COOKIE_LSB);
|
||||
|
||||
if (stats_req->override_cfg_param) {
|
||||
cfg_params.cfg0 = stats_req->cfg_param[0];
|
||||
cfg_params.cfg1 = stats_req->cfg_param[1];
|
||||
cfg_params.cfg2 = stats_req->cfg_param[2];
|
||||
cfg_params.cfg3 = stats_req->cfg_param[3];
|
||||
}
|
||||
|
||||
ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar, type, &cfg_params, cookie);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!wait_for_completion_timeout(&stats_req->htt_stats_rcvd, 3 * HZ)) {
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
if (!stats_req->done) {
|
||||
stats_req->done = true;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
ath12k_warn(ar->ab, "stats request timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_open_htt_stats(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
struct ath12k *ar = inode->i_private;
|
||||
struct debug_htt_stats_req *stats_req;
|
||||
enum ath12k_dbg_htt_ext_stats_type type = ar->debug.htt_stats.type;
|
||||
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
|
||||
int ret;
|
||||
|
||||
if (type == ATH12K_DBG_HTT_EXT_STATS_RESET)
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ah->state != ATH12K_HW_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
if (ar->debug.htt_stats.stats_req) {
|
||||
ret = -EAGAIN;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
stats_req = kzalloc(sizeof(*stats_req) + ATH12K_HTT_STATS_BUF_SIZE, GFP_KERNEL);
|
||||
if (!stats_req) {
|
||||
ret = -ENOMEM;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
ar->debug.htt_stats.stats_req = stats_req;
|
||||
stats_req->type = type;
|
||||
stats_req->cfg_param[0] = ar->debug.htt_stats.cfg_param[0];
|
||||
stats_req->cfg_param[1] = ar->debug.htt_stats.cfg_param[1];
|
||||
stats_req->cfg_param[2] = ar->debug.htt_stats.cfg_param[2];
|
||||
stats_req->cfg_param[3] = ar->debug.htt_stats.cfg_param[3];
|
||||
stats_req->override_cfg_param = !!stats_req->cfg_param[0] ||
|
||||
!!stats_req->cfg_param[1] ||
|
||||
!!stats_req->cfg_param[2] ||
|
||||
!!stats_req->cfg_param[3];
|
||||
|
||||
ret = ath12k_debugfs_htt_stats_req(ar);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
file->private_data = stats_req;
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
kfree(stats_req);
|
||||
ar->debug.htt_stats.stats_req = NULL;
|
||||
err_unlock:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_release_htt_stats(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
struct ath12k *ar = inode->i_private;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
kfree(file->private_data);
|
||||
ar->debug.htt_stats.stats_req = NULL;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ath12k_read_htt_stats(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct debug_htt_stats_req *stats_req = file->private_data;
|
||||
char *buf;
|
||||
u32 length;
|
||||
|
||||
buf = stats_req->buf;
|
||||
length = min_t(u32, stats_req->buf_len, ATH12K_HTT_STATS_BUF_SIZE);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, length);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_dump_htt_stats = {
|
||||
.open = ath12k_open_htt_stats,
|
||||
.release = ath12k_release_htt_stats,
|
||||
.read = ath12k_read_htt_stats,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath12k_write_htt_stats_reset(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath12k *ar = file->private_data;
|
||||
enum ath12k_dbg_htt_ext_stats_type type;
|
||||
struct htt_ext_stats_cfg_params cfg_params = { 0 };
|
||||
u8 param_pos;
|
||||
int ret;
|
||||
|
||||
ret = kstrtou32_from_user(user_buf, count, 0, &type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (type >= ATH12K_DBG_HTT_NUM_EXT_STATS ||
|
||||
type == ATH12K_DBG_HTT_EXT_STATS_RESET)
|
||||
return -E2BIG;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
cfg_params.cfg0 = HTT_STAT_DEFAULT_RESET_START_OFFSET;
|
||||
param_pos = (type >> 5) + 1;
|
||||
|
||||
switch (param_pos) {
|
||||
case ATH12K_HTT_STATS_RESET_PARAM_CFG_32_BYTES:
|
||||
cfg_params.cfg1 = 1 << (cfg_params.cfg0 + type);
|
||||
break;
|
||||
case ATH12K_HTT_STATS_RESET_PARAM_CFG_64_BYTES:
|
||||
cfg_params.cfg2 = ATH12K_HTT_STATS_RESET_BITMAP32_BIT(cfg_params.cfg0 +
|
||||
type);
|
||||
break;
|
||||
case ATH12K_HTT_STATS_RESET_PARAM_CFG_128_BYTES:
|
||||
cfg_params.cfg3 = ATH12K_HTT_STATS_RESET_BITMAP64_BIT(cfg_params.cfg0 +
|
||||
type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar,
|
||||
ATH12K_DBG_HTT_EXT_STATS_RESET,
|
||||
&cfg_params,
|
||||
0ULL);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ar->debug.htt_stats.reset = type;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_htt_stats_reset = {
|
||||
.write = ath12k_write_htt_stats_reset,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void ath12k_debugfs_htt_stats_register(struct ath12k *ar)
|
||||
{
|
||||
debugfs_create_file("htt_stats_type", 0600, ar->debug.debugfs_pdev,
|
||||
ar, &fops_htt_stats_type);
|
||||
debugfs_create_file("htt_stats", 0400, ar->debug.debugfs_pdev,
|
||||
ar, &fops_dump_htt_stats);
|
||||
debugfs_create_file("htt_stats_reset", 0200, ar->debug.debugfs_pdev,
|
||||
ar, &fops_htt_stats_reset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,18 @@
|
|||
#ifndef DEBUG_HTT_STATS_H
|
||||
#define DEBUG_HTT_STATS_H
|
||||
|
||||
#define ATH12K_HTT_STATS_BUF_SIZE (1024 * 512)
|
||||
#define ATH12K_HTT_STATS_COOKIE_LSB GENMASK_ULL(31, 0)
|
||||
#define ATH12K_HTT_STATS_COOKIE_MSB GENMASK_ULL(63, 32)
|
||||
#define ATH12K_HTT_STATS_MAGIC_VALUE 0xF0F0F0F0
|
||||
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP32_OFFSET(_idx) ((_idx) & 0x1f)
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP64_OFFSET(_idx) ((_idx) & 0x3f)
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP32_BIT(_idx) (1 << \
|
||||
ATH12K_HTT_STATS_RESET_BITMAP32_OFFSET(_idx))
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP64_BIT(_idx) (1 << \
|
||||
ATH12K_HTT_STATS_RESET_BITMAP64_OFFSET(_idx))
|
||||
|
||||
void ath12k_debugfs_htt_stats_register(struct ath12k *ar);
|
||||
|
||||
/* htt_dbg_ext_stats_type */
|
||||
|
|
@ -17,4 +29,22 @@ enum ath12k_dbg_htt_ext_stats_type {
|
|||
ATH12K_DBG_HTT_NUM_EXT_STATS,
|
||||
};
|
||||
|
||||
enum ath12k_htt_stats_reset_cfg_param_alloc_pos {
|
||||
ATH12K_HTT_STATS_RESET_PARAM_CFG_32_BYTES = 1,
|
||||
ATH12K_HTT_STATS_RESET_PARAM_CFG_64_BYTES,
|
||||
ATH12K_HTT_STATS_RESET_PARAM_CFG_128_BYTES,
|
||||
};
|
||||
|
||||
struct debug_htt_stats_req {
|
||||
bool done;
|
||||
bool override_cfg_param;
|
||||
u8 pdev_id;
|
||||
enum ath12k_dbg_htt_ext_stats_type type;
|
||||
u32 cfg_param[4];
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
struct completion htt_stats_rcvd;
|
||||
u32 buf_len;
|
||||
u8 buf[];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1086,6 +1086,7 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
|
|||
struct htt_ext_stats_cfg_cmd *cmd;
|
||||
int len = sizeof(*cmd);
|
||||
int ret;
|
||||
u32 pdev_id;
|
||||
|
||||
skb = ath12k_htc_alloc_skb(ab, len);
|
||||
if (!skb)
|
||||
|
|
@ -1097,7 +1098,8 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
|
|||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
|
||||
|
||||
cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id;
|
||||
pdev_id = ath12k_mac_get_target_pdev_id(ar);
|
||||
cmd->hdr.pdev_mask = 1 << pdev_id;
|
||||
|
||||
cmd->hdr.stats_type = type;
|
||||
cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user