From c28cf6381c20a707a2898503677facf304896752 Mon Sep 17 00:00:00 2001
From: Bingquan Mou <moubingquan@huawei.com>
Date: Wed, 28 Jun 2023 11:13:03 +0800
Subject: [PATCH] hikptool: the PM trace function is added to the PCIe module.

The pm trace function of the PCIe module is added to improve the DFX.

Signed-off-by: Bingquan Mou <moubingquan@huawei.com>
---
 pcie/func_lib/pcie_func/pcie_common.h      |   1 +
 pcie/func_lib/pcie_func/pcie_link_ltssm.c  | 180 +++++++++++++++++++++
 pcie/func_lib/pcie_func/pcie_link_ltssm.h  |   7 +
 pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c |  17 +-
 pcie/usr_cmd/interface/pcie_common_api.c   |   1 +
 pcie/usr_cmd/interface/pcie_common_api.h   |   1 +
 6 files changed, 205 insertions(+), 2 deletions(-)

diff --git a/pcie/func_lib/pcie_func/pcie_common.h b/pcie/func_lib/pcie_func/pcie_common.h
index 434b4ed..98d9e25 100644
--- a/pcie/func_lib/pcie_func/pcie_common.h
+++ b/pcie/func_lib/pcie_func/pcie_common.h
@@ -28,6 +28,7 @@ enum pcie_trace_cmd_type {
 	TRACE_CLEAR = 2,
 	TRACE_INFO = 3,
 	TRACE_MODE = 4,
+	TRACE_PM = 5,
 };

 enum pcie_info_cmd_type {
diff --git a/pcie/func_lib/pcie_func/pcie_link_ltssm.c b/pcie/func_lib/pcie_func/pcie_link_ltssm.c
index d57688b..9c4b70c 100644
--- a/pcie/func_lib/pcie_func/pcie_link_ltssm.c
+++ b/pcie/func_lib/pcie_func/pcie_link_ltssm.c
@@ -43,6 +43,31 @@ union ltssm_state_reg {
 	uint64_t val;
 };

+union pm_state_reg {
+	struct {
+		uint64_t pm_state : 6;							 /* [0:5] */
+		uint64_t pm_clock : 18;							 /* [6:23] */
+		uint64_t reserved1 : 8;							 /* [24:31] */
+		uint64_t refclk_stable_vld : 1;                  /* [32] */
+		uint64_t enter_l12_case : 1;            		 /* [33] */
+		uint64_t pm_t_dl_l2_gnt_timeout : 1;             /* [34] */
+		uint64_t pm_t_dl_l1_gnt_timeout : 1;             /* [35] */
+		uint64_t pm_t_dl_l0s_gnt_timeout : 1;            /* [36] */
+		uint64_t pm_t_dl_lastack_timeout : 1;      		 /* [37] */
+		uint64_t pme_turn_off_vld_hold : 1;              /* [38] */
+		uint64_t pm_blk_tlp_timeout : 1;                 /* [39] */
+		uint64_t aspm_nak_vld : 1;            			 /* [40] */
+		uint64_t retrain_link_vld : 1;       			 /* [41] */
+		uint64_t pending_dllp_vld : 1;             		 /* [42] */
+		uint64_t pm_wakeup_tol0_en : 1;           		 /* [43] */
+		uint64_t mac2pm_rx_data_vld : 1;  			     /* [44] */
+		uint64_t dfe_req : 1;      						 /* [45] */
+		uint64_t pm_t_dfe_time_meet : 1; 				 /* [46] */
+		uint64_t reserved2 : 17;              			 /* [47:63] */
+	} bits;
+	uint64_t val;
+};
+
 static int pcie_get_ltssm_trace(uint32_t port_id, uint64_t *ltssm_status, uint32_t *ltssm_num)
 {
 	struct hikp_cmd_header req_header;
@@ -280,3 +305,158 @@ free_cmd_ret:

 	return ret;
 }
+
+static int pcie_get_pm_trace(uint32_t port_id, uint64_t *pm_status, uint32_t *pm_num)
+{
+	struct hikp_cmd_header req_header;
+	struct hikp_cmd_ret *cmd_ret = NULL;
+	struct pcie_trace_req_para req_data = { 0 };
+	size_t src_size, dst_size;
+	int ret;
+
+	req_data.port_id = port_id;
+	hikp_cmd_init(&req_header, PCIE_MOD, PCIE_TRACE, TRACE_PM);
+	cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data));
+	ret = hikp_rsp_normal_check(cmd_ret);
+	if (ret) {
+		Err("PCIe Base", "pcie pm trace cmd_ret check failed, ret: %d.\n", ret);
+		goto free_cmd_ret;
+	}
+
+	if (cmd_ret->rsp_data_num == 0) {
+		Err("PCIe Base", "without rsp data.\n");
+		ret = -EINVAL;
+		goto free_cmd_ret;
+	}
+	/* 0: First uint32_t is pm trace num received from TF */
+	*pm_num = cmd_ret->rsp_data[0];
+
+	if ((cmd_ret->rsp_data_num - 1) * sizeof(uint32_t) != (*pm_num) * sizeof(uint64_t)) {
+		Err("PCIe Base", "rsp data number check failed, rsp_data_num: %u, pm_num: %u.\n",
+		    cmd_ret->rsp_data_num, *pm_num);
+		ret = -EINVAL;
+		goto free_cmd_ret;
+	}
+
+	src_size = (*pm_num) * sizeof(uint64_t);
+	dst_size = TRACER_DEPTH * sizeof(uint64_t);
+	if (src_size > dst_size) {
+		Err("PCIe Base", "size check failed, %u > %u.\n", src_size, dst_size);
+		ret = -EINVAL;
+		goto free_cmd_ret;
+	}
+	memcpy(pm_status, (cmd_ret->rsp_data + 1), src_size);
+
+free_cmd_ret:
+	free(cmd_ret);
+	return ret;
+}
+
+struct pcie_pm_num_string g_pm_string_table[] = {
+	{0x0,	"pm_pme_idle"},
+	{0x1,	"pm_wait_dc_pme_msg_send_out"},
+	{0x2,	"pm_wait_dc_tl_enter_l2"},
+	{0x3,	"pm_wait_dc_dl_enter_l2"},
+	{0x4,	"pm_wait_dc_mac_enter_l2"},
+	{0x5,	"pm_dc_enter_l2"},
+	{0x6,	"pm_wait_dc_tl_enter_pcipm_l1"},
+	{0x7,	"pm_wait_dc_dl_enter_pcipm_l1"},
+	{0x8,	"pm_wait_dc_tl_enter_aspm_l1"},
+	{0x9,	"pm_wait_dc_dl_enter_aspm_l1"},
+	{0xa,	"pm_wait_tl_enter_aspm_l0"},
+	{0xb,	"pm_wait_dl_enter_aspm_l0"},
+	{0xc,	"pm_wait_dc_mac_enter_l1"},
+	{0xd,	"pm_wait_mac_enter_l0s"},
+	{0xe,	"pm_device_in_l0s"},
+	{0xf,	"pm_dc_device_in_l1"},
+	{0x10,	"pm_wait_dc_enter_l0"},
+	{0x11,	"pm_wait_uc_tl_enter_l2"},
+	{0x12,	"pm_wait_uc_dl_enter_l2"},
+	{0x13,	"pm_wait_uc_mac_enter_l2"},
+	{0x15,	"pm_wait_uc_tl_enter_pcipm_l1"},
+	{0x17,	"pm_wait_uc_dl_enter_aspm_l1"},
+	{0x18,	"pm_wait_uc_tl_enter_aspm_l1"},
+	{0x1a,	"pm_wait_uc_dl_enter_pcipm_l1"},
+	{0x1c,	"pm_wait_uc_mac_enter_l1"},
+	{0x1d,	"pm_wait_uc_pme_enter_l1_nak_sent_out"},
+	{0x1e,	"pm_wait_uc_enter_l0"},
+	{0x20,	"pm_device_will_enter_l1_substate"},
+	{0x21,	"pm_device_in_l1_1"},
+	{0x22,	"pm_device_will_exit_l1_substate"},
+	{0x23,	"pm_device_in_l1_2_entry"},
+	{0x24,	"pm_device_in_l1_2_idle"},
+	{0x25,	"pm_device_in_l1_2_exit"},
+	{-1,	"unknown"} /* end of array */
+};
+
+static char *hisi_pcie_pm_string_get(uint32_t pm)
+{
+	int i = 0;
+
+	while (g_pm_string_table[i].pm >= 0) {
+		if ((uint32_t)g_pm_string_table[i].pm != pm) {
+			i++;
+			continue;
+		}
+		break;
+	}
+
+	return g_pm_string_table[i].pm_c;
+}
+
+static int pcie_print_pm_trace(const uint64_t *pm_status, uint32_t pm_num)
+{
+	uint32_t i;
+	char *pm_c = NULL;
+	union pm_state_reg pm_val;
+
+	if (pm_num > TRACER_DEPTH || pm_num == 0) {
+		Err("PCIe Base", "pm_num(%u) is over range or zero\n", pm_num);
+		return -EINVAL;
+	}
+	Info("PCIe Base", "pm tracer:\n");
+	Info("PCIe Base", "\ttrace state: %llx\n", pm_status[0]);
+	Info("PCIe Base",
+	     "\tpm[ii]: BE8: 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 "
+	     "BD8:   23:6   5:0 :  pm state\n");
+	for (i = 1; i < pm_num; i++) {
+		pm_val.val = pm_status[i];
+		pm_c = hisi_pcie_pm_string_get((uint32_t)pm_val.bits.pm_state);
+		Info("PCIe Base",
+			"\tpm[%02u]:\t     %x  %x  %x  %x  %x  %x %x %x %x %x %x %x %x %x %x     0x%06x  0x%02x   %s\n",
+			i,
+			(uint32_t)pm_val.bits.pm_t_dfe_time_meet,
+			(uint32_t)pm_val.bits.dfe_req,
+			(uint32_t)pm_val.bits.mac2pm_rx_data_vld,
+			(uint32_t)pm_val.bits.pm_wakeup_tol0_en,
+			(uint32_t)pm_val.bits.pending_dllp_vld,
+			(uint32_t)pm_val.bits.retrain_link_vld,
+			(uint32_t)pm_val.bits.aspm_nak_vld,
+			(uint32_t)pm_val.bits.pm_blk_tlp_timeout,
+			(uint32_t)pm_val.bits.pme_turn_off_vld_hold,
+			(uint32_t)pm_val.bits.pm_t_dl_lastack_timeout,
+			(uint32_t)pm_val.bits.pm_t_dl_l0s_gnt_timeout,
+			(uint32_t)pm_val.bits.pm_t_dl_l1_gnt_timeout,
+			(uint32_t)pm_val.bits.pm_t_dl_l2_gnt_timeout,
+			(uint32_t)pm_val.bits.enter_l12_case,
+			(uint32_t)pm_val.bits.refclk_stable_vld,
+			(uint32_t)pm_val.bits.pm_clock,
+			(uint32_t)pm_val.bits.pm_state,
+			pm_c);
+	}
+
+	return 0;
+}
+
+int pcie_pm_trace(uint32_t port_id)
+{
+	int ret;
+	uint32_t pm_num = 0;
+	uint64_t pm_st_save[TRACER_DEPTH];
+
+	ret = pcie_get_pm_trace(port_id, pm_st_save, &pm_num);
+	if (ret)
+		return ret;
+
+	return pcie_print_pm_trace(pm_st_save, pm_num);
+}
\ No newline at end of file
diff --git a/pcie/func_lib/pcie_func/pcie_link_ltssm.h b/pcie/func_lib/pcie_func/pcie_link_ltssm.h
index eb57ead..8f3502b 100644
--- a/pcie/func_lib/pcie_func/pcie_link_ltssm.h
+++ b/pcie/func_lib/pcie_func/pcie_link_ltssm.h
@@ -18,12 +18,18 @@

 #define TRACE_STR_NUM 0x20
 #define TRACER_DEPTH 65
