Merge "msm: gsi: add gsi profiling stats and fw version to debugfs"

This commit is contained in:
qctecmdr 2021-04-27 05:09:14 -07:00 committed by Gerrit - the friendly Code Review server
commit d1423053e4
4 changed files with 256 additions and 2 deletions

View File

@ -38,6 +38,14 @@
#define GSI_STTS_REG_BITS 32
#define GSI_INST_RAM_FW_VER_OFFSET (0)
#define GSI_INST_RAM_FW_VER_HW_MASK (0xFC00)
#define GSI_INST_RAM_FW_VER_HW_SHIFT (10)
#define GSI_INST_RAM_FW_VER_FLAVOR_MASK (0x380)
#define GSI_INST_RAM_FW_VER_FLAVOR_SHIFT (7)
#define GSI_INST_RAM_FW_VER_FW_MASK (0x7f)
#define GSI_INST_RAM_FW_VER_FW_SHIFT (0)
#ifndef CONFIG_DEBUG_FS
void gsi_debugfs_init(void)
{
@ -5059,6 +5067,69 @@ static union __packed gsi_channel_scratch __gsi_update_mhi_channel_scratch(
return scr;
}
/**
* gsi_get_hw_profiling_stats() - Query GSI HW profiling stats
* @stats: [out] stats blob from client populated by driver
*
* Returns: 0 on success, negative on failure
*
*/
int gsi_get_hw_profiling_stats(struct gsi_hw_profiling_data *stats)
{
if (stats == NULL) {
GSIERR("bad parms NULL stats == NULL\n");
return -EINVAL;
}
stats->bp_cnt = (u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_BP_CNT_LSB_OFFS) +
((u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_BP_CNT_MSB_OFFS) << 32);
stats->bp_and_pending_cnt = (u64)gsi_readl( gsi_ctx->base +
GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB_OFFS) +
((u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB_OFFS)
<< 32);
stats->mcs_busy_cnt = (u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB_OFFS) +
((u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB_OFFS) << 32);
stats->mcs_idle_cnt = (u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB_OFFS) +
((u64)gsi_readl(gsi_ctx->base +
GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB_OFFS) << 32);
return 0;
}
/**
* gsi_get_fw_version() - Query GSI FW version
* @ver: [out] ver blob from client populated by driver
*
* Returns: 0 on success, negative on failure
*
*/
int gsi_get_fw_version(struct gsi_fw_version *ver)
{
u32 raw = 0;
if (ver == NULL) {
GSIERR("bad parms: ver == NULL\n");
return -EINVAL;
}
raw = gsi_readl(gsi_ctx->base +
GSI_V2_5_GSI_INST_RAM_n_OFFS(GSI_INST_RAM_FW_VER_OFFSET));
ver->hw = (raw & GSI_INST_RAM_FW_VER_HW_MASK) >>
GSI_INST_RAM_FW_VER_HW_SHIFT;
ver->flavor = (raw & GSI_INST_RAM_FW_VER_FLAVOR_MASK) >>
GSI_INST_RAM_FW_VER_FLAVOR_SHIFT;
ver->fw = (raw & GSI_INST_RAM_FW_VER_FW_MASK) >>
GSI_INST_RAM_FW_VER_FW_SHIFT;
return 0;
}
static int msm_gsi_probe(struct platform_device *pdev)
{

View File

@ -1412,6 +1412,32 @@ enum gsi_generic_ee_cmd_return_code {
GSI_GEN_EE_CMD_RETURN_CODE_OUT_OF_RESOURCES = 0x7,
};
/**
* struct gsi_hw_profiling_data - GSI profiling data
* @bp_cnt_lsb: Back Pressure occurences count
* @bp_and_pending_cnt_lsb: Back Pressure with pending back pressure count
* @mcs_busy_cnt_lsb: Cycle count for MCS busy
* @mcs_idle_cnt_lsb: Cycle count for MCS idle
*/
struct gsi_hw_profiling_data {
u64 bp_cnt;
u64 bp_and_pending_cnt;
u64 mcs_busy_cnt;
u64 mcs_idle_cnt;
};
/**
* struct gsi_fw_version - GSI fw version data
* @hw: HW version
* @flavor: Flavor identifier
* @fw: FW version
*/
struct gsi_fw_version {
u32 hw;
u32 flavor;
u32 fw;
};
enum gsi_generic_ee_cmd_query_retun_val {
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_PRIMARY = 0,
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_SECONDARY = 1,
@ -2127,6 +2153,25 @@ int gsi_alloc_channel_ee(unsigned int chan_idx, unsigned int ee, int *code);
*/
int gsi_enable_flow_control_ee(unsigned int chan_idx, unsigned int ee,
int *code);
/**
* gsi_get_hw_profiling_stats() - Query GSI HW profiling stats
* @stats: [out] stats blob from client populated by driver
*
* Returns: 0 on success, negative on failure
*
*/
int gsi_get_hw_profiling_stats(struct gsi_hw_profiling_data *stats);
/**
* gsi_get_fw_version() - Query GSI FW version
* @ver: [out] ver blob from client populated by driver
*
* Returns: 0 on success, negative on failure
*
*/
int gsi_get_fw_version(struct gsi_fw_version *ver);
int gsi_flow_control_ee(unsigned int chan_idx, unsigned int ee,
bool enable, bool prmy_scnd_fc, int *code);
int gsi_query_flow_control_state_ee(unsigned int chan_idx, unsigned int ee,

View File

@ -12,6 +12,8 @@
#include "gsi_reg.h"
#include "gsi.h"
#define GSI_MAX_MSG_LEN 4096
#define TERR(fmt, args...) \
pr_err("%s:%d " fmt, __func__, __LINE__, ## args)
#define TDBG(fmt, args...) \
@ -20,7 +22,7 @@
pr_err(fmt, ## args)
static struct dentry *dent;
static char dbg_buff[4096];
static char dbg_buff[GSI_MAX_MSG_LEN];
static void *gsi_ipc_logbuf_low;
static void gsi_wq_print_dp_stats(struct work_struct *work);
@ -662,6 +664,79 @@ static ssize_t gsi_enable_ipc_low(struct file *file,
return count;
}
static ssize_t gsi_read_gsi_hw_profiling_stats(struct file *file,
char __user *buf, size_t count, loff_t *ppos)
{
struct gsi_hw_profiling_data stats;
int nbytes, cnt = 0;
u64 totalCycles = 0, util = 0;
if (gsi_ctx->per.ver < GSI_VER_2_9) {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"This feature only support on GSI2.9+\n");
cnt += nbytes;
goto done;
}
if (!gsi_get_hw_profiling_stats(&stats)) {
totalCycles = stats.mcs_busy_cnt + stats.mcs_idle_cnt +
stats.bp_and_pending_cnt;
if (totalCycles != 0)
util = (100 * (stats.mcs_busy_cnt + stats.bp_and_pending_cnt)) /
totalCycles;
else
util = 0;
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"bp_count=0x%llx\n"
"bp_and_pending_count=0x%llx\n"
"mcs_busy=0x%llx\n"
"mcs_idle=0x%llx\n"
"total_cycle_count=0x%llx\n"
"utilization_percentage=%llu%%\n",
stats.bp_cnt,
stats.bp_and_pending_cnt,
stats.mcs_busy_cnt,
stats.mcs_idle_cnt,
totalCycles,
util);
cnt += nbytes;
} else {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"Fail to read GSI HW Profiling stats\n");
cnt += nbytes;
}
done:
return simple_read_from_buffer(buf, count, ppos, dbg_buff, cnt);
}
static ssize_t gsi_read_gsi_fw_version(struct file *file,
char __user *buf, size_t count, loff_t *ppos)
{
struct gsi_fw_version ver;
int nbytes, cnt = 0;
if (gsi_ctx->per.ver < GSI_VER_2_9) {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"This feature only support on GSI2.9+\n");
cnt += nbytes;
goto done;
}
if (!gsi_get_fw_version(&ver)) {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"hw=%d\nflavor=%d\nfw=%d\n",
ver.hw,
ver.flavor,
ver.fw);
cnt += nbytes;
} else {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"Fail to read GSI FW version\n");
cnt += nbytes;
}
done:
return simple_read_from_buffer(buf, count, ppos, dbg_buff, cnt);
}
static const struct file_operations gsi_ev_dump_ops = {
.write = gsi_dump_evt,
};
@ -694,10 +769,19 @@ static const struct file_operations gsi_ipc_low_ops = {
.write = gsi_enable_ipc_low,
};
static const struct file_operations gsi_hw_profiling_ops = {
.read = gsi_read_gsi_hw_profiling_stats,
};
static const struct file_operations gsi_ver_ops = {
.read = gsi_read_gsi_fw_version,
};
void gsi_debugfs_init(void)
{
static struct dentry *dfile;
const mode_t write_only_mode = 0220;
const mode_t read_only_mode = 0440;
dent = debugfs_create_dir("gsi", 0);
if (IS_ERR(dent)) {
@ -761,8 +845,22 @@ void gsi_debugfs_init(void)
goto fail;
}
dfile = debugfs_create_file("gsi_hw_profiling_stats", read_only_mode,
dent, 0, &gsi_hw_profiling_ops);
if (!dfile || IS_ERR(dfile)) {
TERR("could not create gsi_hw_profiling_stats\n");
goto fail;
}
dfile = debugfs_create_file("gsi_fw_version", read_only_mode, dent, 0,
&gsi_ver_ops);
if (!dfile || IS_ERR(dfile)) {
TERR("could not create gsi_fw_version\n");
goto fail;
}
return;
fail:
debugfs_remove_recursive(dent);
}

View File

@ -1212,4 +1212,44 @@
#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_PHY_CH_BMSK 0x1f
#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_PHY_CH_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_BP_CNT_LSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x0000185c)
#define GSI_GSI_MCS_PROFILING_BP_CNT_LSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_BP_CNT_LSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_BP_CNT_MSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00001860)
#define GSI_GSI_MCS_PROFILING_BP_CNT_MSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_BP_CNT_MSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00001864)
#define GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00001868)
#define GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x0000186c)
#define GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00001870)
#define GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00001874)
#define GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB_SHFT 0x0
#define GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00001878)
#define GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB_RMSK 0xffffffff
#define GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB_SHFT 0x0
#endif /* __GSI_REG_V2_H__ */