From 71cc63275102a8956afaf60f9183899cd7c4cc82 Mon Sep 17 00:00:00 2001 From: Jie Hai Date: Tue, 17 Dec 2024 15:29:28 +0800 Subject: [PATCH] hikptool/hccs: support dump hccs info 1. support dump HCCS topology. e.g. hikptool hccs -g topo 2. support dump HCCS port fixed attributes. e.g. hikptool hccs -g fixed_attr -c \ -d -p 3. support dump HCCS port dfx information. e.g. hikptool hccs -g dfx_info -c \ -d -p Signed-off-by: Huisong Li Signed-off-by: Jie Hai --- CMakeLists.txt | 1 + hccs/hikp_hccs.c | 807 ++++++++++++++++++++++++++++ hccs/hikp_hccs.h | 161 ++++++ libhikptdev/include/hikptdev_plug.h | 1 + 4 files changed, 970 insertions(+) create mode 100644 hccs/hikp_hccs.c create mode 100644 hccs/hikp_hccs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 56cc932..72f2dab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ file(GLOB_RECURSE HIKPTOOL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sata/*.c ${CMAKE_CURRENT_SOURCE_DIR}/serdes/*.c ${CMAKE_CURRENT_SOURCE_DIR}/socip/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/hccs/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c ${CMAKE_CURRENT_SOURCE_DIR}/info_collect/*.c ${CMAKE_CURRENT_SOURCE_DIR}/hikp_init_main.c diff --git a/hccs/hikp_hccs.c b/hccs/hikp_hccs.c new file mode 100644 index 0000000..5ef4222 --- /dev/null +++ b/hccs/hikp_hccs.c @@ -0,0 +1,807 @@ +/* + * Copyright (c) 2024-2025 Hisilicon Technologies Co., Ltd. + * Hikptool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * + * See the Mulan PSL v2 for more details. + */ + +#include +#include +#include +#include +#include +#include +#include "tool_cmd.h" +#include "hikpt_rciep.h" +#include "hikp_hccs.h" + +enum hccs_link_fsm { + HCCS_PORT_RESET = 1, + HCCS_PORT_SETUP, + HCCS_PORT_CONFIG, + HCCS_PORT_READY +}; + +const struct { + enum hccs_link_fsm link_fsm; + const char *str; +} link_fsm_map[] = { + {HCCS_PORT_RESET, "reset"}, + {HCCS_PORT_SETUP, "setup"}, + {HCCS_PORT_CONFIG, "config"}, + {HCCS_PORT_READY, "link-up"}, +}; + +static struct hccs_param g_hccs_param = { 0 }; +static struct hikp_plat_hccs_info g_hccs_info = { 0 }; + +static int hikp_hccs_get_plat_topo(struct hccs_param *param, + union hccs_feature_info *info); +static void hikp_hccs_show_topo(union hccs_feature_info *data); +static int hikp_hccs_get_port_attr(struct hccs_param *param, + union hccs_feature_info *info); +static void hikp_hccs_show_port_attr(union hccs_feature_info *feature_info); +static int hikp_hccs_get_port_dfx_info(struct hccs_param *param, + union hccs_feature_info *info); +static void hikp_hccs_show_port_dfx_info(union hccs_feature_info *feature_info); +static int hikp_plat_hccs_hw_info(struct hikp_plat_hccs_info *hccs_info); +static int hikp_hccs_get_die_num(uint8_t chip_id, struct hikp_plat_hccs_info *hccs_info); + +static const struct hikp_hccs_feature_cmd g_hccs_feature_cmd[] = { + {"topo", HCCS_GET_PORT_IDS_ON_DIE, hikp_hccs_get_plat_topo, + hikp_hccs_show_topo, 0}, + {"fixed_attr", HCCS_GET_PORT_FIXED_ATTR, hikp_hccs_get_port_attr, + hikp_hccs_show_port_attr, HCCS_PORT_INFO_MASK}, + {"dfx_info", HCCS_GET_PORT_DFX_INFO, hikp_hccs_get_port_dfx_info, + hikp_hccs_show_port_dfx_info, HCCS_PORT_INFO_MASK}, +}; + +static int hikp_hccs_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + HIKP_SET_USED(argv); + + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-c", "--chip_id=", "target chip"); + printf(" %s, %-25s %s\n", "-d", "--die_id=", "target die"); + printf(" %s, %-25s %s\n", "-p", "--port_id=", "target port"); + printf(" %s\n", + "[-g/--get ]\n" + " topo : get hccs_typo info, no target specified.\n" + " fixed_attr : get fixed attributes for port specified by -c X -d X -p X.\n" + " dfx_info : get dfx info for port specified by -c X -d X -p X.\n"); + return 0; +} + +static int hikp_hccs_cmd_send(struct hikp_cmd_header *req_header, + struct hikp_hccs_req *req_data, + void *buff, size_t buff_len, + struct hikp_hccs_rsp_head *rsp_head) +{ + struct hikp_cmd_ret *cmd_ret; + struct hikp_hccs_rsp *rsp; + uint64_t cur_blk_size; + int ret; + + cmd_ret = hikp_cmd_alloc(req_header, req_data, sizeof(struct hikp_hccs_req)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to query from firmware! ret = %d.\n", ret); + goto out; + } + + rsp = (struct hikp_hccs_rsp *)cmd_ret->rsp_data; + cur_blk_size = rsp->rsp_head.cur_blk_size; + if (cur_blk_size == 0) { + HIKP_ERROR_PRINT("Firmware reported zero data size!\n"); + ret = -EINVAL; + goto out; + } + if (cur_blk_size > buff_len || + cur_blk_size > sizeof(struct hikp_hccs_rsp)) { + HIKP_ERROR_PRINT("The firmware data size (%" PRIu64 ") greater than " + "sw buffer(%zu) or hikp_hccs_rsp size(%zu).\n", + cur_blk_size, buff_len, sizeof(struct hikp_hccs_rsp)); + ret = -EINVAL; + goto out; + } + + memcpy(buff, rsp->rsp_data, rsp->rsp_head.cur_blk_size); + rsp_head->total_blk_num = rsp->rsp_head.total_blk_num; + rsp_head->cur_blk_size = rsp->rsp_head.cur_blk_size; + +out: + hikp_cmd_free(&cmd_ret); + return ret; +} + +static int hikp_hccs_query(struct hikp_cmd_header *req_header, + struct hikp_hccs_req *req_data, + void *buff, size_t buff_len) +{ + struct hikp_hccs_rsp_head rsp_head = {0}; + uint16_t total_blk_size = 0; + uint16_t total_blk_num; + uint16_t blk_id = 0; + int ret; + + ret = hikp_hccs_cmd_send(req_header, req_data, buff, buff_len, &rsp_head); + if (ret != 0) + return ret; + total_blk_num = rsp_head.total_blk_num; + total_blk_size += rsp_head.cur_blk_size; + for (blk_id = 1; blk_id < total_blk_num; blk_id++) { + if (buff_len <= total_blk_size) { + HIKP_ERROR_PRINT("No enough buffer to get block-(%u) context.\n", + blk_id); + return -EINVAL; + } + + req_data->head.blk_id = blk_id; + ret = hikp_hccs_cmd_send(req_header, req_data, + (uint8_t *)buff + total_blk_size, + buff_len - total_blk_size, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get context for block-(%u)!\n", + blk_id); + return -EINVAL; + } + total_blk_size += rsp_head.cur_blk_size; + } + + return 0; +} + +static int hikp_hccs_get_chip_num(struct hikp_plat_hccs_info *hccs_info) +{ + struct hccs_chip_num_rsp_data rsp_data = {0}; + struct hikp_cmd_header req_header = {0}; + struct hikp_hccs_req req = {0}; + int ret; + + hikp_cmd_init(&req_header, HCCS_MOD, HCCS_GET_CHIP_NUM, 0); + ret = hikp_hccs_query(&req_header, &req, + &rsp_data, sizeof(struct hccs_chip_num_rsp_data)); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get chip number from firmware, ret = %d!\n", ret); + return ret; + } + + if (rsp_data.chip_num == 0) { + HIKP_ERROR_PRINT("The chip number obtained from firmware is zero!\n"); + return -EINVAL; + } + hccs_info->chip_num = rsp_data.chip_num; + + return 0; +} + +static int hikp_hccs_get_die_num(uint8_t chip_id, struct hikp_plat_hccs_info *hccs_info) +{ + struct hccs_die_num_rsp_data rsp_data = {0}; + struct hikp_cmd_header req_header = {0}; + struct hccs_die_num_req_para *req_param; + struct hikp_hccs_req req = {0}; + int ret; + + hikp_cmd_init(&req_header, HCCS_MOD, HCCS_GET_DIE_NUM, 0); + req_param = (struct hccs_die_num_req_para *)&req.req_data; + req_param->chip_id = chip_id; + ret = hikp_hccs_query(&req_header, &req, + &rsp_data, sizeof(struct hccs_die_num_rsp_data)); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get die number from firmware, ret = %d!\n", ret); + return ret; + } + + hccs_info->chip_info[chip_id].die_num = rsp_data.die_num; + return 0; +} + +static int hikp_hccs_get_die_info(struct hccs_die_info *die_info, + uint8_t chip_id, uint8_t die_idx) +{ + struct hccs_die_info_rsp_data rsp_data = {0}; + struct hccs_die_info_req_para *req_param; + struct hikp_cmd_header req_header = {0}; + struct hikp_hccs_req req = {0}; + int ret; + + hikp_cmd_init(&req_header, HCCS_MOD, HCCS_GET_DIE_INFO, 0); + req_param = (struct hccs_die_info_req_para *)&req.req_data; + req_param->chip_id = chip_id; + req_param->die_idx = die_idx; + ret = hikp_hccs_query(&req_header, &req, + &rsp_data, sizeof(struct hccs_die_info_rsp_data)); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get die information from firmware, ret = %d!\n", ret); + return ret; + } + + die_info->die_id = rsp_data.die_id; + die_info->port_num = rsp_data.port_num; + return 0; +} + +static int hikp_hccs_get_all_die_info(struct hikp_plat_hccs_info *hccs_info) +{ + uint8_t chip_id, die_idx, die_num; + struct hccs_chip_info *chip_info; + struct hccs_die_info *die_info; + bool has_die = false; + int ret; + + for (chip_id = 0; chip_id < hccs_info->chip_num; chip_id++) { + chip_info = &hccs_info->chip_info[chip_id]; + die_num = chip_info->die_num; + if (die_num == 0) + continue; + + has_die = true; + die_info = (struct hccs_die_info *)calloc(die_num, sizeof(struct hccs_die_info)); + if (die_info == NULL) { + HIKP_ERROR_PRINT("Failed to allocate memory for die information!\n"); + return -ENOMEM; + } + chip_info->die_info = die_info; + for (die_idx = 0; die_idx < die_num; die_idx++, die_info++) { + ret = hikp_hccs_get_die_info(die_info, chip_id, die_idx); + if (ret < 0) { + HIKP_ERROR_PRINT("Failed to get die information for die idx %u!\n", + die_idx); + return ret; + } + } + } + + return has_die ? 0 : -EINVAL; +} + +static int hikp_hccs_get_ports_on_die(uint8_t *port_ids, uint16_t port_num, + uint8_t chip_id, uint8_t die_id) +{ + struct hccs_die_ports_req_para *req_param; + struct hikp_cmd_header req_header = {0}; + struct hikp_hccs_req req = {0}; + int ret; + + hikp_cmd_init(&req_header, HCCS_MOD, HCCS_GET_PORT_IDS_ON_DIE, 0); + req_param = (struct hccs_die_ports_req_para *)&req.req_data; + req_param->chip_id = chip_id; + req_param->die_id = die_id; + ret = hikp_hccs_query(&req_header, &req, + port_ids, sizeof(uint8_t) * port_num); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get port ids from firmware, ret = %d!\n", ret); + return ret; + } + + return 0; +} + +static int hikp_hccs_get_all_port_info(struct hikp_plat_hccs_info *hccs_info) +{ + struct hccs_chip_info *chip_info; + struct hccs_die_info *die_info; + struct hccs_die_info *dies; + uint8_t chip_id, die_idx; + bool has_port = false; + int ret; + + for (chip_id = 0; chip_id < hccs_info->chip_num; chip_id++) { + chip_info = &hccs_info->chip_info[chip_id]; + dies = chip_info->die_info; + has_port = false; + for (die_idx = 0; die_idx < chip_info->die_num; die_idx++) { + die_info = &dies[die_idx]; + if (die_info->port_num == 0) + continue; + + has_port = true; + die_info->port_ids = (uint8_t *)calloc(die_info->port_num, + sizeof(uint8_t)); + if (die_info->port_ids == NULL) + return -ENOMEM; + + ret = hikp_hccs_get_ports_on_die(die_info->port_ids, die_info->port_num, + chip_id, die_info->die_id); + if (ret < 0) { + HIKP_ERROR_PRINT("Failed to get port ids for " + "chip (%u) die idx (%u)!\n", + chip_id, die_idx); + return ret; + } + } + } + + return has_port ? 0 : -EINVAL; +} + +static int hikp_hccs_get_chip_info(struct hikp_plat_hccs_info *hccs_info) +{ + uint8_t chip_id; + int ret; + + ret = hikp_hccs_get_chip_num(hccs_info); + if (ret < 0) { + HIKP_ERROR_PRINT("Failed to get chip num!\n"); + return ret; + } + + hccs_info->chip_info = (struct hccs_chip_info *)calloc(hccs_info->chip_num, + sizeof(struct hccs_chip_info)); + if (hccs_info->chip_info == NULL) { + HIKP_ERROR_PRINT("Failed to allocate memory for chip info!\n"); + return -ENOMEM; + } + + for (chip_id = 0; chip_id < hccs_info->chip_num; chip_id++) { + ret = hikp_hccs_get_die_num(chip_id, hccs_info); + if (ret < 0) { + HIKP_ERROR_PRINT("Failed to get die num!\n"); + return ret; + } + } + + return 0; +} + +static int hikp_plat_hccs_hw_info(struct hikp_plat_hccs_info *hccs_info) +{ + int ret; + + ret = hikp_hccs_get_chip_info(hccs_info); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get chip info, ret = %d!\n", ret); + return ret; + } + + ret = hikp_hccs_get_all_die_info(hccs_info); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get all die info, ret = %d!\n", ret); + return ret; + } + + ret = hikp_hccs_get_all_port_info(hccs_info); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get all port info, ret = %d!\n", ret); + return ret; + } + return 0; +} + +static int hikp_hccs_get_plat_topo(struct hccs_param *param, + union hccs_feature_info *info) +{ + int ret; + + HIKP_SET_USED(param); + HIKP_SET_USED(info); + + ret = hikp_plat_hccs_hw_info(&g_hccs_info); + if (ret < 0) { + HIKP_ERROR_PRINT("Failed to get HCCS hardware info, ret = %d!\n", ret); + return ret; + } + return 0; +} + +static void hikp_plat_hccs_free(struct hikp_plat_hccs_info *hccs_info) +{ + struct hccs_chip_info *chip_info; + struct hccs_die_info *die_info; + uint8_t chip_id, die_idx; + + if (hccs_info->chip_info == NULL) + return; + + for (chip_id = 0; chip_id < hccs_info->chip_num; chip_id++) { + chip_info = &hccs_info->chip_info[chip_id]; + die_info = chip_info->die_info; + if (die_info == NULL) + continue; + + for (die_idx = 0; die_idx < chip_info->die_num; die_idx++) { + if (die_info[die_idx].port_ids == NULL) + continue; + free(die_info[die_idx].port_ids); + die_info[die_idx].port_ids = NULL; + } + free(die_info); + chip_info->die_info = NULL; + } + free(hccs_info->chip_info); + hccs_info->chip_info = NULL; +} + +static bool hikp_hccs_die_id_valid(struct hikp_plat_hccs_info *hccs_info, + struct hccs_param *param, uint8_t *die_idx) +{ + struct hccs_chip_info *chip_info; + struct hccs_die_info *die_info; + uint8_t idx; + + chip_info = &hccs_info->chip_info[param->chip_id]; + die_info = chip_info->die_info; + for (idx = 0; idx < chip_info->die_num; idx++) { + if (param->die_id != die_info[idx].die_id) + continue; + *die_idx = idx; + return true; + } + return false; +} + +static bool hikp_hccs_port_id_valid(struct hikp_plat_hccs_info *hccs_info, + struct hccs_param *param, uint8_t die_idx) +{ + struct hccs_chip_info *chip_info; + struct hccs_die_info *die_info; + uint8_t port_id, *port_ids; + + chip_info = &hccs_info->chip_info[param->chip_id]; + die_info = &chip_info->die_info[die_idx]; + port_ids = die_info->port_ids; + + for (port_id = 0; port_id < die_info->port_num; port_id++) { + if (param->port_id == port_ids[port_id]) + return true; + } + + return false; +} + +static bool hikp_hccs_req_param_check(struct hikp_plat_hccs_info *hccs_info, + struct hccs_param *param) +{ + uint8_t die_idx; + + if (param->chip_id >= hccs_info->chip_num) { + HIKP_ERROR_PRINT("param error: chip id %u exceed chip number %u!\n", + param->chip_id, hccs_info->chip_num); + return false; + } + + if (!hikp_hccs_die_id_valid(hccs_info, param, &die_idx)) { + HIKP_ERROR_PRINT("Param error: die%u not found on chip%u!\n", + param->die_id, param->chip_id); + return false; + } + + if (!hikp_hccs_port_id_valid(hccs_info, param, die_idx)) { + HIKP_ERROR_PRINT("Param error: port id %u not found on chip%u die%u!\n", + param->port_id, param->chip_id, param->die_id); + return false; + } + + return true; +} + +static int hikp_hccs_get_port_attr(struct hccs_param *param, + union hccs_feature_info *info) +{ + struct hccs_port_attr_req_para *req_para; + struct hikp_cmd_header req_header = {0}; + struct hikp_hccs_req req = {0}; + int ret; + + ret = hikp_plat_hccs_hw_info(&g_hccs_info); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get HCCS hardware info for " + "port attributes, ret = %d.\n", ret); + return ret; + } + + if (!hikp_hccs_req_param_check(&g_hccs_info, param)) + return -EINVAL; + + hikp_cmd_init(&req_header, HCCS_MOD, HCCS_GET_PORT_FIXED_ATTR, 0); + req_para = (struct hccs_port_attr_req_para *)&req.req_data; + req_para->chip_id = param->chip_id; + req_para->die_id = param->die_id; + req_para->port_id = param->port_id; + ret = hikp_hccs_query(&req_header, &req, + info, sizeof(union hccs_feature_info)); + if (ret != 0) + return ret; + return 0; +} + +static int hikp_hccs_get_port_dfx_info(struct hccs_param *param, + union hccs_feature_info *info) +{ + struct hikp_hccs_rsp_head rsp_head = {0}; + struct hikp_cmd_header req_header = {0}; + struct hccs_port_dfx_info_vld *dfx_info; + struct hccs_port_dfx_req_para *dfx_req; + struct hikp_hccs_req req = {0}; + int ret; + + ret = hikp_plat_hccs_hw_info(&g_hccs_info); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to get HCCS hardware info for dfx info, ret = %d\n", + ret); + return ret; + } + + if (!hikp_hccs_req_param_check(&g_hccs_info, param)) + return -EINVAL; + + dfx_info = &info->dfx_info; + dfx_req = (struct hccs_port_dfx_req_para *)&req.req_data; + dfx_req->chip_id = param->chip_id; + dfx_req->port_id = param->port_id; + dfx_req->die_id = param->die_id; + hikp_cmd_init(&req_header, HCCS_MOD, HCCS_GET_PORT_DFX_INFO, 0); + ret = hikp_hccs_cmd_send(&req_header, &req, + &dfx_info->info, + sizeof(struct hccs_port_dfx_info), + &rsp_head); + if (ret != 0) + return ret; + + dfx_info->vld_size = rsp_head.cur_blk_size; + + return 0; +} + +static void hikp_hccs_show_topo(union hccs_feature_info *data) +{ + uint8_t chip_id, die_idx, die_num, port_idx, *port_ids; + struct hccs_die_info *die_info; + struct hccs_die_info *dies; + + HIKP_SET_USED(data); + + for (chip_id = 0; chip_id < g_hccs_info.chip_num; chip_id++) { + die_num = g_hccs_info.chip_info[chip_id].die_num; + dies = g_hccs_info.chip_info[chip_id].die_info; + printf("--chip%u\n", chip_id); + if (die_num == 0) + continue; + for (die_idx = 0; die_idx < die_num; die_idx++) { + die_info = &dies[die_idx]; + printf("\t--die%u\n", die_info->die_id); + port_ids = die_info->port_ids; + if (die_info->port_num == 0) + continue; + + for (port_idx = 0; port_idx < die_info->port_num; port_idx++) + printf("\t\t--hccs%u\n", port_ids[port_idx]); + } + } +} + +static void hikp_hccs_show_port_attr(union hccs_feature_info *feature_info) +{ + struct hccs_port_fixed_attr *info = &feature_info->attr; + + printf("%-16s\tHCCS-V%u\n" + "%-16s\tx%u\n" + "%-16s\t%uMbps\n" + "%-16s\t%u\n", + "hccs_type", info->hccs_type, + "lane_mode", info->lane_mode, + "speed", info->speed, + "enabled", info->enabled); +} + +static const char *hikp_hccs_link_fsm_to_str(uint8_t link_fsm) +{ + size_t i; + + for (i = 0; i < sizeof(link_fsm_map) / sizeof(link_fsm_map[0]); i++) { + if (link_fsm_map[i].link_fsm == link_fsm) + return link_fsm_map[i].str; + } + + return "unknown"; +} + +static void hikp_hccs_show_port_dfx_info(union hccs_feature_info *feature_info) +{ + struct hccs_port_dfx_info_vld *info_vld = &feature_info->dfx_info; + struct hccs_port_dfx_info *info = &info_vld->info; + size_t vld_size; + + vld_size = (size_t)info_vld->vld_size; + if (vld_size >= sizeof(info->link_fsm)) { + printf("%-16s\t%s\n", "link_fsm", hikp_hccs_link_fsm_to_str(info->link_fsm)); + vld_size -= sizeof(info->link_fsm); + } + + if (vld_size >= sizeof(info->cur_lane_num)) { + printf("%-16s\t%u\n", "cur_lane_num", info->cur_lane_num); + vld_size -= sizeof(info->cur_lane_num); + } + + if (vld_size >= sizeof(info->lane_mask)) { + printf("%-16s\t0x%x\n", "lane_mask", info->lane_mask); + vld_size -= sizeof(info->lane_mask); + } + + if (vld_size >= sizeof(info->crc_err_cnt)) { + printf("%-16s\t%u\n", "crc_err_cnt", info->crc_err_cnt); + vld_size -= sizeof(info->crc_err_cnt); + } + + if (vld_size >= sizeof(info->retry_cnt)) { + printf("%-16s\t%u\n", "retry_cnt", info->retry_cnt); + vld_size -= sizeof(info->retry_cnt); + } + + if (vld_size >= sizeof(info->phy_reinit_cnt)) { + printf("%-16s\t%u\n", "phy_reinit_cnt", info->phy_reinit_cnt); + vld_size -= sizeof(info->phy_reinit_cnt); + } + + if (vld_size >= sizeof(info->tx_credit)) { + printf("%-16s\t%u\n", "tx_credit", info->tx_credit); + vld_size -= sizeof(info->tx_credit); + } +} + +static void hikp_hccs_cmd_execute(struct major_cmd_ctrl *self) +{ + const struct hikp_hccs_feature_cmd *hccs_cmd; + union hccs_feature_info info = {0}; + int ret; + + if (g_hccs_param.feature_idx == -1) { + hikp_hccs_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-g/--get param error!"); + self->err_no = -EINVAL; + return; + } + + hccs_cmd = &g_hccs_feature_cmd[g_hccs_param.feature_idx]; + if (g_hccs_param.param_mask != hccs_cmd->param_needed) { + hikp_hccs_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "Parameter mismatched!"); + self->err_no = -EINVAL; + return; + } + + ret = hikp_hccs_get_chip_num(&g_hccs_info); + if (ret < 0) { + self->err_no = ret; + return; + } + + if (g_hccs_info.chip_num == 1) { + snprintf(self->err_str, sizeof(self->err_str), + "The command is just supported on multi-sockets!\n"); + self->err_no = -EINVAL; + return; + } + + ret = hccs_cmd->query(&g_hccs_param, &info); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Failed to query %s, ret = %d.", + hccs_cmd->feature_name, ret); + self->err_no = ret; + hikp_plat_hccs_free(&g_hccs_info); + return; + } + + printf("############## HCCS: %s info ############\n", hccs_cmd->feature_name); + hccs_cmd->show(&info); + printf("#################### END #######################\n"); + + hikp_plat_hccs_free(&g_hccs_info); +} + +static int hikp_hccs_cmd_feature_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t feat_size = HIKP_ARRAY_SIZE(g_hccs_feature_cmd); + size_t i; + + for (i = 0; i < feat_size; i++) { + if (strcmp(argv, g_hccs_feature_cmd[i].feature_name) == 0) { + g_hccs_param.feature_idx = i; + return 0; + } + } + + hikp_hccs_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-g/--get param error!!!"); + self->err_no = -EINVAL; + + return self->err_no; +} + +static int hikp_hccs_cmd_parse_chip(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t chip_id; + + self->err_no = string_toui(argv, &chip_id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "Failed to parse -c/--chip_id parameter."); + return self->err_no; + } + if (chip_id > UINT8_MAX) { + snprintf(self->err_str, sizeof(self->err_str), + "chip id should not be greater than %u.", UINT8_MAX); + self->err_no = -EINVAL; + return self->err_no; + } + + g_hccs_param.param_mask |= HCCS_ENABLE_CHIP_ID; + g_hccs_param.chip_id = (uint8_t)chip_id; + + return 0; +} + +static int hikp_hccs_cmd_parse_die(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t die_id; + + self->err_no = string_toui(argv, &die_id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "Failed to parse -d/--die_id parameter."); + return self->err_no; + } + + if (die_id > UINT8_MAX) { + snprintf(self->err_str, sizeof(self->err_str), + "die id should not be greater than %u.", UINT8_MAX); + self->err_no = -EINVAL; + return self->err_no; + } + + g_hccs_param.param_mask |= HCCS_ENABLE_DIE_ID; + g_hccs_param.die_id = (uint8_t)die_id; + + return 0; +} + +static int hikp_hccs_cmd_parse_port(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t port_id; + + self->err_no = string_toui(argv, &port_id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "Failed to parse -p/--port_id parameter."); + return self->err_no; + } + + if (port_id > UINT8_MAX) { + snprintf(self->err_str, sizeof(self->err_str), + "port id should not be greater %u.", UINT8_MAX); + self->err_no = -EINVAL; + return self->err_no; + } + + g_hccs_param.param_mask |= HCCS_ENABLE_PORT_ID; + g_hccs_param.port_id = (uint8_t)port_id; + return 0; +} + +static void hikp_hccs_cmd_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_hccs_param.feature_idx = -1; + + major_cmd->option_count = 0; + major_cmd->execute = hikp_hccs_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_hccs_cmd_help); + cmd_option_register("-g", "--get", true, hikp_hccs_cmd_feature_select); + cmd_option_register("-c", "--chip_id", true, hikp_hccs_cmd_parse_chip); + cmd_option_register("-d", "--die_id", true, hikp_hccs_cmd_parse_die); + cmd_option_register("-p", "--port_id", true, hikp_hccs_cmd_parse_port); +} + +HIKP_CMD_DECLARE("hccs", "dump HCCS information.", hikp_hccs_cmd_init); diff --git a/hccs/hikp_hccs.h b/hccs/hikp_hccs.h new file mode 100644 index 0000000..8ccc01a --- /dev/null +++ b/hccs/hikp_hccs.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2024-2025 Hisilicon Technologies Co., Ltd. + * Hikptool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * + * See the Mulan PSL v2 for more details. + */ + +#ifndef HIKP_HCCS_H +#define HIKP_HCCS_H + +#include + +enum hikp_hccs_cmd_type { + HCCS_GET_CHIP_NUM = 0, + HCCS_GET_DIE_NUM, + HCCS_GET_DIE_INFO, + HCCS_GET_PORT_IDS_ON_DIE, + HCCS_GET_PORT_FIXED_ATTR, + HCCS_GET_PORT_DFX_INFO, +}; + +struct hccs_die_info { + uint8_t die_id; + uint16_t port_num; + uint8_t *port_ids; +}; + +struct hccs_chip_info { + uint8_t chip_id; + uint8_t die_num; + struct hccs_die_info *die_info; +}; + +struct hccs_port_fixed_attr { + uint8_t hccs_type; /* HCCS_V1, HCCS_V2 and etc. */ + uint8_t lane_mode; + uint16_t speed; /* Unit Mbps. */ + uint8_t enabled; /* Indicate if port is enabled. */ + uint8_t rsv[3]; +}; + +struct hccs_port_dfx_info { + uint8_t link_fsm; + uint8_t cur_lane_num; + uint16_t lane_mask; + uint32_t crc_err_cnt; + uint32_t retry_cnt; + uint32_t phy_reinit_cnt; + uint32_t tx_credit; + uint32_t rsv1[54]; +}; + +struct hccs_port_dfx_info_vld { + struct hccs_port_dfx_info info; + uint8_t vld_size; /* Indicate the valid bytes firmware reported. */ +}; + +union hccs_feature_info { + struct hccs_port_fixed_attr attr; + struct hccs_port_dfx_info_vld dfx_info; +}; + +struct hccs_chip_num_rsp_data { + uint8_t chip_num; +}; + +struct hccs_die_num_req_para { + uint8_t chip_id; +}; + +struct hccs_die_num_rsp_data { + uint8_t die_num; +}; + +struct hccs_die_info_req_para { + uint8_t chip_id; + uint8_t die_idx; +}; + +struct hccs_die_info_rsp_data { + uint8_t die_id; + uint8_t rsv; + uint16_t port_num; +}; + +struct hccs_die_ports_req_para { + uint8_t chip_id; + uint8_t die_id; +}; + +struct hccs_port_attr_req_para { + uint8_t chip_id; + uint8_t die_id; + uint8_t port_id; +}; + +struct hccs_port_dfx_req_para { + uint8_t chip_id; + uint8_t die_id; + uint8_t port_id; +}; + +struct hikp_hccs_rsp_head { + uint16_t total_blk_num; + uint8_t cur_blk_size; /* real data size, not contain header size. */ + uint8_t rsv; +}; + +#define HCCS_MAX_RSP_DATA 59 +struct hikp_hccs_rsp { + struct hikp_hccs_rsp_head rsp_head; /* 4 Byte */ + uint32_t rsp_data[HCCS_MAX_RSP_DATA]; +}; + +struct hikp_hccs_req_head { + uint16_t blk_id; + uint16_t rsv; +}; + +#define HCCS_MAX_REQ_DATA 31 +struct hikp_hccs_req { + struct hikp_hccs_req_head head; /* 4 Byte */ + uint32_t req_data[HCCS_MAX_REQ_DATA]; +}; + +#define HCCS_ENABLE_CHIP_ID HI_BIT(0) +#define HCCS_ENABLE_DIE_ID HI_BIT(1) +#define HCCS_ENABLE_PORT_ID HI_BIT(2) +#define HCCS_PORT_INFO_MASK (HCCS_ENABLE_CHIP_ID | HCCS_ENABLE_DIE_ID | \ + HCCS_ENABLE_PORT_ID) + +struct hccs_param { + int feature_idx; + uint8_t chip_id; + uint8_t die_id; + uint32_t port_id; + /* mask for param passed by user, see HCCS_ENABLE_XXX. */ + uint16_t param_mask; +}; + +struct hikp_plat_hccs_info { + uint8_t chip_num; + struct hccs_chip_info *chip_info; +}; + +#define HIKP_HCCS_FEATURE_NAME_LEN 20 +struct hikp_hccs_feature_cmd { + const char feature_name[HIKP_HCCS_FEATURE_NAME_LEN]; + uint32_t cmd_code; + int (*query)(struct hccs_param *param, union hccs_feature_info *info); + void (*show)(union hccs_feature_info *data); + uint16_t param_needed; +}; + +#endif /* HIKP_HCCS_H */ diff --git a/libhikptdev/include/hikptdev_plug.h b/libhikptdev/include/hikptdev_plug.h index 2123935..d45a654 100644 --- a/libhikptdev/include/hikptdev_plug.h +++ b/libhikptdev/include/hikptdev_plug.h @@ -44,6 +44,7 @@ enum cmd_module_type { DPDK_MOD = 9, CXL_MOD = 10, UB_MOD = 11, + HCCS_MOD = 16 }; void hikp_unlock(void); -- 2.45.0.windows.1