+#define PM_TRACE_STR_NUM 0x28

 struct pcie_ltssm_num_string {
 	int ltssm;
 	char ltssm_c[TRACE_STR_NUM];
 };

+struct pcie_pm_num_string {
+	int pm;
+	char pm_c[PM_TRACE_STR_NUM];
+};
+
 struct pcie_trace_req_para {
 	uint32_t port_id;
 	uint32_t trace_mode;
@@ -51,5 +57,6 @@ int pcie_ltssm_trace_show(uint32_t port_id);
 int pcie_ltssm_trace_clear(uint32_t port_id);
 int pcie_ltssm_trace_mode_set(uint32_t port_id, uint32_t mode);
 int pcie_ltssm_link_status_get(uint32_t port_id);
+int pcie_pm_trace(uint32_t port_id);

 #endif
diff --git a/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c b/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c
index e50b434..8ceb85a 100644
--- a/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c
+++ b/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c
@@ -37,6 +37,7 @@ static int pcie_trace_help(struct major_cmd_ctrl *self, const char *argv)
 	printf("    %s, %-25s %s\n", "-m", "--mode",
 	       "set ltssm trace mode val 1:recver_en 0:recver_dis\n");
 	printf("    %s, %-25s %s\n", "-f", "--information", "display link information\n");
+	printf("    %s, %-25s %s\n", "-pm", "--pm-state", "show pm status\n");
 	printf("\n");

 	return 0;
@@ -57,6 +58,13 @@ static int pcie_trace_show(struct major_cmd_ctrl *self, const char *argv)
 	return 0;
 }

