Quellcode durchsuchen

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

qctecmdr vor 3 Jahren
Ursprung
Commit
2e1ff23596

+ 75 - 0
drivers/platform/msm/gsi/gsi.c

@@ -43,6 +43,15 @@
 #define GSI_MSB(num) ((u32)((num & GSI_MSB_MASK) >> 32))
 #define GSI_LSB(num) ((u32)(num & GSI_LSB_MASK))
 
+#define GSI_INST_RAM_FW_VER_OFFSET			(0)
+#define GSI_INST_RAM_FW_VER_GSI_3_0_OFFSET	(64)
+#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)
 {
@@ -5069,6 +5078,72 @@ 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)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_BP_CNT_LSB) +
+						((u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_BP_CNT_MSB) << 32);
+	stats->bp_and_pending_cnt = (u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB) +
+						((u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB) << 32);
+	stats->mcs_busy_cnt = (u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB) +
+						((u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB) << 32);
+	stats->mcs_idle_cnt = (u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB) +
+						((u64)gsihal_read_reg(
+						GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB) << 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;
+	}
+
+	if (gsi_ctx->per.ver < GSI_VER_3_0)
+		raw = gsihal_read_reg_n(GSI_GSI_INST_RAM_n,
+			GSI_INST_RAM_FW_VER_OFFSET);
+	else
+		raw = gsihal_read_reg_n(GSI_GSI_INST_RAM_n,
+			GSI_INST_RAM_FW_VER_GSI_3_0_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)
 {

+ 44 - 0
drivers/platform/msm/gsi/gsi.h

@@ -1544,6 +1544,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: Back Pressure occurences count
+ * @bp_and_pending_cnt: Back Pressure with pending back pressure count
+ * @mcs_busy_cnt: Cycle count for MCS busy
+ * @mcs_idle_cnt: 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,
@@ -2299,6 +2325,24 @@ int gsi_query_msi_addr(unsigned long chan_hdl, phys_addr_t *addr);
 */
 void gsi_dump_ch_info(unsigned long chan_hdl);
 
+/**
+ * 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,

+ 101 - 2
drivers/platform/msm/gsi/gsi_dbg.c

@@ -12,6 +12,8 @@
 #include "gsi.h"
 #include "gsihal.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);
@@ -584,6 +586,80 @@ 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 = div_u64(
+				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,
 };
@@ -616,10 +692,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)) {
@@ -683,8 +768,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);
 }
-

+ 56 - 0
drivers/platform/msm/gsi/gsihal/gsihal_reg.c

@@ -163,6 +163,14 @@ static const char *gsireg_name_to_str[GSI_REG_MAX] = {
 	__stringify(GSI_INTER_EE_n_SRC_EV_CH_IRQ_k),
 	__stringify(GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_k),
 	__stringify(GSI_GSI_SHRAM_n),
+	__stringify(GSI_GSI_MCS_PROFILING_BP_CNT_LSB),
+	__stringify(GSI_GSI_MCS_PROFILING_BP_CNT_MSB),
+	__stringify(GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB),
+	__stringify(GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB),
+	__stringify(GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB),
+	__stringify(GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB),
+	__stringify(GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB),
+	__stringify(GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB),
 };
 
 /*
@@ -1686,6 +1694,30 @@ static struct gsihal_reg_obj gsihal_reg_objs[GSI_VER_MAX][GSI_REG_MAX] = {
 	[GSI_VER_2_9][GSI_EE_n_GSI_CH_k_CNTXT_1] = {
 	gsireg_construct_ch_k_cntxt_1_v2_9, gsireg_parse_dummy,
 	0x0000f004, 0x4000, 0x80},
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_BP_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0000185c, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_BP_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001860, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001864, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001868, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0000186c, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001870, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001874, 0, 0 },
+	[GSI_VER_2_9][GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001878, 0, 0 },
 
 	/* GSIv2_11 */
 	[GSI_VER_2_11][GSI_GSI_IRAM_PTR_MSI_DB] = {
@@ -1933,6 +1965,30 @@ static struct gsihal_reg_obj gsihal_reg_objs[GSI_VER_MAX][GSI_REG_MAX] = {
 	[GSI_VER_3_0][GSI_MAP_EE_n_CH_k_VP_TABLE] = {
 	gsireg_construct_dummy, gsireg_parse_dummy,
 	0x00009000, 0x400, 0x4 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_BP_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a5c, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_BP_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a60, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a64, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a68, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a6c, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a70, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a74, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00001a78, 0, 0 },
 };
 
 /*

+ 8 - 0
drivers/platform/msm/gsi/gsihal/gsihal_reg.h

@@ -153,6 +153,14 @@ enum gsihal_reg_name {
 	GSI_INTER_EE_n_SRC_EV_CH_IRQ_k,
 	GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_k,
 	GSI_GSI_SHRAM_n,
+	GSI_GSI_MCS_PROFILING_BP_CNT_LSB,
+	GSI_GSI_MCS_PROFILING_BP_CNT_MSB,
+	GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_LSB,
+	GSI_GSI_MCS_PROFILING_BP_AND_PENDING_CNT_MSB,
+	GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_LSB,
+	GSI_GSI_MCS_PROFILING_MCS_BUSY_CNT_MSB,
+	GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_LSB,
+	GSI_GSI_MCS_PROFILING_MCS_IDLE_CNT_MSB,
 	GSI_REG_MAX
 };