Merge "msm: gsi: add gsi profiling stats and fw version to debugfs"
This commit is contained in:
commit
d1423053e4
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user