+static int pcie_pm_show(struct major_cmd_ctrl *self, const char *argv)
+{
+	g_trace_cmd.cmd_type = TRACE_PM;
+
+	return 0;
+}
+
 static int pcie_trace_mode_set(struct major_cmd_ctrl *self, const char *argv)
 {
 	int ret;
@@ -108,6 +116,8 @@ static int pcie_trace_excute_funs_call(int cmd_type)
 		return comm_api->ltssm_trace_mode_set(port_id, recover_en);
 	else if (cmd_type == TRACE_INFO)
 		return comm_api->ltssm_link_information_get(port_id);
+	else if (cmd_type == TRACE_PM)
+		return comm_api->pm_trace(port_id);
 	else
 		return -EINVAL;
 }
@@ -120,14 +130,16 @@ static void pcie_trace_execute(struct major_cmd_ctrl *self)
 		"pcie_trace_show success.",
 		"pcie_trace_clear success.",
 		"get mac link information success.",
-		"pcie_trace_mode_set success."
+		"pcie_trace_mode_set success.",
+		"pcie_pm_trace success."
 	};
 	const char *err_msg[] = {
 		"pcie_trace sub command type error.",
 		"pcie_trace_show error.",
 		"pcie_trace_clear error.",
 		"get mac link information error.",
-		"pcie_trace_mode_set error."
+		"pcie_trace_mode_set error.",
+		"pcie_pm_trace error"
 	};

 	ret = pcie_trace_excute_funs_call(g_trace_cmd.cmd_type);
@@ -153,6 +165,7 @@ static void cmd_pcie_trace_init(void)
 	cmd_option_register("-m", "--mode", true, pcie_trace_mode_set);
 	cmd_option_register("-f", "--information", false, pcie_link_information_get);
 	cmd_option_register("-i", "--interface", true, pcie_port_id_set);
+	cmd_option_register("-pm", "--pm-state", false, pcie_pm_show);
 }

 HIKP_CMD_DECLARE("pcie_trace", "pcie ltssm trace", cmd_pcie_trace_init);
diff --git a/pcie/usr_cmd/interface/pcie_common_api.c b/pcie/usr_cmd/interface/pcie_common_api.c
index 491daf2..8875481 100644
--- a/pcie/usr_cmd/interface/pcie_common_api.c
+++ b/pcie/usr_cmd/interface/pcie_common_api.c
@@ -27,6 +27,7 @@ struct pcie_comm_api g_tools_api = {
 	.err_status_clear = pcie_error_state_clear,
 	.reg_dump = pcie_dumpreg_do_dump,
 	.reg_read = pcie_reg_read,
+	.pm_trace = pcie_pm_trace,
 };


diff --git a/pcie/usr_cmd/interface/pcie_common_api.h b/pcie/usr_cmd/interface/pcie_common_api.h
index 9809575..08d4403 100644
--- a/pcie/usr_cmd/interface/pcie_common_api.h
+++ b/pcie/usr_cmd/interface/pcie_common_api.h
@@ -37,6 +37,7 @@ struct pcie_comm_api {
 	int (*err_status_clear)(uint32_t port_id);
 	int (*reg_dump)(uint32_t port_id, uint32_t dump_level);
 	int (*reg_read)(uint32_t port_id, uint32_t moudle_id, uint32_t offset);
+	int (*pm_trace)(uint32_t port_id);
 };

 struct pcie_comm_api *pcie_get_comm_api(void);
--
2.33.0