From 49c3788dda5d1525398a2a9da74dfa316529b8cf Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 14:53:25 +0800 Subject: [PATCH 01/14] add rciep device channel layer for hikptool hikptool is a userspace tool for Linux providing enhanced capabilities of inband information collection and problem location on Kunpeng chips. hikptool userspace layer can obtained data through the rciep device Signed-off-by: cjx_2021 Signed-off-by: hesiyuan (cherry picked from commit 274a14cc8153ab4b8e522e263e39300c74f06b6a) --- libhikptdev/CMakeLists.txt | 12 + libhikptdev/include/hikptdev_plug.h | 58 +++ libhikptdev/src/rciep/CMakeLists.txt | 21 + libhikptdev/src/rciep/hikpt_rciep.c | 583 +++++++++++++++++++++++++++ libhikptdev/src/rciep/hikpt_rciep.h | 104 +++++ 5 files changed, 778 insertions(+) create mode 100644 libhikptdev/CMakeLists.txt create mode 100644 libhikptdev/include/hikptdev_plug.h create mode 100644 libhikptdev/src/rciep/CMakeLists.txt create mode 100644 libhikptdev/src/rciep/hikpt_rciep.c create mode 100644 libhikptdev/src/rciep/hikpt_rciep.h diff --git a/libhikptdev/CMakeLists.txt b/libhikptdev/CMakeLists.txt new file mode 100644 index 0000000..3b17f50 --- /dev/null +++ b/libhikptdev/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2022 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. + +add_subdirectory(src/rciep) \ No newline at end of file diff --git a/libhikptdev/include/hikptdev_plug.h b/libhikptdev/include/hikptdev_plug.h new file mode 100644 index 0000000..42bea6b --- /dev/null +++ b/libhikptdev/include/hikptdev_plug.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 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 __HIKPTDEV_PLUG_H +#define __HIKPTDEV_PLUG_H + +#include + +struct hikp_cmd_header { + uint32_t version; + uint32_t mod_code; + uint32_t cmd_code; + uint32_t sub_cmd_code; +}; + +struct hikp_cmd_ret { + uint32_t status; + uint32_t version; + uint32_t rsp_data_num; + uint32_t rsp_data[0]; +}; + +/* Module code */ +enum cmd_module_type { + PCIE_MOD = 0, + SERDES_MOD = 1, + NIC_MOD = 2, + SOCIP_MOD = 3, + ROCE_MOD = 4, + ROH_MOD = 5, + SAS_MOD = 6, + SATA_MOD = 7, + MAC_MOD = 8, + DPDK_MOD = 9, + CXL_MOD = 10, +}; + +void hikp_unlock(void); +void hikp_cmd_init(struct hikp_cmd_header *req_header, uint32_t mod_code, uint32_t cmd_code, + uint32_t sub_cmd_code); +struct hikp_cmd_ret *hikp_cmd_alloc(struct hikp_cmd_header *req_header, + const void *req_data, uint32_t req_size); +int hikp_dev_init(void); +void hikp_dev_uninit(void); +int hikp_rsp_normal_check(const struct hikp_cmd_ret *cmd_ret); +int hikp_rsp_normal_check_with_version(const struct hikp_cmd_ret *cmd_ret, uint32_t version); + +#endif diff --git a/libhikptdev/src/rciep/CMakeLists.txt b/libhikptdev/src/rciep/CMakeLists.txt new file mode 100644 index 0000000..b96d621 --- /dev/null +++ b/libhikptdev/src/rciep/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (c) 2022 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. + +cmake_minimum_required(VERSION 3.0.0) + +set(KPTDEV_SO_NAME hikptdev) + +add_library(KPTDEV_SO SHARED hikpt_rciep.c) + +target_include_directories(KPTDEV_SO PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include) + +set_target_properties(KPTDEV_SO PROPERTIES OUTPUT_NAME ${KPTDEV_SO_NAME} SOVERSION 1 VERSION 1.0.0) +install(TARGETS KPTDEV_SO LIBRARY DESTINATION lib OPTIONAL) \ No newline at end of file diff --git a/libhikptdev/src/rciep/hikpt_rciep.c b/libhikptdev/src/rciep/hikpt_rciep.c new file mode 100644 index 0000000..9b7a82a --- /dev/null +++ b/libhikptdev/src/rciep/hikpt_rciep.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2022 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 +#include +#include +#include +#include +#include "hikpt_rciep.h" + +#define MAX_BUS_PCI_DIR_LEN 300 +#define MAX_PCI_ID_LEN 6 +#define HIKP_BUS_PCI_DEV_DIR "/sys/bus/pci/devices/" +#define HIKP_PCI_REVISION_DIR "/revision" + +static int g_iep_fd; +static uint8_t g_unmap_flag; +static volatile union hikp_space_req *g_hikp_req; +static volatile union hikp_space_rsp *g_hikp_rsp; + +static int hikp_memcpy_io(void *dst, size_t dst_size, void const *src, size_t src_size) +{ + uint32_t i; + + if (dst_size < src_size) + return -EINVAL; + + for (i = 0; i < src_size / sizeof(uint32_t); i++) + ((uint32_t *)dst)[i] = ((uint32_t *)src)[i]; + + return 0; +} + +static void hikp_memclr_io(void) +{ + uint32_t i; + + for (i = 0; i < HIKP_REQ_DATA_MAX; i++) + g_hikp_req->field.data[i] = 0; +} + +static int hikp_try_lock(void) +{ + int count; + pid_t pid; + + pid = getpid(); + count = MAX_LOCK_COUNT; + /* Try to lock */ + do { + if (flock(g_iep_fd, LOCK_EX | LOCK_NB) == 0) { + g_hikp_req->field.sw_db.db_flag = 1; + g_hikp_req->field.pid_record = (uint32_t)pid; + g_hikp_req->field.sw_db.db_mask = 0; + return 0; + } + count--; + usleep(LOCK_CHECK_GAP_US); + } while (count); + printf("dev lock by other process:%u.\n", g_hikp_req->field.pid_record); + + return -EBUSY; +} + +void hikp_unlock(void) +{ + if (g_unmap_flag == 0 && g_hikp_req && g_hikp_req->field.sw_db.db_flag == 1) { + g_hikp_req->field.sw_db.db_flag = 0; + g_hikp_req->field.sw_db.db_mask = 1; + } +} + +static void hikp_init_cpl_status(void) +{ + g_hikp_req->field.cpl_status = 0; +} + +static uint32_t hikp_wait_for_cpl_status(void) +{ + int count = WAIT_CPL_MAX_MS; + uint32_t status; + + do { + status = g_hikp_req->field.cpl_status; + if (status != HIKP_INIT_STAT) + return status; + count--; + usleep(CPL_CHECK_GAP_US); + } while (count); + + return HIKP_APP_WAIT_TIMEOUT; +} + +static void req_issue(void) +{ + hikp_init_cpl_status(); + g_hikp_req->field.sw_db.db_trig = 1; +} + +static void hikp_cmd_header_set(struct hikp_cmd_header *req_header) +{ + if (req_header == NULL) + return; + + g_hikp_req->field.req_header.version = req_header->version; + g_hikp_req->field.req_header.mod_code = req_header->mod_code; + g_hikp_req->field.req_header.cmd_code = req_header->cmd_code; + g_hikp_req->field.req_header.sub_cmd_code = req_header->sub_cmd_code; +} + +void hikp_cmd_init(struct hikp_cmd_header *req_header, uint32_t mod_code, + uint32_t cmd_code, uint32_t sub_cmd_code) +{ + if (req_header == NULL) { + printf("Command init header NULL.\n"); + return; + } + + memset(req_header, 0, sizeof(struct hikp_cmd_header)); + + req_header->mod_code = mod_code; + req_header->cmd_code = cmd_code; + req_header->sub_cmd_code = sub_cmd_code; +} + +static int hikp_rep_init(void const *req_data, uint32_t req_size, + uint32_t **align_req_data, uint32_t *align_data_num) +{ + size_t data_num; + + if (req_data == NULL) { + printf("The request data is NULL.\n"); + return -EINVAL; + } + data_num = (req_size + (sizeof(uint32_t) - 1)) / sizeof(uint32_t); + if (data_num > HIKP_REQ_DATA_MAX) { + printf("request data num(%u) exceeds max size(%u).\n", data_num, HIKP_REQ_DATA_MAX); + return -EINVAL; + } + if (data_num != 0) { + *align_req_data = (uint32_t *)calloc(data_num, sizeof(uint32_t)); + if (*align_req_data == NULL) { + printf("request memory malloc failed.\n"); + return -ENOMEM; + } + memcpy(*align_req_data, req_data, req_size); + } + g_hikp_req->field.req_para_num = data_num; + *align_data_num = data_num; + + return 0; +} + +static int hikp_req_first_round(uint32_t *req_data, uint32_t rep_num, uint32_t *cpl_status) +{ + size_t src_size, dst_size; + int ret; + + if (req_data == NULL) + return 0; + + src_size = rep_num * sizeof(uint32_t); + dst_size = sizeof(g_hikp_req->field.data); + hikp_memclr_io(); + ret = hikp_memcpy_io((uint32_t *)(g_hikp_req->field.data), dst_size, req_data, src_size); + if (ret != 0) { + printf("size error, dst_size:%u, src_size:%u.\n", dst_size, src_size); + return ret; + } + g_hikp_req->field.exe_round = 0; + req_issue(); /* On the first round, an interrupt is triggered. */ + *cpl_status = hikp_wait_for_cpl_status(); + if (*cpl_status != HIKP_CPL_BY_TF && *cpl_status != HIKP_CPL_BY_IMU) { + printf("First round failed. Error code:%u.\n", *cpl_status); + return RCIEP_FAIL; + } + + return 0; +} + +static int hikp_multi_round_interact(struct hikp_cmd_ret **cmd_ret, uint32_t status) +{ + struct hikp_cmd_ret *p_cmd_ret; + uint32_t src_size, dst_size; + uint32_t cycle, i; + uint32_t rsp_num; + uint32_t cpl_status; + + rsp_num = g_hikp_rsp->field.rsp_para_num; + if (rsp_num > HIKP_RSP_ALL_DATA_MAX) { + printf("Response data num[%u] out of range[%d].\n", rsp_num, HIKP_RSP_ALL_DATA_MAX); + return -EINVAL; + } + + p_cmd_ret = (struct hikp_cmd_ret *)malloc(sizeof(struct hikp_cmd_ret) + + rsp_num * sizeof(uint32_t)); + if (p_cmd_ret == NULL) { + printf("response memory malloc fail.\n"); + return -ENOMEM; + } + p_cmd_ret->version = g_hikp_rsp->field.version; + p_cmd_ret->rsp_data_num = rsp_num; + + cycle = (rsp_num + (HIKP_RSP_DATA_MAX - 1)) / HIKP_RSP_DATA_MAX; + for (i = 0; i < cycle; i++) { + if (i != 0) { + g_hikp_req->field.exe_round = i; + if (status == HIKP_CPL_BY_TF) + req_issue(); /* For next rounds, interrupt is triggered again. */ + else + hikp_init_cpl_status(); + + cpl_status = hikp_wait_for_cpl_status(); + if (cpl_status != HIKP_CPL_BY_TF && cpl_status != HIKP_CPL_BY_IMU) { + printf("multi round failed, Error code:%u.\n", cpl_status); + p_cmd_ret->status = RCIEP_FAIL; + *cmd_ret = p_cmd_ret; + return RCIEP_FAIL; + } + } + src_size = (i == cycle - 1) ? + (rsp_num - (i * HIKP_RSP_DATA_MAX)) * sizeof(uint32_t) : + HIKP_RSP_DATA_MAX * sizeof(uint32_t); + dst_size = src_size; + (void)hikp_memcpy_io(&(p_cmd_ret->rsp_data)[i * HIKP_RSP_DATA_MAX], + dst_size, (uint32_t *)(g_hikp_rsp->field.data), src_size); + } + p_cmd_ret->status = 0; + *cmd_ret = p_cmd_ret; + + return 0; +} + +/* + * Before using the returned struct hikp_cmd_ret structure, check the following: + * 1. Whether NULL is returned + * 2. Check whether the status field of struct hikp_cmd_ret meets the expectation + * 3. Use rsp_data according to rsp_data_num + */ +struct hikp_cmd_ret *hikp_cmd_alloc(struct hikp_cmd_header *req_header, + const void *req_data, uint32_t req_size) +{ + struct hikp_cmd_ret *cmd_ret = NULL; + uint32_t *p_req_data = NULL; + uint32_t rep_num, rsp_num; + uint32_t cpl_status = HIKP_INIT_STAT; + int ret; + + ret = hikp_rep_init(req_data, req_size, &p_req_data, &rep_num); + if (ret) + return NULL; + + hikp_cmd_header_set(req_header); + + ret = hikp_req_first_round(p_req_data, rep_num, &cpl_status); + if (ret) + goto free_req_data; + + ret = hikp_multi_round_interact(&cmd_ret, cpl_status); + if (ret) + goto free_req_data; + +free_req_data: + free(p_req_data); + + return cmd_ret; +} + +int hikp_rsp_normal_check(const struct hikp_cmd_ret *cmd_ret) +{ + if (cmd_ret == NULL) + return -ENOSPC; + + if (cmd_ret->status != 0) + return -EINVAL; + + return 0; +} + +int hikp_rsp_normal_check_with_version(const struct hikp_cmd_ret *cmd_ret, uint32_t version) +{ + int ret; + + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) + return ret; + + if (cmd_ret->version != version) + return -EINVAL; + + return 0; +} + +static int hikp_read_pci_info(const char *file_path, uint32_t len, char *content) +{ + char path[PATH_MAX + 1] = { 0 }; + int ret; + int fd; + + if (file_path == NULL || content == NULL) + return -EINVAL; + + if (len > MAX_PCI_ID_LEN) + return -EINVAL; + + if (strlen(file_path) > PATH_MAX || realpath(file_path, path) == NULL) + return -ENOENT; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -EPERM; + + ret = pread(fd, content, len, 0); + if (ret < 0) { + close(fd); + return -EIO; + } + content[len] = '\0'; // The invoker ensures that the bounds are not crossed. + close(fd); + + return 0; +} + +static int hikp_iep_check_item(const char *src_str, uint32_t len, const char *target_str) +{ + char tmp_str[MAX_PCI_ID_LEN + 1] = { 0 }; + int ret; + + ret = hikp_read_pci_info(src_str, len, tmp_str); + if (ret != 0) + return ret; + + if (strcmp(tmp_str, target_str) != 0) + return -ENXIO; + + return 0; +} + +static int hikp_iep_check(const char *tmp_vendor_dir, + const char *tmp_device_dir, const char *revision_dir) +{ + int ret; + + ret = hikp_iep_check_item(tmp_device_dir, MAX_PCI_ID_LEN, HIKP_IEP_DEV_ID); + if (ret != 0) + return ret; + + ret = hikp_iep_check_item(tmp_vendor_dir, MAX_PCI_ID_LEN, HIKP_IEP_VENDOR_ID); + if (ret != 0) + return ret; + + ret = hikp_iep_check_item(revision_dir, MAX_PCI_REVISION_LEN, HIKP_IEP_REVISION); + if (ret != 0) + printf("Revision id not match %s.\n", HIKP_IEP_REVISION); + + return 0; +} + +static void hikp_snprintf_rst_record(int err_ret, int *flag) +{ + if (err_ret <= 0 || *flag != 0) + *flag = RCIEP_FAIL; +} + +static char *hikp_dir_alloc(uint32_t sub_dir, const struct dirent *entry, int *flag) +{ + char *ret_dir = NULL; + int err_ret = 0; + + ret_dir = (char *)calloc(MAX_BUS_PCI_DIR_LEN, sizeof(char)); + if (ret_dir == NULL) { + printf("malloc dir memory 0x%x failed.\n", MAX_BUS_PCI_DIR_LEN); + return NULL; + } + if (sub_dir == HIKP_RESOURCE_DIR) { + err_ret = snprintf(ret_dir, MAX_BUS_PCI_DIR_LEN, "%s%s%s", + HIKP_BUS_PCI_DEV_DIR, entry->d_name, HIKP_PCI_RESOURCE); + hikp_snprintf_rst_record(err_ret, flag); + } else { + err_ret = snprintf(ret_dir, MAX_BUS_PCI_DIR_LEN, "%s%s%s", + HIKP_BUS_PCI_DEV_DIR, entry->d_name, HIKP_PCI_CONFIG); + hikp_snprintf_rst_record(err_ret, flag); + } + if (*flag != 0) { + free(ret_dir); + return NULL; + } + + return ret_dir; +} + +static char *hikp_get_iep_dir(uint32_t sub_dir) +{ + DIR *dir; + struct dirent *entry; + char vendor_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + char device_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + char revision_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + char *ret_dir = NULL; + int flag = 0; + int err_ret = 0; + int ret; + + dir = opendir(HIKP_BUS_PCI_DEV_DIR); + if (!dir) + return NULL; + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + + err_ret = snprintf(vendor_dir, sizeof(vendor_dir), "%s%s%s", + HIKP_BUS_PCI_DEV_DIR, entry->d_name, HIKP_PCI_VENDOR_DIR); + hikp_snprintf_rst_record(err_ret, &flag); + err_ret = snprintf(device_dir, sizeof(device_dir), "%s%s%s", + HIKP_BUS_PCI_DEV_DIR, entry->d_name, HIKP_PCI_DEV_DIR); + hikp_snprintf_rst_record(err_ret, &flag); + err_ret = snprintf(revision_dir, sizeof(revision_dir), "%s%s%s", + HIKP_BUS_PCI_DEV_DIR, entry->d_name, HIKP_PCI_REVISION_DIR); + hikp_snprintf_rst_record(err_ret, &flag); + ret = hikp_iep_check((const char *)vendor_dir, (const char *)device_dir, + (const char *)revision_dir); + if (ret != 0) + continue; + + ret_dir = hikp_dir_alloc(sub_dir, entry, &flag); + goto out_close_dir; + } + printf("Cannot find Device %s:%s.\n", HIKP_IEP_VENDOR_ID, HIKP_IEP_DEV_ID); +out_close_dir: + closedir(dir); + if (flag != 0) { + printf("Get iep dir snprintf failed, flag = %d.\n", flag); + free(ret_dir); + return NULL; + } + + return ret_dir; +} + +static int mem_space_enable(int enable) +{ + int fd; + int ret; + unsigned char val; + char *iep; + char path[PATH_MAX + 1] = { 0 }; + + iep = hikp_get_iep_dir(HIKP_CONFIG_DIR); + if (iep == NULL) + return -ENOENT; + + if (strlen(iep) > PATH_MAX || realpath(iep, path) == NULL) { + ret = -ENOENT; + goto out_free_iep; + } + fd = open(path, O_RDWR); + if (fd < 0) { + printf("Cannot open %s.\n", iep); + ret = -errno; + goto out_free_iep; + } + + ret = pread(fd, &val, 1, PCI_COMMAND_REG); + if (ret != 1) { + printf("MSE enable pread failed.\n"); + ret = -errno; + goto out_close_fd; + } + + if (enable) + (val) |= (1u << 1); /* set up bit1 for memory space enable */ + else + (val) &= (~(1u << 1)); /* clear bit1 for memory space disable */ + + ret = pwrite(fd, &val, 1, PCI_COMMAND_REG); + if (ret != 1) { + printf("MSE enable pwrite failed.\n"); + ret = -errno; + goto out_close_fd; + } + ret = 0; + +out_close_fd: + close(fd); + fd = -1; +out_free_iep: + free(iep); + + return ret; +} + +static void hikp_munmap(void) +{ + g_unmap_flag = 1; + munmap((void *)g_hikp_req, sizeof(union hikp_space_req)); + g_hikp_req = NULL; + g_hikp_rsp = NULL; +} + +int hikp_dev_init(void) +{ + size_t i, len; + int ret = 0; + char *iep; + char path[PATH_MAX + 1] = { 0 }; + + iep = hikp_get_iep_dir(HIKP_RESOURCE_DIR); + if (iep == NULL) + return -ENOENT; + + if (strlen(iep) > PATH_MAX || realpath(iep, path) == NULL) { + ret = -ENOENT; + goto out_free_iep; + } + g_iep_fd = open(path, O_RDWR | O_SYNC); + if (g_iep_fd < 0) { + printf("failed to open %s.\n", iep); + ret = -errno; + goto out_free_iep; + } + + g_hikp_req = (union hikp_space_req *)mmap(0, sizeof(union hikp_space_req), + PROT_READ | PROT_WRITE, MAP_SHARED, g_iep_fd, 0); + if (!g_hikp_req) { + printf("failed to mmap %s.\n", iep); + ret = -errno; + goto out_close_fd; + } + g_hikp_rsp = (union hikp_space_rsp *)(void *)g_hikp_req; + + ret = mem_space_enable(1); /* 1: enable mem space */ + if (ret) { + printf("failed to enable mem space.\n"); + goto out_unmap; + } + + ret = hikp_try_lock(); + if (ret) { + printf("timed out waitting for lock.\n"); + goto out_unmap; + } + + len = (sizeof(union hikp_space_req) - sizeof(struct iep_doorbell)) / sizeof(uint32_t); + for (i = 0; i < len; i++) + g_hikp_req->dw[i] = 0; + + close(g_iep_fd); + g_iep_fd = -1; + free(iep); + return ret; + +out_unmap: + hikp_munmap(); +out_close_fd: + close(g_iep_fd); + g_iep_fd = -1; +out_free_iep: + free(iep); + return ret; +} + +void hikp_dev_uninit(void) +{ + hikp_unlock(); + hikp_munmap(); +} diff --git a/libhikptdev/src/rciep/hikpt_rciep.h b/libhikptdev/src/rciep/hikpt_rciep.h new file mode 100644 index 0000000..093724a --- /dev/null +++ b/libhikptdev/src/rciep/hikpt_rciep.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022 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 __KPT_RCIEP_H__ +#define __KPT_RCIEP_H__ + +#include +#include "hikptdev_plug.h" + +#define MAX_PCI_REVISION_LEN 4 + +#define HIKP_PCI_DEV_DIR "/device" +#define HIKP_PCI_VENDOR_DIR "/vendor" + +#define HIKP_IEP_DEV_ID "0xa12f" +#define HIKP_IEP_VENDOR_ID "0x19e5" +#define HIKP_IEP_REVISION "0x30" +#define HIKP_PCI_RESOURCE "/resource0" +#define HIKP_PCI_CONFIG "/config" + +#define RCIEP_FAIL (-1) + +#define PCI_COMMAND_REG 0x4 + +#define HIKP_REQ_DATA_MAX 32 +#define HIKP_RSP_DATA_MAX 60 + +#define HIKP_RSP_CYCLE_MAX 10 +#define HIKP_RSP_ALL_DATA_MAX (HIKP_RSP_DATA_MAX * HIKP_RSP_CYCLE_MAX) +#define MAX_LOCK_COUNT 5 +#define LOCK_CHECK_GAP_US 1000 +#define CPL_CHECK_GAP_US 1000 +#define WAIT_CPL_MAX_MS 5000 + +enum { + HIKP_RESOURCE_DIR, + HIKP_CONFIG_DIR, +}; + +enum rciep_cpl_status { + HIKP_INIT_STAT = 0, /* Initial state */ + HIKP_CPL_BY_TF = 1, /* TF successfully executed */ + HIKP_CPL_BY_IMU = 2, /* IMU successfully executed. */ + HIKP_INV_REQ = 3, /* Invalid request (command not found) */ + HIKP_INV_REQ_PARA = 4, /* Invalid request parameter */ + HIKP_REQ_PARA_LACK = 5, /* Lack of request parameters */ + HIKP_EXE_FAILED = 6, /* Execution failed */ + HIKP_APP_WAIT_TIMEOUT = 7, /* APP wait Firmware timeout */ + HIKP_IMU_WAIT_IMP_TIMEOUT = 8, /* IMU wait IMP timeout */ + HIKP_IMU_WAIT_APP_TIMEOUT = 9, /* IMU wait APP timeout */ +}; + +#pragma pack(1) + +struct iep_doorbell { + uint32_t db_trig; /* Doorbell interrupt generation register, WO */ + uint32_t db_clr; /* Doorbell interrupt clear register, WC */ + uint32_t db_mask; /* Doorbell interrupt mask register, WR */ + uint32_t db_sta; /* Doorbell interrupt status register, RO */ + uint32_t db_flag; /* Doorbell flag register, WR */ +}; + +union hikp_space_rsp { + struct { + uint32_t version; /* 000h */ + uint32_t rsp_para_num; /* 004h */ + uint32_t data[HIKP_RSP_DATA_MAX]; /* 008h */ + uint32_t cpl_status; /* 0F8h */ + uint32_t pid_record; /* 0FCh */ + struct iep_doorbell sw_db; /* 100h. Fixed and unmodifiable */ + } field; + + uint32_t dw[69]; +}; + +union hikp_space_req { + struct { + uint32_t rsv0[4]; /* 000h */ + struct hikp_cmd_header req_header; /* 010h */ + uint32_t req_para_num; /* 020h */ + uint32_t exe_round; /* 024h */ + uint32_t data[HIKP_REQ_DATA_MAX]; /* 028h */ + uint32_t checksum; /* 0A8h */ + uint32_t rsv1[19]; /* 0ACh */ + uint32_t pid_record; /* 0F8h */ + uint32_t cpl_status; /* 0FCh */ + struct iep_doorbell sw_db; /* 100h. Fixed and unmodifiable */ + } field; + + uint32_t dw[69]; +}; +#pragma pack() + +#endif -- Gitee From 0f94a40ad15262bdaee511b32fcf1d23455b25ec Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 14:57:25 +0800 Subject: [PATCH 02/14] add tool framework to support command process support command initialization, registration, parsing, show help information, and operation log recording Signed-off-by: cjx_2021 (cherry picked from commit 0329c0e3b42d440eb46faea2901c1d28d6f61d1d) --- CMakeLists.txt | 37 ++++ hikp_init_main.c | 164 ++++++++++++++++ hikp_register.ld | 229 +++++++++++++++++++++++ ossl/ossl_user_linux.c | 104 +++++++++++ ossl/ossl_user_linux.h | 72 +++++++ tool_lib/op_logs.c | 416 +++++++++++++++++++++++++++++++++++++++++ tool_lib/op_logs.h | 55 ++++++ tool_lib/tool_cmd.c | 216 +++++++++++++++++++++ tool_lib/tool_cmd.h | 82 ++++++++ tool_lib/tool_lib.c | 351 ++++++++++++++++++++++++++++++++++ tool_lib/tool_lib.h | 108 +++++++++++ 11 files changed, 1834 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 hikp_init_main.c create mode 100644 hikp_register.ld create mode 100644 ossl/ossl_user_linux.c create mode 100644 ossl/ossl_user_linux.h create mode 100644 tool_lib/op_logs.c create mode 100644 tool_lib/op_logs.h create mode 100644 tool_lib/tool_cmd.c create mode 100644 tool_lib/tool_cmd.h create mode 100644 tool_lib/tool_lib.c create mode 100644 tool_lib/tool_lib.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..61120f2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) 2022 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. + +project(hikptool C) + +macro(get_header_dir_recurse HEADER_DIR_LIST) + file(GLOB_RECURSE HEADER_LIST *.h) + set(DIR_LIST "") + foreach(HEADER ${HEADER_LIST}) + get_filename_component(DIR_PATH ${HEADER} PATH) + set(DIR_LIST ${DIR_LIST} ${DIR_PATH}) + endforeach() + list(REMOVE_DUPLICATES DIR_LIST) + set(${HEADER_DIR_LIST} ${DIR_LIST}) +endmacro() + +file(GLOB_RECURSE HIKPTOOL_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/hikp_init_main.c + ) +add_subdirectory(libhikptdev) +add_executable(hikptool ${HIKPTOOL_SRC}) +get_header_dir_recurse(HIKPTOOL_HEADER_DIR) +target_include_directories(hikptool PRIVATE ${HIKPTOOL_HEADER_DIR}) +target_link_directories(hikptool PRIVATE ${CMAKE_INSTALL_PREFIX}/lib) +target_link_libraries(hikptool PRIVATE KPTDEV_SO) +target_link_options(hikptool PRIVATE -g -lpthread -ldl -lm -lrt -T ${CMAKE_CURRENT_SOURCE_DIR}/hikp_register.ld) +install(TARGETS hikptool RUNTIME DESTINATION bin OPTIONAL) diff --git a/hikp_init_main.c b/hikp_init_main.c new file mode 100644 index 0000000..4102c69 --- /dev/null +++ b/hikp_init_main.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "op_logs.h" +#include "hikptdev_plug.h" + +/* hikptool command adapter */ +struct cmd_adapter g_tool = { 0 }; + +static void _sig_ign_handle(int arg) +{ + signal_op_log_write(arg); + hikp_unlock(); + _exit(1); +} + +static void sig_init(void) +{ + (void)signal(SIGINT, _sig_ign_handle); /* Quit process */ + (void)signal(SIGTERM, _sig_ign_handle); + (void)signal(SIGQUIT, _sig_ign_handle); + (void)signal(SIGHUP, _sig_ign_handle); + (void)signal(SIGSEGV, _sig_ign_handle); + (void)signal(SIGBUS, _sig_ign_handle); + (void)signal(SIGFPE, _sig_ign_handle); + (void)signal(SIGABRT, _sig_ign_handle); + (void)signal(SIGTSTP, _sig_ign_handle); /* Stop process */ +} + +static void show_tool_version(const struct cmd_adapter *adapter) +{ + printf("%s version %s Huawei\n", adapter->name, adapter->version); +} + +static int cmp(const void *a, const void *b) +{ + struct hikp_cmd_type x = *(struct hikp_cmd_type *)a; + struct hikp_cmd_type y = *(struct hikp_cmd_type *)b; + + return strncmp(x.name, y.name, MAX_CMD_LEN); +} + +static void show_tool_help(const struct cmd_adapter *adapter) +{ + struct hikp_cmd_type *start_cmd_ptr = (struct hikp_cmd_type *)&_s_cmd_data; + struct hikp_cmd_type *end_cmd_ptr = (struct hikp_cmd_type *)&_e_cmd_data; + struct hikp_cmd_type *cmd_ptr = NULL; + + if (adapter == NULL) + return; + + printf("\n Usage: %s [option]\n\n", adapter->name); + printf(" -h, --help show help information\n"); + printf(" -v, --version show version information\n"); + printf("\n Major Commands:\n\n"); + + /* We should first sort by dictionary to + * avoid the confusion of multi-process compilation. + */ + qsort(start_cmd_ptr, end_cmd_ptr - start_cmd_ptr, + sizeof(struct hikp_cmd_type), (const void *)cmp); + for (cmd_ptr = start_cmd_ptr; cmd_ptr < end_cmd_ptr; cmd_ptr++) + printf(" %-23s %s\n", cmd_ptr->name, cmd_ptr->help_info); + + printf("\n"); +} + +static bool is_help_version(struct cmd_adapter *adapter, const int argc, const char **argv) +{ +#define ARG_NUM_FOR_HELP_VER 2 + const char *arg = NULL; + + if (argc == 1) { + show_tool_help(adapter); + return true; + } + if (argc != ARG_NUM_FOR_HELP_VER) + return false; + + arg = argv[1]; + if (is_specified_option(arg, "-h", "--help")) { + show_tool_help(adapter); + return true; + } + if (is_specified_option(arg, "-v", "--version")) { + show_tool_version(adapter); + return true; + } + + return false; +} + +static int parse_and_init_cmd(const char *arg) +{ + struct hikp_cmd_type *start_cmd_ptr = (struct hikp_cmd_type *)&_s_cmd_data; + struct hikp_cmd_type *end_cmd_ptr = (struct hikp_cmd_type *)&_e_cmd_data; + struct hikp_cmd_type *cmd_ptr = NULL; + + for (cmd_ptr = start_cmd_ptr; cmd_ptr < end_cmd_ptr; cmd_ptr++) { + if (strnlen(cmd_ptr->name, MAX_CMD_LEN) != strnlen(arg, MAX_CMD_LEN)) + continue; + + if (strncmp(arg, cmd_ptr->name, strnlen(cmd_ptr->name, MAX_CMD_LEN - 1) + 1) == 0) { + g_tool.p_major_cmd.cmd_ptr = cmd_ptr; + cmd_ptr->cmd_init(); + return 0; + } + } + + return -EINVAL; +} + +int main(const int argc, const char **argv) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + int ret; + + ret = op_log_initialise(HIKP_LOG_DIR_PATH); + if (ret != 0) + return ret; + + /* Pre-record user input log */ + op_log_record_input(argc, argv); + + sig_init(); + command_mechanism_init(&g_tool, get_tool_name()); + + if (is_help_version(&g_tool, argc, argv)) + return 0; + + ret = hikp_dev_init(); + if (ret != 0) { + HIKP_ERROR_PRINT("Failed to init RCiEP\n"); + major_cmd->err_no = ret; + goto IEP_INIT_FAIL; + } + + ret = parse_and_init_cmd(argv[1]); + if (ret != 0) { + major_cmd->err_no = ret; + HIKP_ERROR_PRINT("Unknown major command, try '%s -h' for help.\n", g_tool.name); + } else { + command_parse_and_excute(argc, argv); + } + + hikp_dev_uninit(); + +IEP_INIT_FAIL: + op_log_record_result(major_cmd->err_no, get_tool_name(), HIKP_LOG_DIR_PATH); + + return major_cmd->err_no; +} diff --git a/hikp_register.ld b/hikp_register.ld new file mode 100644 index 0000000..b1bec44 --- /dev/null +++ b/hikp_register.ld @@ -0,0 +1,229 @@ +/* Script for -z combreloc: combine and sort reloc sections */ +/* Copyright (C) 2014-2018 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", + "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SEARCH_DIR("=/usr/aarch64-Huawei-linux/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/aarch64-Huawei-linux/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.ifunc) + } + .rela.plt : + { + *(.rela.plt) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } =0x1f2003d5 + .plt : ALIGN(16) { *(.plt) *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x1f2003d5 + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } =0x1f2003d5 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : + { + PROVIDE_HIDDEN (__tdata_start = .); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (24, .); + .got.plt : { *(.got.plt) *(.igot.plt) } + .cmd_data : + { + . = ALIGN(4); + PROVIDE (_s_cmd_data = .); + KEEP(*(.cmd_data)); + PROVIDE (_e_cmd_data = .); + . = ALIGN(4); + } + .data : + { + PROVIDE (__data_start = .); + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + __bss_start__ = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + _bss_end__ = .; __bss_end__ = .; + . = ALIGN(64 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(64 / 8); + __end__ = .; + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/ossl/ossl_user_linux.c b/ossl/ossl_user_linux.c new file mode 100644 index 0000000..8266a19 --- /dev/null +++ b/ossl/ossl_user_linux.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "ossl_user_linux.h" + +static struct flock g_fcntl_lock = { + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, +}; + +int uda_access(const char *file_dir) +{ + char path[PATH_MAX + 1] = { 0 }; + + if (strlen(file_dir) > PATH_MAX || realpath(file_dir, path) == NULL) + return -ENOENT; + + return faccessat(AT_FDCWD, path, F_OK, AT_EACCESS) ? (-ENOENT) : 0; +} + +int uda_realpath(const char *file_dir, char *format_dir) +{ + if (file_dir == NULL || format_dir == NULL) + return -EFAULT; + + if (realpath(file_dir, format_dir) == NULL) { + perror("realpath failed"); + return -errno; + } + + return 0; +} + +int uda_fcntl(const char *lock_file, uint32_t operation, int *fd) +{ + uint32_t f_opt = 0; + int fd_t = 0; + int ret; + + if ((fd == NULL) || (lock_file == NULL)) + return -EFAULT; + + fd_t = open(lock_file, O_WRONLY | O_CREAT, 0700); + if (fd_t < 0) + return -errno; + + *fd = fd_t; + + g_fcntl_lock.l_type = F_WRLCK; + if (operation == UDA_FLOCK_NOBLOCK) + ret = fcntl(fd_t, F_SETLK, &g_fcntl_lock); + else + ret = fcntl(fd_t, F_SETLKW, &g_fcntl_lock); + if (ret != 0) + close(fd_t); + + return ret; +} + +int uda_unfcntl(const int *fd, const uint32_t operation) +{ + int fd_t; + + if (fd == NULL) + return -EFAULT; + + if (*fd < 0) + return -EBADFD; + + fd_t = *fd; + g_fcntl_lock.l_type = F_UNLCK; + if (operation == UDA_FLOCK_NOBLOCK) + (void)fcntl(fd_t, F_SETLK, &g_fcntl_lock); + else + (void)fcntl(fd_t, F_SETLKW, &g_fcntl_lock); + + return close(fd_t); +} + +void record_syslog(const char *ident, const int priority, const char *logs) +{ + if (!logs || !ident) { + printf("Invalid parameter [%s].\n", __func__); + return; + } + + openlog(ident, LOG_CONS | LOG_PID, LOG_USER); + syslog(priority, "%s", logs); + closelog(); +} diff --git a/ossl/ossl_user_linux.h b/ossl/ossl_user_linux.h new file mode 100644 index 0000000..16fc2d2 --- /dev/null +++ b/ossl/ossl_user_linux.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 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 OSSL_USER_LINUX_H +#define OSSL_USER_LINUX_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *)0) +#endif + +#ifndef F_OK +#define F_OK 0 +#endif + +#define TOOL_REAL_PATH_MAX_LEN 512 + +#define HIKP_LOG_DIR_PATH "/var/log/hikp/operation_logs/" + +#define PWD_STR "./" +#define DIR_BREAK_CHAR '/' +#define DIR_BREAK_STRING "/" + +#ifndef true +#define true 1 +#endif +#ifndef false +#define false 0 +#endif +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +enum { + UDA_FLOCK_NOBLOCK = 0, + UDA_FLOCK_BLOCK = 1 +}; + +extern int uda_access(const char *file_dir); +extern int uda_realpath(const char *file_dir, char *format_dir); +extern int uda_fcntl(const char *lock_file, uint32_t operation, int *fd); +int uda_unfcntl(const int *fd, const uint32_t operation); + +extern void record_syslog(const char *ident, const int priority, const char *logs); + +#endif diff --git a/tool_lib/op_logs.c b/tool_lib/op_logs.c new file mode 100644 index 0000000..d6082a3 --- /dev/null +++ b/tool_lib/op_logs.c @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "op_logs.h" + +static char g_op_log[OP_LOG_FILE_PATH_MAXLEN] = {0}; +static char g_cmd_exec_time[LOG_TIME_LENGTH] = {0}; +static bool g_record = true; +static bool g_log_info; +static char g_input_buf[OP_LOG_FILE_W_MAXSIZE + 1] = {0}; + + +static void op_log_write(const char *log_data) +{ + size_t w_size; + FILE *fd; + int ret; + + if (strlen(g_op_log) == 0) + return; + + if (!is_file_exist(g_op_log)) + return; + + fd = fopen(g_op_log, "a"); + if (fd == NULL) { + HIKP_ERROR_PRINT("Can not open operation log file[%s], errno is %d\n", + g_op_log, errno); + return; + } + (void)chmod(g_op_log, 0640); + w_size = fwrite((void *)log_data, 1U, strlen(log_data), fd); + if (strlen(log_data) > ((uint32_t)w_size)) + HIKP_ERROR_PRINT("Error data size write to file, errno is %d\n", errno); + + (void)fclose(fd); +} + +static int op_log_write_buffer(const char *log_data, const char *log_dir) +{ + sigset_t sigset; + int op_lock_fd; + int ret; + + sigfillset(&sigset); + sigprocmask(SIG_BLOCK, &sigset, NULL); + ret = tool_flock(OP_LOG_LOCK_NAME, UDA_FLOCK_BLOCK, &op_lock_fd, log_dir); + if (ret == -ENOENT) { + HIKP_ERROR_PRINT("Folder or file required by the operation is not exist.\n"); + return ret; + } + + if (ret) { + HIKP_ERROR_PRINT("Multi-user operate in the meantime will causes fault(%d).\n", + ret); + return ret; + } + + op_log_write(log_data); + tool_unlock(&op_lock_fd, UDA_FLOCK_BLOCK); + g_log_info = true; + sigprocmask(SIG_UNBLOCK, &sigset, NULL); + return 0; +} + +void op_log_on(void) +{ + g_record = true; +} + +void op_log_off(void) +{ + g_record = false; +} + +static bool op_log_is_on(void) +{ + return g_record; +} + +static double op_log_diff_timeval(const struct timeval *now, const struct timeval *last) +{ + double time_val; + + time_val = now->tv_sec - last->tv_sec; + time_val += (now->tv_usec - last->tv_usec) / OP_LOG_SEC_AND_MICROSEC_TRANS; + return time_val; +} + +static int op_log_add_time_to_log(char *log_base, int *offset, uint32_t flag) +{ + static struct timeval g_tv; + struct timeval tv; + struct tm ptm; + int len = 0; + long usec; + long sec; + int ret; + + (void)gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &ptm); + if (flag == LOG_FLAG_DATE_TIME) { + g_tv = tv; + len = (int)strftime(log_base + *offset, (OP_LOG_FILE_W_MAXSIZE + 1 - *offset), + OP_LOG_TIME_TEMP, &ptm); + ret = snprintf(log_base + *offset + len, + (OP_LOG_FILE_W_MAXSIZE + 1 - *offset - len), OP_LOG_SEC_TIME_TEMP, + tv.tv_sec + tv.tv_usec / OP_LOG_SEC_AND_MICROSEC_TRANS); + } else if (flag == LOG_FLAG_ONLY_TIME) { + len = (int)strftime(log_base + *offset, (OP_LOG_FILE_W_MAXSIZE + 1 - *offset), + OP_LOG_RESULT_TIME_TEMP, &ptm); + ret = snprintf(log_base + *offset + len, + (OP_LOG_FILE_W_MAXSIZE + 1 - *offset - len), + OP_LOG_SEC_TIME_TEMP, + op_log_diff_timeval((const struct timeval *)&tv, + (const struct timeval *)&g_tv)); + } + len += ret; + if (ret < 0 || len >= (OP_LOG_FILE_W_MAXSIZE + 1 - *offset)) + return -EINVAL; + + *offset += len; + + return 0; +} + +static int op_log_add_info_to_log(char *log_base, int *offset, const char *str) +{ + int len; + + len = snprintf(log_base + *offset, (OP_LOG_FILE_W_MAXSIZE + 1 - *offset), "%s", str); + if (len < 0 || len >= (OP_LOG_FILE_W_MAXSIZE + 1 - *offset)) + return -EINVAL; + + *offset += len; + + return 0; +} + +static int op_log_file_rollback(const char *op_log_backup, const char *log_dir) +{ + char rollback_log[OP_LOG_FILE_W_MAXSIZE + 1] = {0}; + int offset = 0; + int ret; + int len; + + ret = file_rollback(g_op_log, op_log_backup, OP_LOG_FILE_MAX_SIZE); + if (ret) { + if (ret == FILE_LEN_OK) + return 0; + + HIKP_ERROR_PRINT("Log file rollback failed.\n"); + return ret; + } + + ret = op_log_add_time_to_log(rollback_log, &offset, LOG_FLAG_DATE_TIME); + if (ret) + return ret; + + ret = op_log_add_info_to_log(rollback_log, &offset, + "The old operation log has been backed up to "); + if (ret) + return ret; + + ret = op_log_add_info_to_log(rollback_log, &offset, op_log_backup); + if (ret) + return ret; + + snprintf(rollback_log + offset, + (uint32_t)(OP_LOG_FILE_W_MAXSIZE + 1 - offset), OP_LOG_ITEM_END); + + op_log_write_buffer(rollback_log, log_dir); + + return ret; +} + +static int op_log_dir_mk(const char *log_path) +{ + if (!is_dir_exist(log_path)) + return tool_mk_dir(log_path); + + return 0; +} + +static int op_log_dir_create(char *log_path, int log_path_len) +{ + int ret = 0; + int i; + + for (i = 1; i < log_path_len; i++) { + if (log_path[i] == '/') { + log_path[i] = '\0'; + ret = op_log_dir_mk((const char *)log_path); + if (ret) + return ret; + + log_path[i] = '/'; + } + } + + return ret; +} + +static void op_log_record_time(void) +{ + int offset = 0; + + (void)op_log_add_time_to_log(g_cmd_exec_time, &offset, LOG_FLAG_DATE_TIME); +} + +int op_log_initialise(const char *log_dir) +{ + char op_log_backup[OP_LOG_FILE_PATH_MAXLEN] = {0}; + char log_path[OP_LOG_FILE_PATH_MAXLEN]; + int ret; + + if ((log_dir == NULL) || (strlen(g_op_log) != 0)) + return -EINVAL; + + memset(log_path, '\0', OP_LOG_FILE_PATH_MAXLEN); + memset(g_op_log, '\0', OP_LOG_FILE_PATH_MAXLEN); + ret = snprintf(log_path, sizeof(log_path), "%s", log_dir); + if (ret < 0 || ret >= sizeof(log_path)) + return -EINVAL; + + if (!is_dir_exist(log_path)) { + ret = op_log_dir_create(log_path, strlen(log_path)); + if (ret != 0) { + HIKP_ERROR_PRINT("Operation Log file folder[%s] can not be created.\n", + log_path); + return ret; + } + } + + snprintf(g_op_log, OP_LOG_FILE_PATH_MAXLEN, "%s" DIR_BREAK_STRING "%s", + log_path, OP_LOG_FILE_NAME); + snprintf(op_log_backup, OP_LOG_FILE_PATH_MAXLEN, "%s" DIR_BREAK_STRING "%s", + log_path, OP_LOG_FILE_BACKUP); + + ret = op_log_file_rollback((const char *)op_log_backup, log_dir); + if (ret) + return ret; + + op_log_record_time(); + + return ret; +} + +void op_log_record_input(const int argc, const char **argv) +{ + char input_str[OP_LOG_FILE_W_MAXSIZE + 1] = {0}; + struct op_log_print_t log_info[] = { + {"%s", g_cmd_exec_time}, + {"[%s]", input_str}, + }; + size_t i, arr_size; + int offset = 0; + char *arg; + int ret; + + memset(g_input_buf, 0, sizeof(g_input_buf)); + + if (argv == NULL || argc == 0) + return; + + arg = input_str; + for (i = 0; i < argc; i++) { + snprintf(arg, (sizeof(input_str) - (arg - input_str)), "%s ", argv[i]); + arg = arg + strlen(argv[i]) + 1; + } + input_str[strlen(input_str) - 1] = 0; + arr_size = HIKP_ARRAY_SIZE(log_info); + for (i = 0; i < arr_size; i++) { + ret = snprintf(g_input_buf + offset, (OP_LOG_FILE_W_MAXSIZE + 1 - offset), + log_info[i].format, log_info[i].str); + if (ret < 0 || ret >= (OP_LOG_FILE_W_MAXSIZE + 1 - offset)) + return; + + offset += ret; + } +} + +void op_log_record_result(int ret, const char *tool_name, const char *log_dir) +{ + char result_str[OP_LOG_FILE_W_MAXSIZE + 1] = {0}; + int offset = 0; + int len; + + /* must to open */ + if (op_log_is_on() == false && (ret == 0)) + return; + + len = snprintf(result_str + offset, (OP_LOG_FILE_W_MAXSIZE + 1 - offset), "%s", + g_input_buf); + if (len < 0 || len >= (OP_LOG_FILE_W_MAXSIZE + 1 - offset)) + return; + + offset += len; + + if (op_log_add_time_to_log(result_str, &offset, LOG_FLAG_ONLY_TIME)) + return; + + len = snprintf(result_str + offset, (OP_LOG_FILE_W_MAXSIZE + 1 - offset), + "[%s<%d>].", (ret == 0) ? "SUCCEED" : "FAILED", ret); + if (len < 0 || len >= (OP_LOG_FILE_W_MAXSIZE + 1 - offset)) + return; + + offset += len; + + record_syslog(tool_name, LOG_INFO, result_str); + + snprintf(result_str + offset, (sizeof(result_str) - offset), OP_LOG_ITEM_END); + (void)op_log_write_buffer(result_str, log_dir); +} + +static bool log_info_is_ok(void) +{ + return g_log_info; +} + +static void signal_format_end_log_str(char *log_str, int signal_code) +{ + time_t seconds = time(NULL); + int sec_of_last_day = seconds % SECONDS_PER_DAY; + int hour = sec_of_last_day / SECONDS_PER_HOUR; + int min = (sec_of_last_day % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE; + int sec = (sec_of_last_day % SECONDS_PER_MINUTE); + + /* end of log string format: [hh:mm:ss] [KILLED]. */ + log_str[1] += hour / LOG_TIME_DECIMAL; /* 1: format time: tens of hour */ + log_str[2] += hour % LOG_TIME_DECIMAL; /* 2: format time: units of hour */ + log_str[4] += min / LOG_TIME_DECIMAL; /* 4: format time: tens of min */ + log_str[5] += min % LOG_TIME_DECIMAL; /* 5: format time: units of min */ + log_str[7] += sec / LOG_TIME_DECIMAL; /* 7: format time: tens of sec */ + log_str[8] += sec % LOG_TIME_DECIMAL; /* 8: format time: units of sec */ + log_str[19] += signal_code / LOG_TIME_DECIMAL; /* 19: tens of signal_code */ + log_str[20] += signal_code % LOG_TIME_DECIMAL; /* 20: units of signal_code */ +} + +static int signal_fcntl(const char *name, uint32_t operation, int *fd) +{ + char lock_file[TOOL_LOCK_PATH_MAX_LEN] = HIKP_LOG_DIR_PATH TOOL_LOCK_FLODER_NAME; + int lock_file_len = 0; + int tmp = 0; + int ret; + + while (lock_file[lock_file_len] != '\0') + lock_file_len++; + + if (!is_dir_exist(lock_file)) { + ret = op_log_dir_create(lock_file, lock_file_len); + if (ret) + return ret; + } + + while (name[tmp] != '\0') { + lock_file[lock_file_len] = name[tmp]; + lock_file_len++; + tmp++; + } + lock_file[lock_file_len] = '\0'; + + return uda_fcntl(lock_file, operation, fd); +} + +void signal_op_log_write(int signal_code) +{ + char log_str[] = "[00:00:00] [KILLED<00>].\r\n"; + int op_log_fd; + int start_len; + int len; + int fd; + + if (log_info_is_ok()) + return; + + if (signal_fcntl(OP_LOG_LOCK_NAME, UDA_FLOCK_BLOCK, &op_log_fd)) + return; + + fd = open(g_op_log, O_WRONLY | O_APPEND); + if (fd == -1) { + (void)uda_unfcntl(&op_log_fd, UDA_FLOCK_BLOCK); + return; + } + (void)chmod(g_op_log, 0640); + start_len = 0; + while (g_input_buf[start_len] != '\0') + start_len += 1; + + len = write(fd, g_input_buf, start_len); + if (len == -1) + goto SIGNAL_LOG_OUT; + + signal_format_end_log_str(log_str, signal_code); + len = write(fd, log_str, sizeof(log_str)); + if (len == -1) + goto SIGNAL_LOG_OUT; + +SIGNAL_LOG_OUT: + (void)close(fd); + (void)uda_unfcntl(&op_log_fd, UDA_FLOCK_BLOCK); +} diff --git a/tool_lib/op_logs.h b/tool_lib/op_logs.h new file mode 100644 index 0000000..597f063 --- /dev/null +++ b/tool_lib/op_logs.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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 OP_LOGS_H +#define OP_LOGS_H + +#define OP_LOG_SEC_AND_MICROSEC_TRANS 1000000.0 +#define OP_LOG_DIR_NAME "operation_logs" +#define OP_LOG_FILE_NAME "operations.log" +#define OP_LOG_FILE_BACKUP "operations.log.old" +#define OP_LOG_TIME_TEMP "[%Y-%m-%d %H:%M:%S]" +#define OP_LOG_RESULT_TIME_TEMP "[%H:%M:%S]" +#define OP_LOG_SEC_TIME_TEMP " [%.6f]" +#define OP_LOG_ITEM_END "\r\n" +#define OP_LOG_FILE_PATH_MAXLEN 256 +#define OP_LOG_FILE_W_MAXSIZE 1024 +#define OP_LOG_PARAM_MAX_STRING 512 +#define OP_LOG_LOCK_NAME "op_log" +#define OP_LOG_FILE_MAX_SIZE 0x400000 // 4M + +#define LOG_FLAG_DATE_TIME 0x1 +#define LOG_FLAG_ONLY_TIME 0x2 + +#define LOG_TIME_LENGTH 60 + +#define MINUTES_PER_HOUR 60 +#define SECONDS_PER_MINUTE 60 +#define SECONDS_PER_HOUR (SECONDS_PER_MINUTE * MINUTES_PER_HOUR) +#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) +#define LOG_TIME_DECIMAL 10 + +#define MAX_FORMAT_STRING 10 +struct op_log_print_t { + const char format[MAX_FORMAT_STRING]; + char *str; +}; + +void signal_op_log_write(int signal_code); +void op_log_on(void); +void op_log_off(void); +int op_log_initialise(const char *log_dir); +void op_log_record_input(const int argc, const char **argv); +void op_log_record_result(int ret, const char *tool_name, const char *log_dir); + +#endif /* OP_LOGS_H */ diff --git a/tool_lib/tool_cmd.c b/tool_lib/tool_cmd.c new file mode 100644 index 0000000..43a3b61 --- /dev/null +++ b/tool_lib/tool_cmd.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" + +/* save the tool real name pointer, it was update when enter main function */ +static const char *g_tool_name = TOOL_NAME; + +const char *get_tool_name(void) +{ + return g_tool_name; +} + +void command_mechanism_init(struct cmd_adapter *adapter, const char *name) +{ + if ((adapter == NULL) || (name == NULL)) { + HIKP_ERROR_PRINT("Invalid input parameter.\n"); + return; + } + + adapter->name = name; + adapter->version = TOOL_VER; +} + +static int major_command_check_param(const struct cmd_option *option, const char *arg) +{ + if (option == NULL) + return -EFAULT; + + if (option->have_param) { + if ((!arg) || (arg[0] == '-')) + return -EINVAL; + return 0; + } + + return -EPERM; +} + +static int check_command_length(const int argc, const char **argv) +{ + unsigned long long str_len = 0; + int i; + + for (i = 0; i < argc; i++) { + str_len += (unsigned long long)strlen(argv[i]); + if (str_len > COMMAND_MAX_STRING) + return -EINVAL; + } + + return 0; +} + +struct major_cmd_ctrl *get_major_cmd(void) +{ + return &g_tool.p_major_cmd; +} + +static int sub_command_record(struct major_cmd_ctrl *major_cmd, + struct cmd_option *option, const char *arg) +{ + major_cmd->err_no = option->record(major_cmd, arg); + + if (((strlen((const char *)option->little) + 1) != sizeof("-h")) && + ((strlen((const char *)option->large) + 1) != sizeof("--help"))) { + return major_cmd->err_no; + } + if ((strncmp((const char *)option->little, "-h", sizeof("-h")) == 0) || + (strncmp((const char *)option->large, "--help", sizeof("--help")) == 0)) { + return -ESRCH; + } + + return major_cmd->err_no; +} + +bool is_specified_option(const char *arg, const char *little, const char *large) +{ + bool flag; + + flag = (little == NULL) || (large == NULL) || (arg == NULL); + if (flag) + return false; + + flag = (strlen(arg) != strlen(little)) && (strlen(arg) != strlen(large)); + if (flag) + return false; + + return (strncmp(arg, little, strlen(little) + 1) == 0) || + (strncmp(arg, large, strlen(large) + 1) == 0); +} + +static int major_command_parse(struct major_cmd_ctrl *major_cmd, const int argc, const char **argv) +{ + struct cmd_option *option = NULL; + int intermediate_var; + const char *param = NULL; + int i, j; + int ret; + + for (i = 0; i < argc; i++) { + /* Traverse all registered subcommands */ + for (j = 0; j < major_cmd->option_count; j++) { + option = &major_cmd->options[j]; + if (!is_specified_option(argv[i], option->little, option->large)) + continue; + + /* Prevent duplicate input */ + if (major_cmd->options_repeat_flag[j] != 0) { + major_cmd->err_no = -EINVAL; + snprintf(major_cmd->err_str, sizeof(major_cmd->err_str), + "Repeated option %s.", option->little); + return -EINVAL; + } + major_cmd->options_repeat_flag[j] = 1; + + /* Determine whether the subcommand is related to the parameter */ + intermediate_var = i + 1; + param = intermediate_var < argc ? argv[intermediate_var] : NULL; + ret = major_command_check_param(option, param); + if (ret == 0) { + i++; + } else if (ret == -EINVAL) { + major_cmd->err_no = -EINVAL; + snprintf(major_cmd->err_str, sizeof(major_cmd->err_str), + "%s option need parameter.", option->little); + return -EINVAL; + } + + /* Record the option identifier and parameter + * information to provide parameters + * for subsequent execute processing. + */ + ret = sub_command_record(major_cmd, option, param); + if (ret) + return ret; + + break; + } + + if (j == major_cmd->option_count) { + major_cmd->err_no = -EINVAL; + snprintf(major_cmd->err_str, sizeof(major_cmd->err_str), + "%s is not option needed.", argv[i]); + return -EINVAL; + } + } + + return 0; +} + +void cmd_option_register(const char *little, const char *large, + uint8_t have_param, command_record_t record) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + struct cmd_option *option = NULL; + + if (((little == NULL) && (large == NULL)) || (record == NULL)) { + HIKP_ERROR_PRINT("Invalid input parameter.\n"); + return; + } + + if (major_cmd->option_count >= COMMAND_MAX_OPTIONS) { + HIKP_ERROR_PRINT("Do not support more than %d options\n", COMMAND_MAX_OPTIONS); + return; + } + + option = &major_cmd->options[major_cmd->option_count]; + major_cmd->options_repeat_flag[major_cmd->option_count] = 0; + major_cmd->option_count++; + + option->record = record; + option->little = little; + option->large = large; + option->have_param = have_param; +} + +void command_parse_and_excute(const int argc, const char **argv) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + int lock_fd; + int check; + int ret; + + major_cmd->err_no = check_command_length(argc, argv); + if (major_cmd->err_no) { + snprintf(major_cmd->err_str, sizeof(major_cmd->err_str), "Command input too long."); + goto PARSE_OUT; + } + + /* More than 2 means major command need to be parsed */ + if (argc > 2) { + /* 2: Start index of the execution content */ + if (major_command_parse(major_cmd, argc - 2, argv + 2)) + goto PARSE_OUT; + } + ret = tool_flock(CMD_EXECUTE_LOCK_NAME, UDA_FLOCK_BLOCK, &lock_fd, HIKP_LOG_DIR_PATH); + if (ret) { + major_cmd->err_no = ret < 0 ? ret : -ret; + snprintf(major_cmd->err_str, sizeof(major_cmd->err_str), "locking failed."); + goto PARSE_OUT; + } + major_cmd->execute(major_cmd); + tool_unlock(&lock_fd, UDA_FLOCK_BLOCK); +PARSE_OUT: + if (major_cmd->err_no) + HIKP_ERROR_PRINT("%s command error(%d): %s\n", + g_tool.name, major_cmd->err_no, major_cmd->err_str); +} diff --git a/tool_lib/tool_cmd.h b/tool_lib/tool_cmd.h new file mode 100644 index 0000000..566b2a3 --- /dev/null +++ b/tool_lib/tool_cmd.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 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 TOOL_CMD_H +#define TOOL_CMD_H +#include "tool_lib.h" + +#define CMD_EXECUTE_LOCK_NAME "op_execute_lock" + +/* The maximum number of this command supported by a single main command */ +#define COMMAND_MAX_OPTIONS 64 +/* Full command maximum length */ +#define COMMAND_MAX_STRING 512 +/* Length of command error description */ +#define COMMANDER_ERR_MAX_STRING 128 + +/* Define driver type which hikptool needed, defined as bit mask value */ +enum { + DRIVER_TYPE_OF_NONE = 0, + DRIVER_TYPE_OF_OTHERS = HI_BIT(0), + DRIVER_TYPE_OF_NIC_KERNEL = HI_BIT(1), + DRIVER_TYPE_OF_NIC_DPDK = HI_BIT(2), +}; + +struct major_cmd_ctrl; +struct cmd_adapter; + +/* Callback function prototype for minor command parameter records */ +typedef int (*command_record_t)(struct major_cmd_ctrl *major, const char *param); +/* Callback function prototype for command execution */ +typedef void (*command_executeute_t)(struct major_cmd_ctrl *major); + +/* Subcommand description information */ +struct cmd_option { + const char *little; + const char *large; + uint8_t have_param; + command_record_t record; +}; + +/* Main command description */ +struct major_cmd_ctrl { + int option_count; + struct cmd_option options[COMMAND_MAX_OPTIONS]; + uint32_t options_repeat_flag[COMMAND_MAX_OPTIONS]; + command_executeute_t execute; + + int err_no; + char err_str[COMMANDER_ERR_MAX_STRING + 1]; + struct hikp_cmd_type *cmd_ptr; + void *cmd_param; +}; + +struct cmd_adapter { + const char *name; + const char *version; + struct major_cmd_ctrl p_major_cmd; +}; + +extern int _s_cmd_data; +extern int _e_cmd_data; +extern struct cmd_adapter g_tool; + +extern const char *get_tool_name(void); +extern void command_mechanism_init(struct cmd_adapter *adapter, const char *name); +extern bool is_specified_option(const char *arg, const char *little, const char *large); +extern void cmd_option_register(const char *little, const char *large, uint8_t have_param, + command_record_t record); +extern void command_parse_and_excute(const int argc, const char **argv); +extern struct major_cmd_ctrl *get_major_cmd(void); + +#endif diff --git a/tool_lib/tool_lib.c b/tool_lib/tool_lib.c new file mode 100644 index 0000000..ad4bb68 --- /dev/null +++ b/tool_lib/tool_lib.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include +#include +#include +#include + +int string_toui(const char *nptr, uint32_t *value) +{ + char *endptr = NULL; + int64_t tmp_value; + + if (nptr == NULL) + return -EINVAL; + + tmp_value = strtol(nptr, &endptr, 0); + if ((*endptr != 0) || (tmp_value > UINT_MAX) || (tmp_value < 0)) + return -EINVAL; + + *value = (uint32_t)tmp_value; + return 0; +} + +int string_toub(const char *nptr, uint8_t *value) +{ + char *endptr = NULL; + int64_t tmp_value; + + if (nptr == NULL) + return -EINVAL; + + tmp_value = strtol(nptr, &endptr, 0); + if ((*endptr != 0) || (tmp_value > UCHAR_MAX) || (tmp_value < 0)) + return -EINVAL; + + *value = (uint8_t)tmp_value; + return 0; +} + +static void dir_break_char(char *absolute_path, uint32_t absolute_len) +{ + uint32_t i; + + i = (uint32_t)strlen(absolute_path); + if (i + 1 >= absolute_len) { + HIKP_ERROR_PRINT("absolute path invalid.\n"); + return; + } + if (i != 1) { + if (absolute_path[i] != DIR_BREAK_CHAR) + absolute_path[i++] = DIR_BREAK_CHAR; + absolute_path[i] = '\0'; + } +} + +static int check_current_patch_dir(const char *file, char *absolute_path, uint32_t absolute_len) +{ + char tmp_path[TOOL_REAL_PATH_MAX_LEN] = {0}; + int ret; + + strncat(tmp_path, PWD_STR, HIKP_STR_BUF_LEFT_LEN(tmp_path)); + ret = uda_realpath(tmp_path, absolute_path); + if (ret) + return ret; + + dir_break_char(absolute_path, absolute_len); + + strncat(absolute_path, file, absolute_len - strlen(absolute_path) - 1); + + return 0; +} + +static int check_absolute_patch_dir(char *file, char *absolute_path, uint32_t absolute_len) +{ + char file_name[TOOL_REAL_PATH_MAX_LEN] = {0}; + char *pchar = strrchr(file, DIR_BREAK_CHAR); + int ret; + int i; + + if (pchar == NULL) + return -EINVAL; + + pchar++; + i = 0; + while (*pchar != '\0') { + file_name[i] = *pchar; + *pchar = '\0'; + pchar++; + i++; + } + file_name[i] = '\0'; + + ret = uda_realpath(file, absolute_path); + if (ret) + return ret; + + dir_break_char(absolute_path, absolute_len); + + strncat(absolute_path, file_name, absolute_len - strlen(absolute_path) - 1); + + return 0; +} + +static int check_file_path_dir(const char *file_path, char *absolute_path, uint32_t absolute_len) +{ + char file[TOOL_REAL_PATH_MAX_LEN] = {0}; + + if ((file_path == NULL) || (absolute_path == NULL) || (absolute_len == 0)) + return -EFAULT; + + if (strlen(file_path) >= sizeof(file)) + return -EINVAL; + + strncpy(file, file_path, sizeof(file) - 1); + + memset(absolute_path, 0, absolute_len); + + return (strchr(file, DIR_BREAK_CHAR)) == NULL ? + check_current_patch_dir(file, absolute_path, absolute_len) : + check_absolute_patch_dir(file, absolute_path, absolute_len); +} + +int check_file_access(const char *file_dir) +{ + if (file_dir == NULL) + return -ENXIO; + + return uda_access(file_dir); +} + +static uint32_t get_file_size(const char *file_dir) +{ + char format_dir[TOOL_REAL_PATH_MAX_LEN] = {0}; + struct stat file_stat = { 0 }; + int ret; + + if (file_dir == NULL) + return 0; + + ret = check_file_path_dir(file_dir, format_dir, TOOL_REAL_PATH_MAX_LEN); + if (ret) { + HIKP_ERROR_PRINT("This file path[%s] is not exist.\n", file_dir); + return 0; + } + + ret = stat(format_dir, &file_stat); + if (ret) { + HIKP_ERROR_PRINT("Can not get size of file %s.\n", format_dir); + return 0; + } + return (uint32_t)file_stat.st_size; +} + +bool is_file_exist(const char *file) +{ + if (file == NULL) + return false; + + /* access return 0, means file exist, else file no exist. */ + return (uda_access(file) == 0); +} + +bool is_dir_exist(const char *path) +{ + return is_file_exist(path); +} + +int tool_mk_dir(const char *path) +{ + if (path == NULL) + return -EFAULT; + + return (int)mkdir(path, 0700); +} + +int tool_flock(const char *name, uint32_t operation, int *fd, const char *log_dir) +{ + char lock_file[TOOL_LOCK_PATH_MAX_LEN] = {0}; + size_t file_len; + int ret; + + if (!name || !fd || !log_dir) + return -EFAULT; + + file_len = strlen(log_dir) + strlen(TOOL_LOCK_FLODER_NAME) + strlen(name); + if (file_len > TOOL_LOCK_PATH_MAX_LEN - 1) + return -EINVAL; + + if (!is_dir_exist(log_dir)) { + if (tool_mk_dir(log_dir)) { + HIKP_ERROR_PRINT("manage folder [%s] can not be created.\n", log_dir); + return -ENOENT; + } + } + + ret = snprintf(lock_file, sizeof(lock_file), "%s", log_dir); + if (ret < 0 || ret >= sizeof(lock_file)) { + HIKP_ERROR_PRINT("generate flock [%s] folder name failed, errno is %d\n", + log_dir, errno); + return -errno; + } + + strncat(lock_file, TOOL_LOCK_FLODER_NAME, HIKP_STR_BUF_LEFT_LEN(lock_file)); + if (!is_dir_exist(lock_file)) { + if (tool_mk_dir(lock_file)) { + HIKP_ERROR_PRINT("lock file folder[%s] can not be created.\n", lock_file); + return -ENOENT; + } + } + + strncat(lock_file, name, HIKP_STR_BUF_LEFT_LEN(lock_file)); + + return uda_fcntl(lock_file, operation, fd); +} + +void tool_unlock(int *fd, uint32_t operation) +{ + if ((fd != NULL) && (*fd != 0)) + (void)uda_unfcntl(fd, operation); +} + +int file_rollback(const char *cur_file, const char *backup_file, uint32_t file_max_size) +{ + bool check = (cur_file == NULL) || (backup_file == NULL) || (file_max_size == 0); + bool rename_flag = false; + FILE *fd = NULL; + int ret; + uint32_t file_size; + + if (check) + return -EFAULT; + + ret = check_file_access(cur_file); + if (ret == 0) { + file_size = get_file_size(cur_file); + if (file_size > file_max_size) { + ret = rename(cur_file, backup_file); + if (ret != 0) { + HIKP_ERROR_PRINT("rename file(%s) fail, errno is %d\n", + cur_file, errno); + return -errno; + } + rename_flag = true; + } else { + return FILE_LEN_OK; + } + } + + fd = fopen(cur_file, "a+"); + if (fd == NULL) { + HIKP_ERROR_PRINT("open %s fail, errno is %d\n", cur_file, errno); + return -errno; + } + (void)chmod(cur_file, 0640); + (void)fclose(fd); + + return rename_flag ? 0 : FILE_LEN_OK; +} + +static int get_rand_str(char *str, int length) +{ +#define TYPE_NUMBER 0 +#define TYPE_UPPERCASE 1 +#define TYPE_LOWERCASE 2 +#define RANDOM_CHAR_TYPE_NUM 3 +#define RANDOM_NUM 2 + struct type_trans type_arr[RANDOM_CHAR_TYPE_NUM] = { + [TYPE_NUMBER] = {'0', 10}, + [TYPE_UPPERCASE] = {'A', 26}, + [TYPE_LOWERCASE] = {'a', 26}, + }; + uint32_t r[RANDOM_NUM]; + int fd, size; + int i, j; + int type; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + HIKP_ERROR_PRINT("open urandom fail, errno is %d\n", errno); + return -errno; + } + for (i = 0; i < (length - 1); i++) { + for (j = 0; j < RANDOM_NUM; j++) { + size = read(fd, &r[j], sizeof(uint32_t)); + if (size < 0) { + HIKP_ERROR_PRINT("read fd fail, errno is %d\n", errno); + close(fd); + return -errno; + } + } + type = r[0] % RANDOM_CHAR_TYPE_NUM; + str[i] = type_arr[type].type_base + r[1] % type_arr[type].type_size; + } + close(fd); + + return 0; +} + +int generate_file_name(unsigned char *file_name, + uint32_t file_name_len, const unsigned char *prefix) +{ +#define RANDOM_STR_LENGTH 7 + char str_r[RANDOM_STR_LENGTH] = {0}; + time_t time_seconds = time(0); + struct tm timeinfo; + int ret; + + ret = get_rand_str(str_r, RANDOM_STR_LENGTH); + if (ret) { + HIKP_ERROR_PRINT("get randrom string failed.\n"); + return ret; + } + localtime_r(&time_seconds, &timeinfo); + ret = snprintf((char *)file_name, file_name_len, "%s_%d_%d_%d_%d_%d_%d_%s.log", prefix, + timeinfo.tm_year + START_YEAR, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, str_r); + if (ret < 0 || ret >= file_name_len) { + HIKP_ERROR_PRINT("generate file name failed, errno is %d\n", errno); + return -errno; + } + + return 0; +} + +bool tool_can_print(uint32_t interval, uint32_t burst, uint32_t *print_num, uint64_t *last_time) +{ + uint64_t cur_time; + + cur_time = (uint64_t)time(NULL); + if ((*last_time + interval) == cur_time) + *print_num = 0; + + if (*print_num < (burst)) { + (*print_num)++; + *last_time = cur_time; + return true; + } + + return false; +} diff --git a/tool_lib/tool_lib.h b/tool_lib/tool_lib.h new file mode 100644 index 0000000..29e7e8c --- /dev/null +++ b/tool_lib/tool_lib.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2022 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 __TOOL_LIB_H__ +#define __TOOL_LIB_H__ + +#include "ossl_user_linux.h" + +#define TOOL_NAME "hikptool" + +#define TOOL_VER "1.0.12" + +#define HI_GET_BITFIELD(value, start, mask) (((value) >> (start)) & (mask)) +#define HI_SET_FIELD(origin, shift, val) ((origin) |= (val) << (shift)) + +#define HI_BIT(shift) (1UL << (shift)) +#define HI_SETBIT(x, y) ((x) |= (HI_BIT(y))) +#define HI_CLRBIT(x, y) ((x) &= (~(HI_BIT(y)))) +#define HI_GETBIT(x, y) ((x) & (HI_BIT(y))) + +#define HIKP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define HIKP_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +#define HIKP_MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define BITS_PER_LONG (sizeof(long) * 8) +#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +#define hikp_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift)) +#define hikp_get_bit(origin, shift) hikp_get_field((origin), (0x1UL << (shift)), (shift)) + +#define HIKP_STR_BUF_LEFT_LEN(str) (sizeof(str) - strlen(str) - 1) + +#define HIKP_BITS_PER_BYTE 8 + +#define MAX_CMD_LEN 30 +#define MAX_HELP_INFO_LEN 100 +struct hikp_cmd_type { + char name[MAX_CMD_LEN]; + char help_info[MAX_HELP_INFO_LEN]; + void (*cmd_init)(void); +}; + +#define _cmd_data_ __attribute__((section(".cmd_data"))) + +#define HIKP_CMD_DECLARE(cmd_name, help_info, init_func) \ + static volatile struct hikp_cmd_type _cmd_data_ g_hikp_##init_func##_arr[] = { \ + {cmd_name, help_info, init_func}, \ + } + +struct type_trans { + char type_base; + uint32_t type_size; +}; + +#define FILE_LEN_OK 27 +#define TOOL_LOCK_PATH_MAX_LEN 512 +#define TOOL_LOCK_FLODER_NAME "locks/" + +#define MAX_LOG_NAME_LEN 128 +#define START_YEAR 1900 + +#define HIKP_DEF_RATELIMIT_INTERVAL 5U +#define HIKP_DEF_RATELIMIT_BURST 10U + +#define HIKP_LOG_PRINT(x, args...) \ + do { \ + static uint32_t print_num; \ + static uint64_t last_time; \ + bool can_print = tool_can_print(HIKP_DEF_RATELIMIT_INTERVAL, \ + HIKP_DEF_RATELIMIT_BURST, &print_num, &last_time); \ + if (can_print) { \ + printf(x, ##args); \ + } \ + } while (0) + +#define HIKP_CRITICAL_PRINT(x, args...) HIKP_LOG_PRINT("[ CRITICAL ] " x, ##args) +#define HIKP_ERROR_PRINT(x, args...) HIKP_LOG_PRINT("[ ERROR ] " x, ##args) +#define HIKP_WARN_PRINT(x, args...) HIKP_LOG_PRINT("[ WARN ] " x, ##args) +#define HIKP_INFO_PRINT(x, args...) HIKP_LOG_PRINT("[ INFO ] " x, ##args) +#define HIKP_DBG_PRINT(x, args...) HIKP_LOG_PRINT("[ DBG ] " x, ##args) + +int string_toui(const char *nptr, uint32_t *value); +int string_toub(const char *nptr, uint8_t *value); + +int check_file_access(const char *file_dir); +int tool_flock(const char *name, uint32_t operation, int *fd, const char *log_dir); +void tool_unlock(int *fd, uint32_t operation); +int file_rollback(const char *cur_file, const char *backup_file, uint32_t file_max_size); +bool is_dir_exist(const char *path); +int tool_mk_dir(const char *path); +bool is_file_exist(const char *file); +int generate_file_name(unsigned char *file_name, uint32_t file_name_len, + const unsigned char *prefix); +bool tool_can_print(uint32_t interval, uint32_t burst, uint32_t *print_num, uint64_t *last_time); + +#endif -- Gitee From 3e88714cd928415f6c9decc47f9dc2feb4c0a477 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 14:59:24 +0800 Subject: [PATCH 03/14] support querying SAS module information including CQ/DQ, link bit error, AXI, error statistics, device SAS_ADDR, and ITCT entry information Signed-off-by: nifujia (cherry picked from commit 76d4d17156248b91de8b2c09de0c6895b838014a) --- CMakeLists.txt | 1 + sas/sas_func/sas_analy_queue.c | 117 +++++++++++++++++++ sas/sas_func/sas_analy_queue.h | 36 ++++++ sas/sas_func/sas_common.h | 85 ++++++++++++++ sas/sas_func/sas_dump_reg.c | 76 +++++++++++++ sas/sas_func/sas_dump_reg.h | 27 +++++ sas/sas_func/sas_read_dev.c | 132 ++++++++++++++++++++++ sas/sas_func/sas_read_dev.h | 51 +++++++++ sas/sas_func/sas_read_dqe.c | 113 ++++++++++++++++++ sas/sas_func/sas_read_dqe.h | 85 ++++++++++++++ sas/sas_func/sas_read_errcode.c | 91 +++++++++++++++ sas/sas_func/sas_read_errcode.h | 26 +++++ sas/user_cmd/cmd_code/sas_cmd_anacq.c | 99 ++++++++++++++++ sas/user_cmd/cmd_code/sas_cmd_anadq.c | 93 +++++++++++++++ sas/user_cmd/cmd_code/sas_cmd_common.c | 100 ++++++++++++++++ sas/user_cmd/cmd_code/sas_cmd_dev.c | 101 +++++++++++++++++ sas/user_cmd/cmd_code/sas_cmd_dqe.c | 105 +++++++++++++++++ sas/user_cmd/cmd_code/sas_cmd_dump.c | 115 +++++++++++++++++++ sas/user_cmd/cmd_code/sas_cmd_errcode.c | 102 +++++++++++++++++ sas/user_cmd/cmd_code/sas_tools_include.h | 47 ++++++++ 20 files changed, 1602 insertions(+) create mode 100644 sas/sas_func/sas_analy_queue.c create mode 100644 sas/sas_func/sas_analy_queue.h create mode 100644 sas/sas_func/sas_common.h create mode 100644 sas/sas_func/sas_dump_reg.c create mode 100644 sas/sas_func/sas_dump_reg.h create mode 100644 sas/sas_func/sas_read_dev.c create mode 100644 sas/sas_func/sas_read_dev.h create mode 100644 sas/sas_func/sas_read_dqe.c create mode 100644 sas/sas_func/sas_read_dqe.h create mode 100644 sas/sas_func/sas_read_errcode.c create mode 100644 sas/sas_func/sas_read_errcode.h create mode 100644 sas/user_cmd/cmd_code/sas_cmd_anacq.c create mode 100644 sas/user_cmd/cmd_code/sas_cmd_anadq.c create mode 100644 sas/user_cmd/cmd_code/sas_cmd_common.c create mode 100644 sas/user_cmd/cmd_code/sas_cmd_dev.c create mode 100644 sas/user_cmd/cmd_code/sas_cmd_dqe.c create mode 100644 sas/user_cmd/cmd_code/sas_cmd_dump.c create mode 100644 sas/user_cmd/cmd_code/sas_cmd_errcode.c create mode 100644 sas/user_cmd/cmd_code/sas_tools_include.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 61120f2..c1389f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ endmacro() file(GLOB_RECURSE HIKPTOOL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c ${CMAKE_CURRENT_SOURCE_DIR}/hikp_init_main.c ) diff --git a/sas/sas_func/sas_analy_queue.c b/sas/sas_func/sas_analy_queue.c new file mode 100644 index 0000000..ce886b9 --- /dev/null +++ b/sas/sas_func/sas_analy_queue.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "sas_common.h" +#include "sas_analy_queue.h" + +static int sas_get_res(const struct tool_sas_cmd *cmd, uint32_t *reg_save, uint32_t *reg_num) +{ + struct hikp_cmd_ret *cmd_ret; + struct hikp_cmd_header req_header = { 0 }; + struct sas_analy_para req_data = { 0 }; + + req_data.chip_id = cmd->chip_id; + req_data.die_id = cmd->die_id; + req_data.phy_id = cmd->phy_id; + + if (cmd->sas_cmd_type == ANADQ_NUM) + hikp_cmd_init(&req_header, SAS_MOD, SAS_ANADQ, ANADQ_NUM); + else if (cmd->sas_cmd_type == ANACQ_NUM) + hikp_cmd_init(&req_header, SAS_MOD, SAS_ANACQ, ANACQ_NUM); + else if (cmd->sas_cmd_type == ANADQ_PRT) + hikp_cmd_init(&req_header, SAS_MOD, SAS_ANADQ, ANADQ_PRT); + else + hikp_cmd_init(&req_header, SAS_MOD, SAS_ANACQ, ANACQ_PRT); + + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL) { + printf("sas_analy excutes hikp_cmd_alloc err\n"); + return -EINVAL; + } + *reg_num = cmd_ret->rsp_data_num; + for (int i = 0; i < *reg_num; i++) + reg_save[i] = cmd_ret->rsp_data[i]; + + free(cmd_ret); + return 0; +} + +static void sas_print_prt(const uint32_t *reg_save, uint32_t reg_num) +{ + uint32_t i; + + if (reg_num == 0) { + printf("SAS get queue pointer is failed\n"); + return; + } + printf(" sas queue READ/WRITE pointer:\n"); + printf(" QUEUE READ WRITE\n"); + for (i = 0; i < reg_num; i += REG_NUM_DQ) + printf(" %u 0x%04x 0x%08x\n", + i / REG_NUM_DQ, reg_save[i], reg_save[i + 1]); +} + +static void sas_print_dqnum(const uint32_t *reg_save, uint32_t reg_num) +{ + if (reg_num < DQE_NUM_REG) { + printf("SAS get dq number is failed\n"); + return; + } + printf(" sas delive dq num is %u\n", reg_save[0]); + printf(" sas dqe wait to complete is %u\n", reg_save[1]); +} + +static void sas_print_cqnum(const uint32_t *reg_save, uint32_t reg_num) +{ + if (reg_num < CQ_COAL_CNT) { + printf("SAS get cq number is failed\n"); + return; + } + printf(" sas delive cq num is %u\n", reg_save[CQE_NUM_BYTE]); + if ((reg_save[CQ_COAL] & CQ_COAL_ENABLE) != CQ_COAL_ENABLE) { + printf(" sas cq int coal is disable\n"); + return; + } + printf(" sas cq int coal is enable\n"); + printf(" sas cq int coal time is 0x%08x\n", reg_save[CQ_COAL_TIME]); + printf(" sas cq int coal count is 0x%02x\n", reg_save[CQ_COAL_CNT]); +} + +int sas_analy_cmd(struct tool_sas_cmd *cmd) +{ + int ret; + uint32_t reg_num = 0; + uint32_t reg_save[RESP_MAX_NUM] = { 0 }; + + if (cmd == NULL) + return -ENOSPC; + + ret = sas_get_res(cmd, reg_save, ®_num); + if (ret) + return ret; + + if (cmd->sas_cmd_type == ANADQ_NUM) + sas_print_dqnum(reg_save, reg_num); + else if (cmd->sas_cmd_type == ANACQ_NUM) + sas_print_cqnum(reg_save, reg_num); + else + sas_print_prt(reg_save, reg_num); + + return 0; +} diff --git a/sas/sas_func/sas_analy_queue.h b/sas/sas_func/sas_analy_queue.h new file mode 100644 index 0000000..a6e2223 --- /dev/null +++ b/sas/sas_func/sas_analy_queue.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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 __SAS_ANALY_DQ_H_ +#define __SAS_ANALY_DQ_H_ + +#include "sas_tools_include.h" + +#define REG_NUM_DQ 2 +#define REG_NUM_CQ 2 +#define CQE_NUM_BYTE 0 +#define DQE_NUM_REG 2 +#define CQ_COAL 1 +#define CQ_COAL_TIME 2 +#define CQ_COAL_CNT 3 +#define CQ_COAL_ENABLE 3 + +struct sas_analy_para { + uint32_t chip_id; + uint32_t die_id; + uint32_t phy_id; +}; + +int sas_analy_cmd(struct tool_sas_cmd *cmd); + +#endif diff --git a/sas/sas_func/sas_common.h b/sas/sas_func/sas_common.h new file mode 100644 index 0000000..9464792 --- /dev/null +++ b/sas/sas_func/sas_common.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022 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 __SAS_COMMON_H_ +#define __SAS_COMMON_H_ + +#define RESP_MAX_NUM 60 +#define SAS_MAX_PHY_NUM 7 +#define SAS_MAX_ERR_NUM 6 +#define SAS_ERR_NUM 4 +#define SAS_QUEUE_NUM 16 +#define IPTT_ICT_STATUS 29 +#define LINK_SPEED_OFFSET 8 +#define LINK_SPEED_WIDTH 4 +#define MAX_DEVICE_NUM 2048 + +#define DWS_LOST 0 +#define RESET_PROB 1 +#define CRC_FAIL 2 +#define OPEN_REJ 3 + +/* SAS command code */ +enum sas_cmd_type { + SAS_DUMP = 0, + SAS_ANADQ, + SAS_ANACQ, + SAS_ERRCODE, + SAS_DEV, + SAS_DQE, +}; + +enum sas_dump_cmd_type { + DUMP_GLOBAL, + DUMP_PHYX, + DUMP_AXI, + DUMP_UNKNOWN_TYPE, +}; + +enum sas_anadq_cmd_type { + ANADQ_PRT, + ANADQ_NUM, + ANADQ_UNKNOWN_TYPE, +}; + +enum sas_anacq_cmd_type { + /* + * cq and dq functions use same interface to communication with TF, their subcommands + * must be coded in a unified manner, so ANACQ_PRT is defined as 3. + */ + ANACQ_PRT = 3, + ANACQ_NUM, + ANACQ_UNKNOWN_TYPE, +}; + +enum sas_errcode_cmd_type { + ERRCODE_ALL, + ERRCODE_DWS_LOST, + ERRCODE_RESET_PROB, + ERRCODE_CRC_FAIL, + ERRCODE_OPEN_REJ, + ERRCODE_UNKNOWN_TYPE, +}; + +enum sas_dev_cmd_type { + DEV_LINK, + DEV_INFO, + DEV_UNKNOWN_TYPE, +}; + +enum sas_dqe_cmd_type { + DQE_INFO, + DQE_UNKNOWN_TYPE, +}; + +#endif diff --git a/sas/sas_func/sas_dump_reg.c b/sas/sas_func/sas_dump_reg.c new file mode 100644 index 0000000..d012aa1 --- /dev/null +++ b/sas/sas_func/sas_dump_reg.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "sas_common.h" +#include "sas_dump_reg.h" + +static int sas_get_reg(const struct tool_sas_cmd *cmd, uint32_t *reg_save, uint32_t *reg_num) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct sas_dump_req_para req_data = { 0 }; + + req_data.chip_id = cmd->chip_id; + req_data.die_id = cmd->die_id; + req_data.phy_id = cmd->phy_id; + + hikp_cmd_init(&req_header, SAS_MOD, SAS_DUMP, cmd->sas_cmd_type); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL) { + printf("sas_dump excutes hikp_cmd_alloc err\n"); + return -1; + } + *reg_num = cmd_ret->rsp_data_num; + for (int i = 0; i < *reg_num; i++) + reg_save[i] = cmd_ret->rsp_data[i]; + + free(cmd_ret); + return 0; +} + +static void sas_print_reg(uint32_t cmd_type, const uint32_t *reg_save, uint32_t reg_num) +{ + uint32_t i; + + if (reg_num == 0) { + printf("SAS dump is failed\n"); + return; + } + printf(" sas reg dump list:\n"); + for (i = 0; i < reg_num; i += 1) + printf(" 0x%08x\n", reg_save[i]); +} + +int sas_reg_dump(struct tool_sas_cmd *cmd) +{ + int ret; + uint32_t reg_num = 0; + uint32_t reg_save[RESP_MAX_NUM] = { 0 }; + + if (cmd == NULL) + return -ENOSPC; + + ret = sas_get_reg(cmd, reg_save, ®_num); + if (ret) + return ret; + + sas_print_reg(cmd->sas_cmd_type, reg_save, reg_num); + + return 0; +} diff --git a/sas/sas_func/sas_dump_reg.h b/sas/sas_func/sas_dump_reg.h new file mode 100644 index 0000000..06dca72 --- /dev/null +++ b/sas/sas_func/sas_dump_reg.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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 __SAS_DUMP_REG_H_ +#define __SAS_DUMP_REG_H_ + +#include "sas_tools_include.h" + +struct sas_dump_req_para { + uint32_t chip_id; + uint32_t die_id; + uint32_t phy_id; +}; + +int sas_reg_dump(struct tool_sas_cmd *cmd); + +#endif diff --git a/sas/sas_func/sas_read_dev.c b/sas/sas_func/sas_read_dev.c new file mode 100644 index 0000000..382a1ef --- /dev/null +++ b/sas/sas_func/sas_read_dev.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "sas_common.h" +#include "sas_read_dev.h" + +static int sas_get_dev(const struct tool_sas_cmd *cmd, uint32_t *reg_save, uint32_t *reg_num) +{ + int i; + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct sas_dev_req_para req_data = { 0 }; + + req_data.chip_id = cmd->chip_id; + req_data.die_id = cmd->die_id; + req_data.dev_id = cmd->dev_id; + + hikp_cmd_init(&req_header, SAS_MOD, SAS_DEV, cmd->sas_cmd_type); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL) { + printf("sas_dqe excutes hikp_cmd_alloc err\n"); + return -EINVAL; + } + *reg_num = cmd_ret->rsp_data_num; + for (i = 0; i < *reg_num; i++) + reg_save[i] = cmd_ret->rsp_data[i]; + + free(cmd_ret); + return 0; +} + +static void print_dev_link(const uint32_t *reg_save, uint32_t reg_num) +{ + uint32_t i; + uint32_t index, index1; + uint32_t phy_status = reg_save[0]; + uint32_t link_type = reg_save[1]; + uint32_t link_speed = reg_save[2]; + const char *dev_type[] = { + "not SATA", + "SATA", + }; + + const char *dev_speed[] = { + "1.5Gbps", + "3.0GBPS", + "6.0Gbps", + "12.0GBPS", + }; + + for (i = 0; i <= SAS_MAX_PHY_NUM; i++) { + if ((phy_status >> i) & 0x1) { + index = ((link_type >> i) & 0x1) ? 1 : 0; + index1 = ((link_speed >> (i * LINK_SPEED_WIDTH)) & 0xf) - LINK_SPEED_OFFSET; + if (index1 < HIKP_ARRAY_SIZE(dev_speed)) + printf("device on phy%u is %s, link speed is %s\n", + i, dev_type[index], dev_speed[index1]); + } + } +} + +static void print_dev_info(const void *reg_save, uint32_t reg_num) +{ + struct hikp_sas_itct *itct = (struct hikp_sas_itct *)reg_save; + + printf("The device information as below:\n"); + printf("dev_type: %d\n", itct->dw0.dev_type); + printf("dev_valid: %d\n", itct->dw0.dev_valid); + printf("break_reply_en: %d\n", itct->dw0.break_reply_en); + printf("smp_timeout: %d\n", itct->dw0.smp_timeout); + printf("tlr_en: %d\n", itct->dw0.tlr_en); + printf("awt_continue: %d\n", itct->dw0.awt_continue); + printf("sas_addr: 0x%llx\n", itct->sas_addr); + printf("I_T_nexus_loss: %d\n", itct->dw2.I_T_nexus_loss); + printf("awt_initial_value: %d\n", itct->dw2.awt_initial_value); + printf("maximum_connect_time: %d\n", itct->dw2.maximum_connect_time); + printf("reject_to_open_limit: %d\n", itct->dw2.reject_to_open_limit); +} + +static void sas_print_dev(const uint32_t *reg_save, uint32_t reg_num, uint32_t cmd_type) +{ + uint32_t i; + + if (reg_num == 0) { + printf("SAS device is failed\n"); + return; + } + switch (cmd_type) { + case DEV_LINK: + print_dev_link(reg_save, reg_num); + break; + case DEV_INFO: + print_dev_info(reg_save, reg_num); + break; + default: + printf("cmd_type is error\n"); + } +} + + +int sas_dev(const struct tool_sas_cmd *cmd) +{ + int ret; + uint32_t reg_num = 0; + uint32_t reg_save[RESP_MAX_NUM] = { 0 }; + + if (cmd == NULL) + return -ENOSPC; + + ret = sas_get_dev(cmd, reg_save, ®_num); + if (ret) + return ret; + + sas_print_dev(reg_save, reg_num, cmd->sas_cmd_type); + return 0; +} diff --git a/sas/sas_func/sas_read_dev.h b/sas/sas_func/sas_read_dev.h new file mode 100644 index 0000000..47d984f --- /dev/null +++ b/sas/sas_func/sas_read_dev.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 __SAS_DEV_H_ +#define __SAS_DEV_H_ + +#include "sas_tools_include.h" + +struct sas_dev_req_para { + uint32_t chip_id; + uint32_t die_id; + uint32_t dev_id; +}; + +struct hikp_sas_itct_dw0 { + uint64_t dev_type : 2; + uint64_t dev_valid : 1; + uint64_t break_reply_en : 1; + uint64_t reserved0 : 12; + uint64_t smp_timeout : 8; + uint64_t tlr_en : 1; + uint64_t awt_continue : 1; + uint64_t reserved : 38; +}; + +struct hikp_sas_itct_dw2 { + uint64_t I_T_nexus_loss : 16; + uint64_t awt_initial_value : 16; + uint64_t maximum_connect_time : 16; + uint64_t reject_to_open_limit : 16; +}; + +struct hikp_sas_itct { + struct hikp_sas_itct_dw0 dw0; + uint64_t sas_addr; + struct hikp_sas_itct_dw2 dw2; +}; + +int sas_dev(const struct tool_sas_cmd *cmd); + +#endif diff --git a/sas/sas_func/sas_read_dqe.c b/sas/sas_func/sas_read_dqe.c new file mode 100644 index 0000000..fc04682 --- /dev/null +++ b/sas/sas_func/sas_read_dqe.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "sas_common.h" +#include "sas_read_dqe.h" + +static int sas_get_dqe(const struct tool_sas_cmd *cmd, uint32_t *reg_save, uint32_t *reg_num) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct sas_dqe_req_para req_data = { 0 }; + + req_data.chip_id = cmd->chip_id; + req_data.die_id = cmd->die_id; + req_data.que_id = cmd->que_id; + req_data.dqe_id = cmd->dqe_id; + + hikp_cmd_init(&req_header, SAS_MOD, SAS_DQE, cmd->sas_cmd_type); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL) { + printf("sas_dqe excutes hikp_cmd_alloc err\n"); + return -EINVAL; + } + *reg_num = cmd_ret->rsp_data_num; + for (int i = 0; i < *reg_num; i++) + reg_save[i] = cmd_ret->rsp_data[i]; + + free(cmd_ret); + return 0; +} + +static void print_dqe_info(const void *reg_save, uint32_t reg_num) +{ + struct hisi_sas_dq_info *dqe = (struct hisi_sas_dq_info *)(reg_save); + + printf("The dqe dw0 information as below:\n"); + printf("abort_flag: %u\n", dqe->dw0.abort_flag); + printf("abort_devtype: %u\n", dqe->dw0.abort_devtype); + printf("Rsponse_report: %u\n", dqe->dw0.Rsponse_report); + printf("TLR_Ctrl: %u\n", dqe->dw0.TLR_Ctrl); + printf("Phy_ID: %u\n", dqe->dw0.Phy_ID); + printf("Force_Phy: %u\n", dqe->dw0.Force_Phy); + printf("PORT: 0x%llx\n", dqe->dw0.PORT); + printf("PRI: %u\n", dqe->dw0.PRI); + printf("CMD: %u\n", dqe->dw0.CMD); + + printf("The dqe dw1 information as below:\n"); + printf("Non_Busy_Constraint: %u\n", dqe->dw1.Non_Busy_Constraint); + printf("SSP_Pass_Through: %u\n", dqe->dw1.SSP_Pass_Through); + printf("DIR: %u\n", dqe->dw1.DIR); + printf("Reset: %u\n", dqe->dw1.Reset); + printf("PIR_Present: %u\n", dqe->dw1.PIR_Present); + printf("Enable_Transport_Layer_Retry: %u\n", dqe->dw1.Enable_Transport_Layer_Retry); + printf("Verify_Data_Transfer_Length: 0x%llx\n", dqe->dw1.Verify_Data_Transfer_Length); + printf("Frame_Type: %u\n", dqe->dw1.Frame_Type); + printf("Device_ID: %u\n", dqe->dw1.Device_ID); + + printf("The dqe dw2 information as below:\n"); + printf("Command_Frame_Length: %u\n", dqe->dw2.Command_Frame_Length); + printf("Leave_Affiliation_Open: %u\n", dqe->dw2.Leave_Affiliation_Open); + printf("Ncq_Tag: %u\n", dqe->dw2.Ncq_Tag); + printf("Max_Response_Frame_Length: %u\n", dqe->dw2.Max_Response_Frame_Length); + printf("Sg_Mode: %u\n", dqe->dw2.Sg_Mode); + printf("First_Burst: %u\n", dqe->dw2.First_Burst); + + printf("Initiator_Port_Transfer_Tag: %u\n", dqe->Initiator_Port_Transfer_Tag); + printf("Target_Port_Transfer_Tag: %u\n", dqe->Target_Port_Transfer_Tag); + printf("Data_Transfer_Length: %u\n", dqe->Data_Transfer_Length); + printf("First_Burst_Num: %u\n", dqe->First_Burst_Num); + printf("DIF_PRD_Table_Length: %u\n", dqe->DIF_PRD_Table_Length); + printf("PRD_Table_Length: %u\n", dqe->PRD_Table_Length); + + printf("The dqe dw7 information as below:\n"); + printf("Double_Mode: %u\n", dqe->dw7.Double_Mode); + printf("Abort_IPTT: %u\n", dqe->dw7.Abort_IPTT); +} + +int sas_dqe(const struct tool_sas_cmd *cmd) +{ + int ret; + uint32_t reg_num = 0; + uint32_t reg_save[RESP_MAX_NUM] = { 0 }; + + if (cmd == NULL) + return -ENOSPC; + + ret = sas_get_dqe(cmd, reg_save, ®_num); + if (ret) + return ret; + + if (reg_num == 0) { + printf("SAS dqe is failed\n"); + return -EINVAL; + } + print_dqe_info(reg_save, reg_num); + return 0; +} diff --git a/sas/sas_func/sas_read_dqe.h b/sas/sas_func/sas_read_dqe.h new file mode 100644 index 0000000..28c0592 --- /dev/null +++ b/sas/sas_func/sas_read_dqe.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022 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 __SAS_DQE_H_ +#define __SAS_DQE_H_ + +#include "sas_tools_include.h" + +struct sas_dqe_req_para { + uint32_t chip_id; + uint32_t die_id; + uint32_t que_id; + uint32_t dqe_id; +}; + +struct hikp_sas_dqe_dw0 { + uint32_t abort_flag : 2; + uint32_t abort_devtype : 1; + uint32_t Rsvd0 : 2; + uint32_t Rsponse_report : 1; + uint32_t TLR_Ctrl : 2; + uint32_t Phy_ID : 9; + uint32_t Force_Phy : 1; + uint32_t PORT : 4; + uint32_t Rsvd1 : 5; + uint32_t PRI : 1; + uint32_t Rsvd5 : 1; + uint32_t CMD : 3; +}; + +struct hikp_sas_dqe_dw1 { + uint32_t Rsvd2 : 3; + uint32_t Non_Busy_Constraint : 1; + uint32_t SSP_Pass_Through : 1; + uint32_t DIR : 2; + uint32_t Reset : 1; + uint32_t PIR_Present : 1; + uint32_t Enable_Transport_Layer_Retry : 1; + uint32_t Verify_Data_Transfer_Length : 1; + uint32_t Frame_Type : 5; + uint32_t Device_ID : 16; +}; + +struct hikp_sas_dqe_dw2 { + uint32_t Command_Frame_Length : 9; + uint32_t Leave_Affiliation_Open : 1; + uint32_t Ncq_Tag : 5; + uint32_t Max_Response_Frame_Length : 9; + uint32_t Sg_Mode : 2; + uint32_t First_Burst : 1; + uint32_t Rsvd3 : 5; +}; + +struct hikp_sas_dqe_dw7 { + uint32_t Rsvd4 : 15; + uint32_t Double_Mode : 1; + uint32_t Abort_IPTT : 16; +}; + +struct hisi_sas_dq_info { + struct hikp_sas_dqe_dw0 dw0; + struct hikp_sas_dqe_dw1 dw1; + struct hikp_sas_dqe_dw2 dw2; + uint32_t Initiator_Port_Transfer_Tag : 16; + uint32_t Target_Port_Transfer_Tag : 16; + uint32_t Data_Transfer_Length; + uint32_t First_Burst_Num; + uint32_t DIF_PRD_Table_Length : 16; + uint32_t PRD_Table_Length : 16; + struct hikp_sas_dqe_dw7 dw7; +}; + +int sas_dqe(const struct tool_sas_cmd *cmd); + +#endif diff --git a/sas/sas_func/sas_read_errcode.c b/sas/sas_func/sas_read_errcode.c new file mode 100644 index 0000000..4f89bda --- /dev/null +++ b/sas/sas_func/sas_read_errcode.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "sas_common.h" +#include "sas_read_errcode.h" + +static int sas_get_errcode(const struct tool_sas_cmd *cmd, uint32_t *reg_save, uint32_t *reg_num) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct sas_errcode_req_para req_data = { 0 }; + + req_data.chip_id = cmd->chip_id; + req_data.die_id = cmd->die_id; + + hikp_cmd_init(&req_header, SAS_MOD, SAS_ERRCODE, cmd->sas_cmd_type); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL) { + printf("sas_errcode excutes hikp_cmd_alloc err\n"); + return -EINVAL; + } + *reg_num = cmd_ret->rsp_data_num; + for (int i = 0; i < *reg_num; i++) + reg_save[i] = cmd_ret->rsp_data[i]; + + free(cmd_ret); + return 0; +} + +static void sas_print_errcode(uint32_t cmd_type, const uint32_t *reg_save, uint32_t reg_num) +{ + uint32_t i; + const char *errcode_type[] = { + "", + "DWS_LOST", + "RESET_PROB", + "CRC_FAIL", + "OPEN_REJ" + }; + + if (reg_num == 0) { + printf("SAS error code read is failed\n"); + return; + } + if (cmd_type == ERRCODE_ALL) { + printf(" DWS_LOST RESET_PROB CRC_FAIL OPEN_REJ\n"); + for (i = 0; i < reg_num; i += SAS_ERR_NUM) { + printf("phy%u 0x%08x 0x%08x 0x%08x 0x%08x\n", i / SAS_ERR_NUM, + reg_save[i + DWS_LOST], reg_save[i + RESET_PROB], + reg_save[i + CRC_FAIL], reg_save[i + OPEN_REJ]); + } + } else { + printf(" %s\n", errcode_type[cmd_type]); + for (i = 0; i < reg_num; i++) + printf("phy%u 0x%08x\n", i, reg_save[i]); + } +} + +int sas_errcode_read(struct tool_sas_cmd *cmd) +{ + int ret; + uint32_t reg_num = 0; + uint32_t reg_save[RESP_MAX_NUM] = { 0 }; + + if (cmd == NULL) + return -ENOSPC; + + ret = sas_get_errcode(cmd, reg_save, ®_num); + if (ret) + return ret; + + sas_print_errcode(cmd->sas_cmd_type, reg_save, reg_num); + + return 0; +} diff --git a/sas/sas_func/sas_read_errcode.h b/sas/sas_func/sas_read_errcode.h new file mode 100644 index 0000000..c597c16 --- /dev/null +++ b/sas/sas_func/sas_read_errcode.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 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 __SAS_ERRCODE_REG_H_ +#define __SAS_ERRCODE_REG_H_ + +#include "sas_tools_include.h" + +struct sas_errcode_req_para { + uint32_t chip_id; + uint32_t die_id; +}; + +int sas_errcode_read(struct tool_sas_cmd *cmd); + +#endif diff --git a/sas/user_cmd/cmd_code/sas_cmd_anacq.c b/sas/user_cmd/cmd_code/sas_cmd_anacq.c new file mode 100644 index 0000000..46bf5aa --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_anacq.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sas_common.h" +#include "sas_tools_include.h" +#include "sas_analy_queue.h" + +static int sas_anacq_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-p", "--pointer", "dispaly cq queue read/write pointer\n"); + printf(" %s, %-25s %s\n", "-s", "--number", "dispaly cq number\n"); + printf("\n"); + + return 0; +} + +static int sas_anacq_prt(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_cmd_type(ANACQ_PRT); +} + +static int sas_anacq_num(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_cmd_type(ANACQ_NUM); +} + +static int sas_anacq_excute_funs_call(uint32_t cmd_type) +{ + if (cmd_type != SAS_UNKNOW_CMD) + return sas_analy_cmd(sas_get_cmd_p()); + + return -1; +} + +static void sas_anacq_execute(struct major_cmd_ctrl *self) +{ + int ret, cmd; + const char *suc_msg[] = { + "", + "", + "", + "sas_analy_cq_prt success.", + "sas_analy_cq_num success.", + }; + const char *err_msg[] = { + "", + "", + "", + "sas_analy_cq_prt error.", + "sas_analy_cq_num error.", + "sas_analy_cq failed, unknown type", + }; + + cmd = sas_get_cmd_type(); + ret = sas_anacq_excute_funs_call(cmd); + (void)sas_set_cmd_type(SAS_UNKNOW_CMD); + if (ret == 0) { + printf("%s\n", suc_msg[cmd]); + } else { + if (cmd == SAS_UNKNOW_CMD) + cmd = ANACQ_UNKNOWN_TYPE; + snprintf(self->err_str, sizeof(self->err_str), "%s\n", err_msg[cmd]); + self->err_no = ret; + } +} + +static void cmd_sas_anacq_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sas_anacq_execute; + + cmd_option_register("-c", "--chipid", true, sas_set_chip_id); + cmd_option_register("-d", "--dieid", true, sas_set_die_id); + cmd_option_register("-h", "--help", false, sas_anacq_help); + cmd_option_register("-p", "--pointer", false, sas_anacq_prt); + cmd_option_register("-s", "--number", false, sas_anacq_num); +} + +HIKP_CMD_DECLARE("sas_anacq", "sas analysis cq queue ", cmd_sas_anacq_init); diff --git a/sas/user_cmd/cmd_code/sas_cmd_anadq.c b/sas/user_cmd/cmd_code/sas_cmd_anadq.c new file mode 100644 index 0000000..e1b68b6 --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_anadq.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sas_common.h" +#include "sas_tools_include.h" +#include "sas_analy_queue.h" + +static int sas_anadq_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-p", "--pointer", "dispaly dq queue read/write pointer\n"); + printf(" %s, %-25s %s\n", "-s", "--number", "dispaly dq number\n"); + printf("\n"); + + return 0; +} + +static int sas_anadq_prt(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_cmd_type(ANADQ_PRT); +} + +static int sas_anadq_num(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_cmd_type(ANADQ_NUM); +} + +static int sas_anadq_excute_funs_call(uint32_t cmd_type) +{ + if (cmd_type != SAS_UNKNOW_CMD) + return sas_analy_cmd(sas_get_cmd_p()); + + return -1; +} + +static void sas_anadq_execute(struct major_cmd_ctrl *self) +{ + int ret, cmd; + const char *suc_msg[] = { + "sas_analy_dq_prt success.", + "sas_analy_dq_num success.", + }; + const char *err_msg[] = { + "sas_analy_dq_prt error.", + "sas_analy_dq_num error.", + "sas_analy_dq failed, unknown type", + }; + + cmd = sas_get_cmd_type(); + ret = sas_anadq_excute_funs_call(cmd); + (void)sas_set_cmd_type(SAS_UNKNOW_CMD); + if (ret == 0) { + printf("%s\n", suc_msg[cmd]); + } else { + if (cmd == SAS_UNKNOW_CMD) + cmd = ANADQ_UNKNOWN_TYPE; + snprintf(self->err_str, sizeof(self->err_str), "%s\n", err_msg[cmd]); + self->err_no = ret; + } +} + +static void cmd_sas_anadq_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sas_anadq_execute; + + cmd_option_register("-c", "--chipid", true, sas_set_chip_id); + cmd_option_register("-d", "--dieid", true, sas_set_die_id); + cmd_option_register("-h", "--help", false, sas_anadq_help); + cmd_option_register("-p", "--pointer", false, sas_anadq_prt); + cmd_option_register("-s", "--number", false, sas_anadq_num); +} + +HIKP_CMD_DECLARE("sas_anadq", "sas analysis dq queue ", cmd_sas_anadq_init); diff --git a/sas/user_cmd/cmd_code/sas_cmd_common.c b/sas/user_cmd/cmd_code/sas_cmd_common.c new file mode 100644 index 0000000..cca4084 --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_common.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022 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 "sas_tools_include.h" + +static struct tool_sas_cmd g_sas_cmd = { + .sas_cmd_type = SAS_UNKNOW_CMD, + .chip_id = (uint32_t)(-1), + .phy_id = (uint32_t)(-1), + .die_id = (uint32_t)(-1), + .dev_id = (uint32_t)(-1), + .que_id = (uint32_t)(-1), + .dqe_id = (uint32_t)(-1), +}; + +int sas_set_id(struct major_cmd_ctrl *self, const char *argv, uint32_t *id) +{ + int ret; + uint32_t val = 0; + + ret = string_toui(argv, &val); + if (ret) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid id."); + self->err_no = ret; + return ret; + } + *id = val; + return ret; +} + +int sas_set_cmd_type(int cmd_type) +{ + g_sas_cmd.sas_cmd_type = cmd_type; + return 0; +} + +struct tool_sas_cmd *sas_get_cmd_p(void) +{ + return &g_sas_cmd; +} + +int sas_get_phy_id(void) +{ + return g_sas_cmd.phy_id; +} + +int sas_get_dev_id(void) +{ + return g_sas_cmd.dev_id; +} + +int sas_get_que_id(void) +{ + return g_sas_cmd.que_id; +} + +int sas_get_cmd_type(void) +{ + return g_sas_cmd.sas_cmd_type; +} + +int sas_set_chip_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_id(self, argv, &g_sas_cmd.chip_id); +} + +int sas_set_phy_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_id(self, argv, &g_sas_cmd.phy_id); +} + +int sas_set_die_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_id(self, argv, &g_sas_cmd.die_id); +} + +int sas_set_dev_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_id(self, argv, &g_sas_cmd.dev_id); +} + +int sas_set_que_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_id(self, argv, &g_sas_cmd.que_id); +} + +int sas_set_dqe_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_id(self, argv, &g_sas_cmd.dqe_id); +} diff --git a/sas/user_cmd/cmd_code/sas_cmd_dev.c b/sas/user_cmd/cmd_code/sas_cmd_dev.c new file mode 100644 index 0000000..c95006b --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_dev.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sas_common.h" +#include "sas_tools_include.h" +#include "sas_read_dev.h" + +static int sas_dev_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-l", "--link", "dispaly device type and speed\n"); + printf(" %s, %-25s %s\n", "-i", "--info", "dispaly the device detail information\n"); + printf("\n"); + + return 0; +} + +static int sas_dev_link(struct major_cmd_ctrl *self, const char *argv) +{ + return sas_set_cmd_type(DEV_LINK); +} + +static int sas_dev_info(struct major_cmd_ctrl *self, const char *argv) +{ + int ret; + + (void)sas_set_cmd_type(DEV_INFO); + ret = sas_set_dev_id(self, argv); + if (ret || sas_get_dev_id() >= MAX_DEVICE_NUM) { + printf("device id is too large(>=%d)\n", MAX_DEVICE_NUM); + return -EINVAL; + } + return ret; +} + +static int sas_dev_excute_funs_call(uint32_t cmd_type) +{ + if (cmd_type != SAS_UNKNOW_CMD) + return sas_dev(sas_get_cmd_p()); + + return -EINVAL; +} + +static void sas_dev_execute(struct major_cmd_ctrl *self) +{ + int ret, cmd; + const char *suc_msg[] = { + "sas_dev_link success.", + "sas_dev_info success.", + }; + const char *err_msg[] = { + "sas_dev_link error.", + "sas_dev_info error.", + "sas_dev failed, unknown type", + }; + + cmd = sas_get_cmd_type(); + ret = sas_dev_excute_funs_call(cmd); + (void)sas_set_cmd_type(SAS_UNKNOW_CMD); + if (ret == 0) { + printf("%s\n", suc_msg[cmd]); + } else { + if (cmd == SAS_UNKNOW_CMD) + cmd = DEV_UNKNOWN_TYPE; + snprintf(self->err_str, sizeof(self->err_str), "%s\n", err_msg[cmd]); + self->err_no = ret; + } +} + +static void cmd_sas_dev_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sas_dev_execute; + + cmd_option_register("-c", "--chipid", true, sas_set_chip_id); + cmd_option_register("-d", "--dieid", true, sas_set_die_id); + cmd_option_register("-h", "--help", false, sas_dev_help); + cmd_option_register("-l", "--link", false, sas_dev_link); + cmd_option_register("-i", "--info", true, sas_dev_info); +} + +HIKP_CMD_DECLARE("sas_dev", "sas device information ", cmd_sas_dev_init); diff --git a/sas/user_cmd/cmd_code/sas_cmd_dqe.c b/sas/user_cmd/cmd_code/sas_cmd_dqe.c new file mode 100644 index 0000000..4a9547a --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_dqe.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sas_common.h" +#include "sas_tools_include.h" +#include "sas_read_dqe.h" + +static int sas_dqe_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf(" %s, %-25s %s\n", "-q", "--queue", "please input queue id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-i", "--info", "dispaly the dqe detail information\n"); + printf("\n"); + + return 0; +} + +static int sas_dqe_info(struct major_cmd_ctrl *self, const char *argv) +{ + int ret; + + (void)sas_set_cmd_type(DQE_INFO); + ret = sas_set_dqe_id(self, argv); + return ret; +} + +static int sas_set_queue_id(struct major_cmd_ctrl *self, const char *argv) +{ + int ret; + uint32_t val = 0; + + ret = sas_set_que_id(self, argv); + if (ret || sas_get_que_id() >= SAS_QUEUE_NUM) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid queue id."); + self->err_no = ret; + return -EINVAL; + } + + return 0; +} + +static int sas_dqe_excute_funs_call(uint32_t cmd_type) +{ + if ((cmd_type != SAS_UNKNOW_CMD) && (sas_get_que_id() != (uint32_t)(-1))) + return sas_dqe(sas_get_cmd_p()); + + return -EINVAL; +} + +static void sas_dqe_execute(struct major_cmd_ctrl *self) +{ + int ret, cmd; + const char *suc_msg[] = { + "sas_dqe_info success.", + }; + const char *err_msg[] = { + "sas_dqe_info error.", + "sas_dqe failed, unknown type", + }; + + cmd = sas_get_cmd_type(); + ret = sas_dqe_excute_funs_call(cmd); + (void)sas_set_cmd_type(SAS_UNKNOW_CMD); + if (ret == 0) { + printf("%s\n", suc_msg[cmd]); + } else { + if (cmd == SAS_UNKNOW_CMD) + cmd = DQE_UNKNOWN_TYPE; + snprintf(self->err_str, sizeof(self->err_str), "%s\n", err_msg[cmd]); + self->err_no = ret; + } +} + +static void cmd_sas_dqe_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sas_dqe_execute; + + cmd_option_register("-c", "--chipid", true, sas_set_chip_id); + cmd_option_register("-d", "--dieid", true, sas_set_die_id); + cmd_option_register("-h", "--help", false, sas_dqe_help); + cmd_option_register("-q", "--queue", true, sas_set_queue_id); + cmd_option_register("-i", "--info", true, sas_dqe_info); +} + +HIKP_CMD_DECLARE("sas_dqe", "sas dqe information ", cmd_sas_dqe_init); diff --git a/sas/user_cmd/cmd_code/sas_cmd_dump.c b/sas/user_cmd/cmd_code/sas_cmd_dump.c new file mode 100644 index 0000000..4f2cfea --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_dump.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sas_common.h" +#include "sas_tools_include.h" +#include "sas_dump_reg.h" + +static int sas_dump_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-p", "--phyx", "set phy num(0-7) to dump reg\n"); + printf(" %s, %-25s %s\n", "-g", "--global", "dump global dfx reg\n"); + printf(" %s, %-25s %s\n", "-b", "--axi", "dump axi master reg\n"); + printf("\n"); + + return 0; +} + +static int sas_dump_global(struct major_cmd_ctrl *self, const char *argv) +{ + (void)sas_set_cmd_type(DUMP_GLOBAL); + return 0; +} + +static int sas_dump_phyx(struct major_cmd_ctrl *self, char const *argv) +{ + int ret; + uint32_t val = 0; + + (void)sas_set_cmd_type(DUMP_PHYX); + ret = sas_set_phy_id(self, argv); + if (ret || sas_get_phy_id() > SAS_MAX_PHY_NUM) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid phyid."); + self->err_no = ret; + return -EINVAL; + } + + return 0; +} + +static int sas_dump_axi(struct major_cmd_ctrl *self, char const *argv) +{ + (void)sas_set_cmd_type(DUMP_AXI); + return 0; +} + +static int sas_dump_excute_funs_call(uint32_t cmd_type) +{ + if (cmd_type != SAS_UNKNOW_CMD) + return sas_reg_dump(sas_get_cmd_p()); + + return -1; +} + +static void sas_dump_execute(struct major_cmd_ctrl *self) +{ + int ret, cmd; + const char *suc_msg[] = { + "sas_dump_global success.", + "sas_dump_phy success.", + "sas_dump_axi success." + }; + const char *err_msg[] = { + "sas_dump_global error.", + "sas_dump_phy error.", + "sas_dump_axi error.", + "sas_dump failed, unknown type", + }; + + cmd = sas_get_cmd_type(); + ret = sas_dump_excute_funs_call(cmd); + (void)sas_set_cmd_type(SAS_UNKNOW_CMD); + if (ret == 0) { + printf("%s\n", suc_msg[cmd]); + } else { + if (cmd == SAS_UNKNOW_CMD) + cmd = DUMP_UNKNOWN_TYPE; + snprintf(self->err_str, sizeof(self->err_str), "%s\n", err_msg[cmd]); + self->err_no = ret; + } +} + +static void cmd_sas_dump_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sas_dump_execute; + + cmd_option_register("-c", "--chipid", true, sas_set_chip_id); + cmd_option_register("-d", "--dieid", true, sas_set_die_id); + cmd_option_register("-h", "--help", false, sas_dump_help); + cmd_option_register("-g", "--global", false, sas_dump_global); + cmd_option_register("-p", "--phyx", true, sas_dump_phyx); + cmd_option_register("-b", "--axi", false, sas_dump_axi); +} + +HIKP_CMD_DECLARE("sas_dump", "sas reg dump", cmd_sas_dump_init); diff --git a/sas/user_cmd/cmd_code/sas_cmd_errcode.c b/sas/user_cmd/cmd_code/sas_cmd_errcode.c new file mode 100644 index 0000000..eb3c5e6 --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_cmd_errcode.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sas_common.h" +#include "sas_tools_include.h" +#include "sas_read_errcode.h" + +static int sas_errcode_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-t", "--type", "read error code of 8 phys\n"); + printf("\n"); + + return 0; +} + +static int sas_errcode_one(struct major_cmd_ctrl *self, char const *argv) +{ + int ret; + uint32_t val = 0; + + ret = string_toui(argv, &val); + if (ret || val >= SAS_MAX_ERR_NUM) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid error code type."); + self->err_no = ret; + return -EINVAL; + } + + (void)sas_set_cmd_type(val); + return 0; +} + +static int sas_errcode_excute_funs_call(uint32_t cmd_type) +{ + if (cmd_type != SAS_UNKNOW_CMD) + return sas_errcode_read(sas_get_cmd_p()); + + return -EINVAL; +} + +static void sas_errcode_execute(struct major_cmd_ctrl *self) +{ + int ret, cmd; + const char *suc_msg[] = { + "sas_errcode_all success.", + "sas_errcode_dws_lost success.", + "sas_errcode_reset_prob success.", + "sas_errcode_crc_fail success.", + "sas_errcode_open_rej success.", + }; + const char *err_msg[] = { + "sas_errcode_all error.", + "sas_errcode_dws_lost error.", + "sas_errcode_reset_prob error.", + "sas_errcode_crc_fail error.", + "sas_errcode_open_rej error.", + "sas_errcode failed, unknown type", + }; + + cmd = sas_get_cmd_type(); + ret = sas_errcode_excute_funs_call(cmd); + (void)sas_set_cmd_type(SAS_UNKNOW_CMD); + if (ret == 0) { + printf("%s\n", suc_msg[cmd]); + } else { + if (cmd == SAS_UNKNOW_CMD) + cmd = ERRCODE_UNKNOWN_TYPE; + snprintf(self->err_str, sizeof(self->err_str), "%s\n", err_msg[cmd]); + self->err_no = ret; + } +} + +static void cmd_sas_errcode_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sas_errcode_execute; + + cmd_option_register("-h", "--help", false, sas_errcode_help); + cmd_option_register("-c", "--chipid", true, sas_set_chip_id); + cmd_option_register("-d", "--dieid", true, sas_set_die_id); + cmd_option_register("-t", "--type", true, sas_errcode_one); +} + +HIKP_CMD_DECLARE("sas_errcode", "sas read error code", cmd_sas_errcode_init); diff --git a/sas/user_cmd/cmd_code/sas_tools_include.h b/sas/user_cmd/cmd_code/sas_tools_include.h new file mode 100644 index 0000000..a71e614 --- /dev/null +++ b/sas/user_cmd/cmd_code/sas_tools_include.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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 __SAS_TOOLS_INCLUDE_H_ +#define __SAS_TOOLS_INCLUDE_H_ + +#include "hikptdev_plug.h" +#include "tool_lib.h" +#include "tool_cmd.h" + +#define MAX_PARA_LENTH 10 +#define SAS_UNKNOW_CMD 0xff + +struct tool_sas_cmd { + uint32_t sas_cmd_type; + uint32_t chip_id; + uint32_t phy_id; + uint32_t die_id; + uint32_t dev_id; + uint32_t que_id; + uint32_t dqe_id; +}; + +int sas_set_cmd_type(int cmd_type); +int sas_get_cmd_type(void); +int sas_get_phy_id(void); +int sas_get_dev_id(void); +int sas_get_que_id(void); +struct tool_sas_cmd *sas_get_cmd_p(void); +int sas_set_chip_id(struct major_cmd_ctrl *self, const char *argv); +int sas_set_phy_id(struct major_cmd_ctrl *self, const char *argv); +int sas_set_die_id(struct major_cmd_ctrl *self, const char *argv); +int sas_set_dev_id(struct major_cmd_ctrl *self, const char *argv); +int sas_set_que_id(struct major_cmd_ctrl *self, const char *argv); +int sas_set_dqe_id(struct major_cmd_ctrl *self, const char *argv); + +#endif -- Gitee From 49b35e3b5e2b17095c23f23fe4f1597169342d39 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 15:02:53 +0800 Subject: [PATCH 04/14] support querying NIC_MAC module information including port link, port optical module information, and key registers dump function Signed-off-by: veega2022 (cherry picked from commit 67b0f3a69a571a76be4cb613fe5fe46d513c94f0) --- CMakeLists.txt | 1 + net/hikp_net_lib.c | 382 +++++++++++++++++++++ net/hikp_net_lib.h | 121 +++++++ net/nic/nic_mac/hikp_mac_cmd.h | 62 ++++ net/nic/nic_mac/hikp_nic_mac_dump.c | 252 ++++++++++++++ net/nic/nic_mac/hikp_nic_mac_dump.h | 63 ++++ net/nic/nic_mac/hikp_nic_port.c | 491 +++++++++++++++++++++++++++ net/nic/nic_mac/hikp_nic_port.h | 201 +++++++++++ net/nic/nic_mac/hikp_nic_xsfp.c | 495 ++++++++++++++++++++++++++++ net/nic/nic_mac/hikp_nic_xsfp.h | 393 ++++++++++++++++++++++ 10 files changed, 2461 insertions(+) create mode 100644 net/hikp_net_lib.c create mode 100644 net/hikp_net_lib.h create mode 100644 net/nic/nic_mac/hikp_mac_cmd.h create mode 100644 net/nic/nic_mac/hikp_nic_mac_dump.c create mode 100644 net/nic/nic_mac/hikp_nic_mac_dump.h create mode 100644 net/nic/nic_mac/hikp_nic_port.c create mode 100644 net/nic/nic_mac/hikp_nic_port.h create mode 100644 net/nic/nic_mac/hikp_nic_xsfp.c create mode 100644 net/nic/nic_mac/hikp_nic_xsfp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c1389f6..3cb2944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ macro(get_header_dir_recurse HEADER_DIR_LIST) endmacro() file(GLOB_RECURSE HIKPTOOL_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/net/*.c ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c diff --git a/net/hikp_net_lib.c b/net/hikp_net_lib.c new file mode 100644 index 0000000..eba086e --- /dev/null +++ b/net/hikp_net_lib.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2022 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 "hikp_net_lib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tool_lib.h" +#include "hikptdev_plug.h" + +static int hikp_read_net_pci_info(const char *file_path, uint32_t len, char *content) +{ + char path[PATH_MAX + 1] = { 0 }; + int ret; + int fd; + + if (file_path == NULL || content == NULL) + return -EINVAL; + + if (len > MAX_PCI_ID_LEN) + return -EINVAL; + + if (strlen(file_path) > PATH_MAX || realpath(file_path, path) == NULL) + return -ENOENT; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -EPERM; + + ret = pread(fd, content, len, 0); + if (ret < 0) { + close(fd); + return -EIO; + } + content[len] = '\0'; // The invoker ensures that the bounds are not crossed. + close(fd); + + return 0; +} + +int hikp_net_creat_sock(void) +{ + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (sockfd < MIN_SOCKFD) { + if (sockfd >= 0) + close(sockfd); + sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); + } + if (sockfd < 0) { + HIKP_ERROR_PRINT("cannot get control socket.\n"); + return -EIO; + } + if (sockfd < MIN_SOCKFD) { + HIKP_ERROR_PRINT("sockfd invalid\n"); + close(sockfd); + return -EINVAL; + } + return sockfd; +} + +static void fill_bdf_id(struct bdf_t *bdf, uint8_t bus, uint8_t dev, uint8_t func) +{ + bdf->bus_id = bus; + bdf->dev_id = dev; + bdf->fun_id = func; +} + +static bool check_and_parse_domain_bdf_id(const char *bus_info, struct bdf_t *bdf) +{ + char remains[IFNAMSIZ + 1] = {0}; + uint32_t domain = 0; + uint32_t bus = 0; + uint32_t dev = 0; + uint32_t fun = 0; + int retval; + + if (strlen(bus_info) >= IFNAMSIZ) + return false; + + /* pci_id: 0000:bd:00.0 ==> doman:bus:device.function add + * remains here to solve such input: 0000:bd:00.0abcdef + */ + retval = sscanf(bus_info, "%x:%x:%x.%u%s", &domain, &bus, &dev, &fun, remains); + if ((retval == PCI_ID_FOUR_NUMS) && (bus != 0) && !(domain & ~PCI_DOMAIN_MASK) && + !(dev & ~PCI_DEV_ID_MASK) && !(fun & ~PCI_FUNC_ID_MASK)) { + bdf->domain = domain; + fill_bdf_id(bdf, (uint8_t)bus, (uint8_t)dev, (uint8_t)fun); + return true; + } + + return false; +} + +static bool check_and_parse_simple_bdf_id(const char *bus_info, struct bdf_t *bdf) +{ + char remains[IFNAMSIZ + 1] = {0}; + uint32_t bus = 0; + uint32_t dev = 0; + uint32_t fun = 0; + int retval; + + if (strlen(bus_info) >= IFNAMSIZ) + return false; + + /* pci_id: bd:00.0 ==> bus:device.function */ + retval = sscanf(bus_info, "%x:%x.%u%s", &bus, &dev, &fun, remains); + if ((retval == PCI_ID_THREE_NUMS) && + (bus != 0) && !(dev & ~PCI_DEV_ID_MASK) && !(fun & ~PCI_FUNC_ID_MASK)) { + bdf->domain = 0; + fill_bdf_id(bdf, (uint8_t)bus, (uint8_t)dev, (uint8_t)fun); + return true; + } + + return false; +} + +static bool check_dev_name_and_get_bdf(int sockfd, struct tool_target *target) +{ + struct ethtool_drvinfo drvinfo = { 0 }; + struct ifreq ifr = { 0 }; + + ifr.ifr_data = (char *)&drvinfo; + drvinfo.cmd = ETHTOOL_GDRVINFO; + + strncpy(ifr.ifr_name, target->dev_name, IFNAMSIZ - 1); + + if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0) + return false; + + if (!check_and_parse_domain_bdf_id(drvinfo.bus_info, &(target->bdf))) + return false; + + if (strncmp(drvinfo.driver, HNS3_DRIVER_NAME, sizeof(HNS3_DRIVER_NAME)) != 0) + return false; + + return true; +} + +static bool interface_is_bdf_id(const char *dev_name, struct tool_target *target) +{ + bool ret; + + ret = check_and_parse_domain_bdf_id(dev_name, &(target->bdf)); + if (ret) + return true; + + return check_and_parse_simple_bdf_id(dev_name, &(target->bdf)); +} + +static int tool_get_bdf_by_dev_name(const char *name, struct tool_target *target) +{ + int sockfd; + + if (strlen(name) >= IFNAMSIZ) { + HIKP_ERROR_PRINT("parameter of target name is too long.\n"); + return -EINVAL; + } + strncpy(target->dev_name, name, sizeof(target->dev_name)); + target->dev_name[sizeof(target->dev_name) - 1] = '\0'; + + sockfd = hikp_net_creat_sock(); + if (sockfd < 0) + return sockfd; + + if (!check_dev_name_and_get_bdf(sockfd, target)) { + HIKP_ERROR_PRINT("device name error or unsupported.\n"); + close(sockfd); + return -EINVAL; + } + close(sockfd); + + return 0; +} + +int tool_check_and_get_valid_bdf_id(const char *name, struct tool_target *target) +{ + if (!name || !target) + return 0; + + if (interface_is_bdf_id(name, target)) + return 0; + + return tool_get_bdf_by_dev_name(name, target); +} + +bool is_dev_valid_and_special(int sockfd, struct tool_target *target) +{ + if (!check_dev_name_and_get_bdf(sockfd, target)) + return false; + + /* if device id is zero, we can assume that it is special. */ + if (target->bdf.dev_id != 0) + return false; + + return true; +} + +int get_revision_id_by_bdf(const struct bdf_t *bdf, char *revision_id) +{ + char revision_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + int ret; + + ret = snprintf(revision_dir, sizeof(revision_dir), "%s%04x:%02x:%02x.%u%s", + HIKP_BUS_PCI_DEV_DIR, bdf->domain, bdf->bus_id, bdf->dev_id, + bdf->fun_id, HIKP_PCI_REVISION_DIR); + if (ret < 0) { + HIKP_ERROR_PRINT("get revision dir fail.\n"); + return -EIO; + } + ret = hikp_read_net_pci_info((const char *)revision_dir, MAX_PCI_ID_LEN, revision_id); + if (ret != 0) + return ret; + + return 0; +} + +static int hikp_get_dir_name_of_device(const char *path, uint32_t len, char *dir_name) +{ + struct dirent *ptr; + DIR *dir = NULL; + + if (len > PCI_MAX_DIR_NAME_LEN) + return -EINVAL; + + dir = opendir(path); + if (dir == NULL) { + HIKP_ERROR_PRINT("read path %s fail.\n", path); + return -EINVAL; + } + + while ((ptr = readdir(dir)) != NULL) { + if (ptr->d_name[0] == '.') + continue; + + if (strlen(ptr->d_name) >= len) { + HIKP_ERROR_PRINT("parameter of directory name is too long.\n"); + closedir(dir); + return -EINVAL; + } + strncpy(dir_name, ptr->d_name, len); + dir_name[len - 1] = '\0'; + break; + } + + return closedir(dir); +} + +int get_dev_name_by_bdf(const struct bdf_t *bdf, char *dev_name) +{ + char dev_name_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + int ret; + + if (!dev_name || !bdf) + return -EINVAL; + + /* if dev_name already has a value, we do not need to obtain it. */ + if (dev_name[0] != 0) + return 0; + + ret = snprintf(dev_name_dir, sizeof(dev_name_dir), "%s%04x:%02x:%02x.%u%s", + HIKP_BUS_PCI_DEV_DIR, bdf->domain, bdf->bus_id, bdf->dev_id, + bdf->fun_id, HIKP_NET_PATH); + if (ret < 0) { + HIKP_ERROR_PRINT("get dev_name dir fail.\n"); + return -EIO; + } + if (!is_dir_exist(dev_name_dir)) + return -ENOENT; + + return hikp_get_dir_name_of_device(dev_name_dir, IFNAMSIZ, dev_name); +} + +int get_vf_dev_info_by_pf_dev_name(const char *pf_dev_name, + struct tool_target *vf_target, uint8_t vf_id) +{ + char dev_name_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + int ret; + + if (!pf_dev_name || !vf_target) + return -EINVAL; + + ret = snprintf(dev_name_dir, sizeof(dev_name_dir), "%s%s%s%u%s", HIKP_NET_DEV_PATH, + pf_dev_name, HIKP_VIRTFN_PATH, vf_id, HIKP_NET_PATH); + if (ret < 0 || ret >= sizeof(dev_name_dir)) { + HIKP_ERROR_PRINT("get vf dev_name dir fail.\n"); + return -EIO; + } + if (!is_dir_exist(dev_name_dir)) + return -ENOENT; + + ret = hikp_get_dir_name_of_device(dev_name_dir, IFNAMSIZ, vf_target->dev_name); + if (ret != 0) + return ret; + + return tool_get_bdf_by_dev_name(vf_target->dev_name, vf_target); +} + +int get_pf_dev_info_by_vf_dev_name(const char *vf_dev_name, struct tool_target *pf_target) +{ + char dev_name_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + int ret; + + if (!vf_dev_name || !pf_target) + return -EINVAL; + + ret = snprintf(dev_name_dir, sizeof(dev_name_dir), "%s%s%s", HIKP_NET_DEV_PATH, + vf_dev_name, HIKP_PHYSFN_PATH); + if (ret < 0 || ret >= sizeof(dev_name_dir)) { + HIKP_ERROR_PRINT("get vf dev_name dir fail.\n"); + return -EIO; + } + if (!is_dir_exist(dev_name_dir)) + return -ENOENT; + + ret = hikp_get_dir_name_of_device(dev_name_dir, IFNAMSIZ, pf_target->dev_name); + if (ret != 0) + return ret; + + return tool_get_bdf_by_dev_name(pf_target->dev_name, pf_target); +} + +int get_numvfs_by_bdf(const struct bdf_t *bdf, uint8_t *numvfs) +{ +#define MAX_STR_LEN_OF_NUMVFS 8 + char numvfs_dir[MAX_BUS_PCI_DIR_LEN] = { 0 }; + char numvf[MAX_STR_LEN_OF_NUMVFS] = { 0 }; + int ret; + + if (!bdf || !numvfs) + return -EINVAL; + + ret = snprintf(numvfs_dir, sizeof(numvfs_dir), "%s%04x:%02x:%02x.%u%s", + HIKP_BUS_PCI_DEV_DIR, bdf->domain, bdf->bus_id, bdf->dev_id, + bdf->fun_id, HIKP_SRIOV_NUMVFS_PATH); + if (ret < 0) { + HIKP_ERROR_PRINT("get numvfs dir fail.\n"); + return -EIO; + } + ret = hikp_read_net_pci_info((const char *)numvfs_dir, MAX_PCI_ID_LEN, numvf); + if (ret != 0) + return ret; + + ret = (int)strtol(numvf, NULL, 0); + if ((ret > UCHAR_MAX) || (ret < 0)) { + HIKP_ERROR_PRINT("get numvfs by bdf fail.\n"); + return -EINVAL; + } + *numvfs = (uint8_t)ret; + + return 0; +} + +void hikp_ether_format_addr(char *buf, uint16_t size, const uint8_t *mac_addr) +{ + int len; + + if (buf == NULL || mac_addr == NULL) { + HIKP_WARN_PRINT("buf or mac_addr pointer is NULL.\n"); + return; + } + + len = snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], + mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + if (len < 0 || len >= size) + HIKP_WARN_PRINT("fail to get ether format addr.\n"); +} diff --git a/net/hikp_net_lib.h b/net/hikp_net_lib.h new file mode 100644 index 0000000..cc99d0c --- /dev/null +++ b/net/hikp_net_lib.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022 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_NET_LIB_H__ +#define __HIKP_NET_LIB_H__ + +#include "ossl_user_linux.h" +#include "tool_cmd.h" +#include "hikptdev_plug.h" + +struct bdf_t { + uint32_t domain; + /* bdf_id ===> fun_id: bit0~bit7, device_id: bit8~bit15, bus_id: bit16~bit23 */ + union { + uint32_t bdf_id; + struct { + uint8_t fun_id; + uint8_t dev_id; + uint8_t bus_id; + uint8_t rsv; + }; + }; +}; + +struct tool_target { + char dev_name[IFNAMSIZ]; /* *net device name* */ + struct bdf_t bdf; +}; + +#define NET_MAX_REQ_DATA_NUM 30 + +#define HNS3_DRIVER_NAME "hns3" + +#define HIKP_NET_DEV_PATH "/sys/class/net/" +#define HIKP_NET_PATH "/net/" +#define HIKP_SRIOV_NUMVFS_PATH "/sriov_numvfs" +#define HIKP_VIRTFN_PATH "/device/virtfn" +#define HIKP_PHYSFN_PATH "/device/physfn/net/" + +#define MAX_BUS_PCI_DIR_LEN 300 +#define MAX_PCI_ID_LEN 6 +#define HIKP_BUS_PCI_DEV_DIR "/sys/bus/pci/devices/" +#define HIKP_PCI_REVISION_DIR "/revision" + +#define PCI_MAX_DIR_NAME_LEN 30 + +#define PCI_ID_FOUR_NUMS 4 +#define PCI_ID_THREE_NUMS 3 + +#define PCI_BUS_ID_OFF 16 +#define PCI_DEV_ID_OFF 8 +#define PCI_FUNC_ID_OFF 0 + +#define PCI_DOMAIN_MASK 0xFFFF +#define PCI_BUS_ID_MASK 0xFF +#define PCI_DEV_ID_MASK 0x1F +#define PCI_FUNC_ID_MASK 0x7 + +#define MIN_SOCKFD 3 + +enum nic_cmd_type { + GET_CHIP_INFO_CMD = 0x1, + GET_FW_LOG_INFO_CMD, + GET_DFX_INFO_CMD, + GET_RSS_INFO_CMD, + GET_QOS_INFO_CMD, + GET_QUEUE_INFO_CMD, + GET_PPP_INFO_CMD, + GET_FD_INFO_CMD, + GET_FEC_INFO_CMD, + GET_GRO_INFO_CMD, +}; + +enum roh_cmd_type { + HIKP_ROH_MAC = 0x1, + HIKP_ROH_SHOW_MIB = 0x2, + HIKP_ROH_SHOW_BP = 0x3, +}; + +enum roce_cmd_type { + GET_ROCEE_MDB_CMD = 0x1, + GET_ROCEE_GMV_CMD, + GET_ROCEE_CAEP_CMD, + GET_ROCEE_PKT_CMD, + GET_ROCEE_SCC_CMD, + GET_ROCEE_QMM_CMD, + GET_ROCEE_TIMER_CMD, + GET_ROCEE_TRP_CMD, + GET_ROCEE_TSP_CMD, +}; + +#define HIKP_MAX_PF_NUM 8 +#define HIKP_NIC_MAX_FUNC_NUM 256 + +#define HIKP_NIC_MAX_TC_NUM 8 +#define HIKP_NIC_MAX_USER_PRIO_NUM 8 + +#define HIKP_NIC_ETH_MAC_ADDR_LEN 6 +#define HIKP_NIC_ETH_ADDR_FMT_SIZE 18 + +int hikp_net_creat_sock(void); +int tool_check_and_get_valid_bdf_id(const char *name, struct tool_target *target); +bool is_dev_valid_and_special(int sockfd, struct tool_target *target); +int get_revision_id_by_bdf(const struct bdf_t *bdf, char *revision_id); +int get_dev_name_by_bdf(const struct bdf_t *bdf, char *dev_name); +int get_numvfs_by_bdf(const struct bdf_t *bdf, uint8_t *numvfs); +int get_vf_dev_info_by_pf_dev_name(const char *pf_dev_name, + struct tool_target *vf_target, uint8_t vf_id); +int get_pf_dev_info_by_vf_dev_name(const char *vf_dev_name, struct tool_target *pf_target); +void hikp_ether_format_addr(char *buf, uint16_t size, const uint8_t *mac_addr); + +#endif diff --git a/net/nic/nic_mac/hikp_mac_cmd.h b/net/nic/nic_mac/hikp_mac_cmd.h new file mode 100644 index 0000000..5f0450a --- /dev/null +++ b/net/nic/nic_mac/hikp_mac_cmd.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022 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_MAC_CMD_H +#define HIKP_MAC_CMD_H + +/* mac command code */ +enum mac_module_cmd { + MAC_CMD_PORT = 1, + MAC_CMD_DUMP_REG, + MAC_CMD_DUMP_XSFP, +}; + +enum mac_port_sub_cmd { + QUERY_PHY_KSETTING = 0, + QUERY_PORT_HARDWARE, + QUERY_PORT_MAC_DFX, + QUERY_PORT_LINK_DFX, + QUERY_PORT_ARB_DFX, + QUERY_PORT_ADAPT_DFX, + QUERY_PORT_PHY_DFX, + QUERY_HOT_PLUG_CARD_DFX, +}; + +enum mac_dump_reg_sub_cmd { + MAC_DUMP_GET_BLK_NUM = 0, + MAC_DUMP_RX_MAC_REG, + MAC_DUMP_RX_PCS_REG, + MAC_DUMP_RX_RSFEC_REG, + MAC_DUMP_RX_BRFEC_REG, + MAC_DUMP_RXPMA_CORE_REG, + MAC_DUMP_RXPMA_LANE_REG, + MAC_DUMP_TXPMA_LANE_REG, + MAC_DUMP_TXPMA_CORE_REG, + MAC_DUMP_TX_BRFEC_REG, + MAC_DUMP_TX_RSFEC_REG, + MAC_DUMP_TX_PCS_REG, + MAC_DUMP_TX_MAC_REG, + MAC_DUMP_MIB_REG, + MAC_DUMP_COM_REG, + MAC_DUMP_GE_REG, + MAC_DUMP_MAC_COMM_REG, + MAC_DUMP_AN_REG, + MAC_DUMP_LT_REG, +}; + +enum mac_dump_xsfp_sub_cmd { + NIC_XSFP_GET_BASIC_INFO, + NIC_XSFP_GET_EEPROM_DATA, +}; + +#endif diff --git a/net/nic/nic_mac/hikp_nic_mac_dump.c b/net/nic/nic_mac/hikp_nic_mac_dump.c new file mode 100644 index 0000000..6e856a8 --- /dev/null +++ b/net/nic/nic_mac/hikp_nic_mac_dump.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "hikp_net_lib.h" +#include "hikptdev_plug.h" +#include "hikp_mac_cmd.h" +#include "hikp_nic_mac_dump.h" + +static struct cmd_mac_dump g_dump_reg_info = {0}; + +static int mac_dump_module_reg(struct major_cmd_ctrl *self, uint32_t cur_blk_id, uint32_t sub_code) +{ + struct reg_rsp_info *rsp_data = NULL; + struct dump_reg_req req_data = {0}; + struct hikp_cmd_ret *cmd_ret = NULL; + struct hikp_cmd_header req_header = {0}; + uint32_t rsp_reg_num; + uint32_t i; + + req_data.bdf = g_dump_reg_info.target.bdf; + req_data.blk_id = cur_blk_id; + + hikp_cmd_init(&req_header, MAC_MOD, MAC_CMD_DUMP_REG, sub_code); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (!cmd_ret) { + HIKP_ERROR_PRINT("dump mac sub_code:0x%x reg failed.\n", sub_code); + self->err_no = -ENOSPC; + return self->err_no; + } + if (cmd_ret->status != 0) { + free(cmd_ret); + self->err_no = -EINVAL; + return self->err_no; + } + + rsp_data = (struct reg_rsp_info *)(cmd_ret->rsp_data); + rsp_reg_num = cmd_ret->rsp_data_num >> 1U; + + for (i = 0; i < rsp_reg_num; i++) { + printf("\t[0x%04x] :\t0x%012lx\n", rsp_data->addr, (uint64_t)rsp_data->val); + rsp_data++; + } + + free(cmd_ret); + + return 0; +} + +static int mac_cmd_dump_mod(struct major_cmd_ctrl *self, const char *name, + uint32_t sub_code, uint32_t blk_num) +{ + uint32_t i; + int ret; + + printf("============ %10s REG INFO ==============\n", name); + printf("\t %s :\t%10s\n", "offset", "value"); + + for (i = 0; i < blk_num; i++) { + ret = mac_dump_module_reg(self, i, sub_code); + if (ret != 0) + return ret; + } + + return 0; +} + +struct mac_dump_mod_proc g_dump_mod_proc[] = { + {MOD_RX_MAC, MAC_DUMP_RX_MAC_REG, "RX_MAC" }, + {MOD_RX_PCS, MAC_DUMP_RX_PCS_REG, "RX_PCS" }, + {MOD_RX_RSFEC, MAC_DUMP_RX_RSFEC_REG, "RX_RSFEC" }, + {MOD_RX_BRFEC, MAC_DUMP_RX_BRFEC_REG, "RX_BRFEC" }, + {MOD_RXPMA_CORE, MAC_DUMP_RXPMA_CORE_REG, "RXPMA_CORE" }, + {MOD_RXPMA_LANE, MAC_DUMP_RXPMA_LANE_REG, "RXPMA_LANE" }, + {MOD_TXPMA_LANE, MAC_DUMP_TXPMA_LANE_REG, "TXPMA_LANE" }, + {MOD_TXPMA_CORE, MAC_DUMP_TXPMA_CORE_REG, "TXPMA_CORE" }, + {MOD_TX_BRFEC, MAC_DUMP_TX_BRFEC_REG, "TX_BRFEC" }, + {MOD_TX_RSFEC, MAC_DUMP_TX_RSFEC_REG, "TX_RSFEC" }, + {MOD_TX_PCS, MAC_DUMP_TX_PCS_REG, "TX_PCS" }, + {MOD_TX_MAC, MAC_DUMP_TX_MAC_REG, "TX_MAC" }, + {MOD_MIB, MAC_DUMP_MIB_REG, "MIB" }, + {MOD_COM, MAC_DUMP_COM_REG, "COM" }, + {MOD_GE, MAC_DUMP_GE_REG, "GE", }, + {MOD_MAC_COMM, MAC_DUMP_MAC_COMM_REG, "MAC_COMM" }, + {MOD_AN, MAC_DUMP_AN_REG, "AN" }, + {MOD_LT, MAC_DUMP_LT_REG, "LT" }, +}; + +static void mac_cmd_dump_all(struct major_cmd_ctrl *self) +{ + size_t size = HIKP_ARRAY_SIZE(g_dump_mod_proc); + size_t i; + int ret; + + for (i = 0; i < size; i++) { + ret = mac_cmd_dump_mod(self, g_dump_mod_proc[i].name, g_dump_mod_proc[i].sub_cmd, + g_dump_reg_info.blk_num[g_dump_mod_proc[i].module_id]); + if (ret != 0) { + HIKP_ERROR_PRINT("dump module name:%s reg failed.\n", + g_dump_mod_proc[i].name); + return; + } + } +} + +static void mac_cmd_dump_module(struct major_cmd_ctrl *self, const char *module_name) +{ + size_t size = HIKP_ARRAY_SIZE(g_dump_mod_proc); + size_t i; + int ret; + + for (i = 0; i < size; i++) { + if (strcmp(g_dump_mod_proc[i].name, module_name) != 0) + continue; + + ret = mac_cmd_dump_mod(self, g_dump_mod_proc[i].name, g_dump_mod_proc[i].sub_cmd, + g_dump_reg_info.blk_num[g_dump_mod_proc[i].module_id]); + if (ret != 0) + HIKP_ERROR_PRINT("dump module name:%s reg failed.\n", module_name); + return; + } + + HIKP_ERROR_PRINT("invalid module name:%s.\n", module_name); +} + +static int mac_cmd_get_dump_blk_num(struct major_cmd_ctrl *self) +{ + struct hikp_cmd_ret *cmd_ret = NULL; + struct hikp_cmd_header req_header = {0}; + + hikp_cmd_init(&req_header, MAC_MOD, MAC_CMD_DUMP_REG, MAC_DUMP_GET_BLK_NUM); + cmd_ret = hikp_cmd_alloc(&req_header, &g_dump_reg_info.target.bdf, + sizeof(g_dump_reg_info.target.bdf)); + if (!cmd_ret) { + HIKP_ERROR_PRINT("nic_mac get reg blk num failed.\n"); + self->err_no = -ENOSPC; + return self->err_no; + } + + if (cmd_ret->status != 0 || cmd_ret->rsp_data_num < MOD_ID_MAX) { + HIKP_ERROR_PRINT("nic_mac reg blk num error, rsp_num:%u\n", cmd_ret->rsp_data_num); + self->err_no = -EINVAL; + free(cmd_ret); + return self->err_no; + } + + memcpy(g_dump_reg_info.blk_num, cmd_ret->rsp_data, sizeof(g_dump_reg_info.blk_num)); + + free(cmd_ret); + + return 0; +} + +static int mac_cmd_dump_para_check(struct major_cmd_ctrl *self) +{ + if (!g_dump_reg_info.port_flag) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need port id."); + return self->err_no; + } + + if (!g_dump_reg_info.module_name) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need module name."); + return self->err_no; + } + + return 0; +} + +static void mac_cmd_dump_execute(struct major_cmd_ctrl *self) +{ + int ret; + + ret = mac_cmd_dump_para_check(self); + if (ret != 0) + return; + + /* first:get blk num */ + ret = mac_cmd_get_dump_blk_num(self); + if (ret != 0) + return; + + if (strcmp(g_dump_reg_info.module_name, "ALL") == 0) + mac_cmd_dump_all(self); + else + mac_cmd_dump_module(self, g_dump_reg_info.module_name); +} + +static int mac_cmd_dump_reg_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &g_dump_reg_info.target); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + g_dump_reg_info.port_flag = true; + + return 0; +} + +static int mac_cmd_dump_reg_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i -m \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0~3"); + + printf(" %s, %-25s %s\n", "-m", "--module=", + "input the mac key reg module name, e.g:"); + printf(" %s\n", + "ALL/RX_MAC/RX_PCS/RX_RSFEC/RX_BRFEC/RXPMA_CORE/RXPMA_LANE/TXPMA_LANE"); + printf(" %s\n", + "TXPMA_CORE/TX_BRFEC/TX_RSFEC/TX_PCS/TX_MAC/MIB/COM/GE/MAC_COMM/AN/LT"); + + return 0; +} + +static int mac_cmd_dump_module_cfg(struct major_cmd_ctrl *self, const char *argv) +{ + g_dump_reg_info.module_name = argv; + + return 0; +} + +static void cmd_mac_dump_reg_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_dump_reg_info.port_flag = false; + + major_cmd->option_count = 0; + major_cmd->execute = mac_cmd_dump_execute; + + cmd_option_register("-h", "--help", false, mac_cmd_dump_reg_help); + cmd_option_register("-i", "--interface", true, mac_cmd_dump_reg_target); + cmd_option_register("-m", "--module", true, mac_cmd_dump_module_cfg); +} + +HIKP_CMD_DECLARE("nic_mac", "dump mac module reg information", cmd_mac_dump_reg_init); diff --git a/net/nic/nic_mac/hikp_nic_mac_dump.h b/net/nic/nic_mac/hikp_nic_mac_dump.h new file mode 100644 index 0000000..f82762e --- /dev/null +++ b/net/nic/nic_mac/hikp_nic_mac_dump.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 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_NIC_MAC_DUMP_H +#define HIKP_NIC_MAC_DUMP_H + +#include "hikp_net_lib.h" + +struct mac_dump_mod_proc { + uint32_t module_id; + uint32_t sub_cmd; + const char *name; +}; + +enum dump_module { + MOD_RX_MAC = 0, + MOD_RX_PCS, + MOD_RX_RSFEC, + MOD_RX_BRFEC, + MOD_RXPMA_CORE, + MOD_RXPMA_LANE, + MOD_TXPMA_LANE, + MOD_TXPMA_CORE, + MOD_TX_BRFEC, + MOD_TX_RSFEC, + MOD_TX_PCS, + MOD_TX_MAC, + MOD_MIB, + MOD_COM, + MOD_GE, + MOD_MAC_COMM, + MOD_AN, + MOD_LT, + MOD_ID_MAX, +}; + +struct dump_reg_req { + struct bdf_t bdf; + uint32_t blk_id; +}; + +struct reg_rsp_info { + uint64_t addr : 16; + uint64_t val : 48; +}; + +struct cmd_mac_dump { + struct tool_target target; + bool port_flag; + uint32_t blk_num[MOD_ID_MAX]; + const char *module_name; +}; +#endif diff --git a/net/nic/nic_mac/hikp_nic_port.c b/net/nic/nic_mac/hikp_nic_port.c new file mode 100644 index 0000000..1ff3569 --- /dev/null +++ b/net/nic/nic_mac/hikp_nic_port.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "hikp_net_lib.h" +#include "hikptdev_plug.h" +#include "hikp_mac_cmd.h" +#include "hikp_nic_port.h" + +static struct cmd_port_info g_port_info = {0}; + +struct mac_item g_fec_table[] = { + {PORT_CFG_FEC_NOT_SET, "unset"}, + {PORT_CFG_FEC_RSFEC, "rsfec"}, + {PORT_CFG_FEC_BASEFEC, "basefec"}, + {PORT_CFG_FEC_NOFEC, "nofec"}, + {PORT_CFG_FEC_AUTO, "auto"}, + {PORT_CFG_FEC_LLRSFEC, "llrsfec"} +}; + +struct mac_item g_speed_table[] = { + {PORT_SPEED_NOT_SET, "unset"}, + {PORT_SPEED_10MB, "10M"}, + {PORT_SPEED_100MB, "100M"}, + {PORT_SPEED_1GB, "1G"}, + {PORT_SPEED_10GB, "10G"}, + {PORT_SPEED_25GB, "25G"}, + {PORT_SPEED_40GB, "40G"}, + {PORT_SPEED_50GB, "50G"}, + {PORT_SPEED_100GB, "100G"}, + {PORT_SPEED_200GB, "200G"}, +}; + +struct mac_item g_an_table[] = { + {PORT_CFG_NOT_SET, "unset"}, + {PORT_CFG_AN_ON, "on"}, + {PORT_CFG_AN_OFF, "off"}, +}; + +struct mac_item g_adapt_table[] = { + {PORT_CFG_ADAPT_NOT_SET, "unset"}, + {PORT_CFG_ADAPT_ON, "on"}, + {PORT_CFG_ADAPT_OFF, "off"} +}; + +struct mac_item g_duplex_table[] = { + {HIKP_MAC_DUPLEX_UNKNOWN, "unset"}, + {HIKP_MAC_DUPLEX_FULL, "full"}, + {HIKP_MAC_DUPLEX_HALF, "half"}, +}; + +struct mac_item g_sds_rate_table[] = { + {HIKP_MAC_SDS_RATE_UNKNOWN, "unset"}, + {HIKP_MAC_SDS_RATE_1P25G, "1.25G"}, + {HIKP_MAC_SDS_RATE_10P3125G, "10.3125G"}, + {HIKP_MAC_SDS_RATE_25P78125G, "25.78125G"}, + {HIKP_MAC_SDS_RATE_26P5625G, "26.5625G"}, + {HIKP_MAC_SDS_RATE_53P125G, "53.125G"}, +}; + +struct mac_item g_lanes_table[] = { + {HIKP_MAC_LANES_UNKNOWN, "unset"}, + {HIKP_MAC_LANES_X1, "X1"}, + {HIKP_MAC_LANES_X2, "X2"}, + {HIKP_MAC_LANES_X4, "X4"}, + {HIKP_MAC_LANES_X8, "X8"}, +}; + +static void mac_show_mask(uint32_t mask, const struct mac_item *table, uint32_t size) +{ + uint32_t i; + + for (i = 0; i < size; i++) { + if (mask & table[i].key) + printf("%s ", table[i].name); + } + printf("\n"); +} + +static void mac_print_modes(const char *label, uint32_t mask, + const struct mac_item *table, uint32_t size) +{ + printf("%s: ", label); + + mac_show_mask(mask, table, size); +} + +static const char *mac_get_str(uint32_t val, const struct mac_item *table, + uint32_t size, const char *none_str) +{ + const char *str = none_str; + uint32_t i; + + for (i = 0; i < size; i++) { + if (table[i].key == val) { + str = table[i].name; + break; + } + } + + return str; +} + +static void mac_print_enum(const char *label, uint32_t val, const struct mac_item *table, + uint32_t size, const char *none_str) +{ + const char *str = mac_get_str(val, table, size, none_str); + + if (str == NULL) + return; + + printf("%s: %s\n", label, str); +} + +static void mac_print_enable(const char *label, uint32_t val) +{ + const char *str = (val != 0) ? "on" : "off"; + + printf("%s: %s\n", label, str); +} + +static void mac_print_link(const char *label, uint32_t val) +{ + const char *str = (val != 0) ? "link" : "no link"; + + printf("%s: %s\n", label, str); +} + +static int mac_cmd_get_dfx_cfg(uint32_t sub_cmd, struct hikp_cmd_ret **cmd_ret) +{ + struct hikp_cmd_header req_header = {0}; + + hikp_cmd_init(&req_header, MAC_MOD, MAC_CMD_PORT, sub_cmd); + *cmd_ret = hikp_cmd_alloc(&req_header, &g_port_info.target.bdf, + sizeof(g_port_info.target.bdf)); + if (*cmd_ret == NULL) + return -ENOSPC; + + if ((*cmd_ret)->status != 0) { + free(*cmd_ret); + *cmd_ret = NULL; + return -EAGAIN; + } + + return 0; +} + +static bool is_ge_speed(uint32_t speed) +{ + return speed == PORT_SPEED_10MB || speed == PORT_SPEED_100MB || speed == PORT_SPEED_1GB; +} + +static void mac_show_speed(uint32_t speed, uint32_t lanes) +{ + const char *speed_str = mac_get_str(speed, g_speed_table, + HIKP_ARRAY_SIZE(g_speed_table), NULL); + const char *lanes_str = mac_get_str(lanes, g_lanes_table, + HIKP_ARRAY_SIZE(g_lanes_table), NULL); + + if (is_ge_speed(speed) || speed_str == NULL || lanes_str == NULL) + printf("speed: %s\n", (speed_str != NULL) ? speed_str : "unknown"); + else + printf("speed: %s_%s\n", speed_str, lanes_str); +} + +static void mac_cmd_disp_mac_info(const struct mac_cmd_mac_dfx *mac_dfx) +{ + printf("\n========================== MAC INFO ==========================\n"); + mac_show_speed(mac_dfx->speed, mac_dfx->lanes); + mac_print_enum("fec", mac_dfx->fec, g_fec_table, HIKP_ARRAY_SIZE(g_fec_table), "unknown"); + mac_print_enum("duplex", mac_dfx->duplex, g_duplex_table, + HIKP_ARRAY_SIZE(g_duplex_table), "unknown"); + mac_print_enum("sds_rate", mac_dfx->sds_rate, g_sds_rate_table, + HIKP_ARRAY_SIZE(g_sds_rate_table), "unknown"); + mac_print_enable("mac_tx_en", mac_dfx->mac_tx_en); + mac_print_enable("mac_rx_en", mac_dfx->mac_rx_en); + mac_print_link("pcs_link", mac_dfx->pcs_link); + mac_print_link("mac_link", mac_dfx->mac_link); + printf("pma_ctrl = %u\n", mac_dfx->pma_ctrl); + printf("rf_lf = 0x%x\n", mac_dfx->rf_lf); + printf("pcs_err = 0x%x\n", mac_dfx->pcs_err_cnt); +} + +static void mac_cmd_show_mac(struct major_cmd_ctrl *self) +{ + struct mac_cmd_mac_dfx *mac_dfx = NULL; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + ret = mac_cmd_get_dfx_cfg(QUERY_PORT_MAC_DFX, &cmd_ret); + if (ret != 0) { + printf("hikp_data_proc get mac dfx failed.\n"); + self->err_no = -ENOSPC; + return; + } + + mac_dfx = (struct mac_cmd_mac_dfx *)(cmd_ret->rsp_data); + mac_cmd_disp_mac_info(mac_dfx); + free(cmd_ret); +} + +static void mac_cmd_disp_link_info(struct mac_cmd_link_dfx *link_dfx) +{ + struct mac_port_param *port_cfg = &link_dfx->port_cfg; + + printf("\n======================= PORT LINK INFO =======================\n"); + mac_print_enum("adapt", port_cfg->adapt, g_adapt_table, + HIKP_ARRAY_SIZE(g_adapt_table), "unknown"); + mac_print_enum("autoneg", port_cfg->an, g_an_table, HIKP_ARRAY_SIZE(g_an_table), "unknown"); + mac_show_speed(port_cfg->speed, port_cfg->lanes); + mac_print_enum("fec", port_cfg->fec, g_fec_table, HIKP_ARRAY_SIZE(g_fec_table), "unknown"); + mac_print_enum("duplex", port_cfg->duplex, g_duplex_table, + HIKP_ARRAY_SIZE(g_duplex_table), "unknown"); + mac_print_enum("sds_rate", port_cfg->sds_rate, g_sds_rate_table, + HIKP_ARRAY_SIZE(g_sds_rate_table), "unknown"); + mac_print_link("port link", link_dfx->port_link); + mac_print_enable("port enable", link_dfx->port_enable); + mac_print_enable("link debug", link_dfx->link_debug_en); + mac_print_enable("link report", link_dfx->link_report_en); + printf("cur_link_machine = 0x%x\n", link_dfx->cur_link_machine); + printf("his_link_machine = 0x%x\n", link_dfx->his_link_machine); +} + +static void mac_cmd_show_link(struct major_cmd_ctrl *self) +{ + struct mac_cmd_link_dfx *link_dfx = NULL; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + ret = mac_cmd_get_dfx_cfg(QUERY_PORT_LINK_DFX, &cmd_ret); + if (ret != 0) { + printf("hikp_data_proc get link dfx failed.\n"); + self->err_no = -ENOSPC; + return; + } + + link_dfx = (struct mac_cmd_link_dfx *)(cmd_ret->rsp_data); + mac_cmd_disp_link_info(link_dfx); + free(cmd_ret); +} + +static void mac_cmd_disp_phy_reg(const uint16_t *reg, uint32_t num) +{ +#define PRINT_OFFSET 4 + + uint32_t i; + + for (i = 0; i < num; i++) { + printf("reg %2u : 0x%04x\t", i, reg[i]); + + if (i % PRINT_OFFSET == (PRINT_OFFSET - 1)) + printf("\n"); + } +} + +static void mac_cmd_disp_phy_info(const struct mac_cfg_phy_cfg *phy_param, + const struct mac_cmd_phy_dfx *phy_dfx) +{ + struct mac_item dup_ext_tbl[] = { + {HIKP_PHY_DUPLEX_HALF, "half"}, {HIKP_PHY_DUPLEX_FULL, "full"}, + }; + struct mac_item phy_abi_tbl[] = { + {HIKP_MAC_PHY_ABI_10M_HALF, "10M/Half"}, {HIKP_MAC_PHY_ABI_10M_FULL, "10M/Full"}, + {HIKP_MAC_PHY_ABI_100M_HALF, "100M/Half"}, + {HIKP_MAC_PHY_ABI_100M_FULL, "100M/Full"}, + {HIKP_MAC_PHY_ABI_1000M_HALF, "1000M/Half"}, + {HIKP_MAC_PHY_ABI_1000M_FULL, "1000M/Full"}, + }; + + printf("\n========================== PHY INFO ==========================\n"); + printf("phy_addr = %u\n", phy_param->phy_addr); + mac_print_enable("autoneg", phy_param->autoneg); + printf("speed: %u\n", phy_param->speed); + mac_print_enum("duplex", phy_param->duplex, dup_ext_tbl, + HIKP_ARRAY_SIZE(dup_ext_tbl), "unknown"); + mac_print_modes("supported", phy_param->supported, phy_abi_tbl, + HIKP_ARRAY_SIZE(phy_abi_tbl)); + mac_print_modes("advertised", phy_param->advertising, phy_abi_tbl, + HIKP_ARRAY_SIZE(phy_abi_tbl)); + mac_print_modes("LP advertised", phy_param->lp_advertising, phy_abi_tbl, + HIKP_ARRAY_SIZE(phy_abi_tbl)); + + printf("--------------------------------------------------------------\n"); + mac_cmd_disp_phy_reg(phy_dfx->reg_val, MAC_PHY_DFX_REG_NUM); +} + +static void mac_cmd_show_phy(struct major_cmd_ctrl *self) +{ + struct mac_cfg_phy_cfg *phy_cfg = NULL; + struct mac_cmd_phy_dfx *phy_dfx = NULL; + struct hikp_cmd_ret *phy_cfg_ret = NULL; + struct hikp_cmd_ret *phy_dfx_ret = NULL; + int ret; + + ret = mac_cmd_get_dfx_cfg(QUERY_PHY_KSETTING, &phy_cfg_ret); + if (ret != 0) { + printf("hikp_data_proc get phy cfg failed.\n"); + self->err_no = -ENOSPC; + return; + } + phy_cfg = (struct mac_cfg_phy_cfg *)(phy_cfg_ret->rsp_data); + + ret = mac_cmd_get_dfx_cfg(QUERY_PORT_PHY_DFX, &phy_dfx_ret); + if (ret != 0) { + printf("hikp_data_proc get phy dfx failed.\n"); + self->err_no = -ENOSPC; + free(phy_cfg_ret); + return; + } + phy_dfx = (struct mac_cmd_phy_dfx *)(phy_dfx_ret->rsp_data); + mac_cmd_disp_phy_info(phy_cfg, phy_dfx); + free(phy_cfg_ret); + free(phy_dfx_ret); +} + +static void mac_cmd_disp_port_param(const char *label, const struct mac_port_param *port) +{ + const char *adapt_str = mac_get_str(port->adapt, g_adapt_table, + HIKP_ARRAY_SIZE(g_adapt_table), "unset"); + const char *speed_str = mac_get_str(port->speed, g_speed_table, + HIKP_ARRAY_SIZE(g_speed_table), "unset"); + const char *lanes_str = mac_get_str(port->lanes, g_lanes_table, + HIKP_ARRAY_SIZE(g_lanes_table), "unset"); + const char *dup_str = mac_get_str(port->duplex, g_duplex_table, + HIKP_ARRAY_SIZE(g_duplex_table), "unset"); + const char *sds_str = mac_get_str(port->sds_rate, g_sds_rate_table, + HIKP_ARRAY_SIZE(g_sds_rate_table), "unset"); + const char *fec_str = mac_get_str(port->fec, g_fec_table, + HIKP_ARRAY_SIZE(g_fec_table), "unset"); + const char *an_str = mac_get_str(port->an, g_an_table, + HIKP_ARRAY_SIZE(g_an_table), "unset"); + + printf("%s\t|%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", label, + adapt_str, an_str, speed_str, lanes_str, fec_str, dup_str, sds_str); +} + +static void mac_cmd_disp_arb_info(const struct mac_cmd_arb_dfx *arb_dfx) +{ + printf("\n======================== ARB LINK INFO =======================\n"); + + printf("area\t|adapt |an |speed |lanes |fec |duplex |sds_rate\n"); + printf("----------------------------------------------------------------------------\n"); + + mac_cmd_disp_port_param("Default", &arb_dfx->default_cfg); + mac_cmd_disp_port_param("BIOS", &arb_dfx->bios_cfg); + mac_cmd_disp_port_param("TOOL", &arb_dfx->user_cfg); + mac_cmd_disp_port_param("Final", &arb_dfx->port_cfg); +} + +static void mac_cmd_disp_hot_plug_card_info(const struct cmd_hot_plug_card_info *hpc_dfx) +{ + printf("\n======================== HOT PLUG CARD INFO =======================\n"); + + printf("hot plug card in position: 0x%x\n", hpc_dfx->in_pos); + printf("support type: 0x%x\n", hpc_dfx->support_type); + printf("current type: 0x%x\n", hpc_dfx->cur_type); + printf("----------------------------------------------------------------------------\n"); +} + +static void mac_cmd_show_arb(struct major_cmd_ctrl *self) +{ + struct mac_cmd_arb_dfx *arb_dfx = NULL; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + ret = mac_cmd_get_dfx_cfg(QUERY_PORT_ARB_DFX, &cmd_ret); + if (ret != 0) { + printf("hikp_data_proc get arb dfx failed.\n"); + self->err_no = -ENOSPC; + return; + } + + arb_dfx = (struct mac_cmd_arb_dfx *)(cmd_ret->rsp_data); + mac_cmd_disp_arb_info(arb_dfx); + free(cmd_ret); +} + +static void mac_cmd_show_hot_plug_card(struct major_cmd_ctrl *self) +{ + struct cmd_hot_plug_card_info *hpc_dfx = NULL; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + ret = mac_cmd_get_dfx_cfg(QUERY_HOT_PLUG_CARD_DFX, &cmd_ret); + if (ret != 0) { + printf("hikp_data_proc get hot plug card dfx failed.\n"); + self->err_no = -ENOSPC; + return; + } + + hpc_dfx = (struct cmd_hot_plug_card_info *)(cmd_ret->rsp_data); + mac_cmd_disp_hot_plug_card_info(hpc_dfx); + free(cmd_ret); +} + +static void mac_cmd_show_port_dfx(struct major_cmd_ctrl *self, uint32_t mask) +{ + struct mac_cmd_dfx_callback dfx_cb[] = { + {MAC_LSPORT_LINK, mac_cmd_show_link}, + {MAC_LSPORT_MAC, mac_cmd_show_mac}, + {MAC_LSPORT_PHY, mac_cmd_show_phy}, + {MAC_LSPORT_ARB, mac_cmd_show_arb}, + {MAC_HOT_PLUG_CARD, mac_cmd_show_hot_plug_card}, + }; + size_t size = HIKP_ARRAY_SIZE(dfx_cb); + size_t i; + + for (i = 0; i < size; i++) { + if (mask & dfx_cb[i].mask) + dfx_cb[i].show_dfx(self); + } +} + +static void mac_cmd_port_execute(struct major_cmd_ctrl *self) +{ + uint32_t mask = MAC_LSPORT_LINK | MAC_LSPORT_MAC | MAC_LSPORT_ARB | MAC_HOT_PLUG_CARD; + struct mac_cmd_port_hardware *port_hw = NULL; + struct hikp_cmd_ret *hw_cmd_ret = NULL; + int ret; + + if (!g_port_info.port_flag) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need port id."); + return; + } + + ret = mac_cmd_get_dfx_cfg(QUERY_PORT_HARDWARE, &hw_cmd_ret); + if (ret != 0) { + printf("hikp_data_proc get port hw failed.\n"); + self->err_no = -ENOSPC; + return; + } + + port_hw = (struct mac_cmd_port_hardware *)(hw_cmd_ret->rsp_data); + if (port_hw->port_type == 1) + mask |= MAC_LSPORT_PHY; + + mac_cmd_show_port_dfx(self, mask); + free(hw_cmd_ret); +} + +static int mac_cmd_get_port_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &g_port_info.target); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + g_port_info.port_flag = true; + + return 0; +} + +static int mac_cmd_port_show_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~3 or 0000:34:00.0"); + printf("\n"); + + return 0; +} + +static void cmd_mac_get_port_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_port_info.port_flag = false; + + major_cmd->option_count = 0; + major_cmd->execute = mac_cmd_port_execute; + + cmd_option_register("-h", "--help", false, mac_cmd_port_show_help); + cmd_option_register("-i", "--interface", true, mac_cmd_get_port_target); +} + +HIKP_CMD_DECLARE("nic_port", "query nic port information", cmd_mac_get_port_init); diff --git a/net/nic/nic_mac/hikp_nic_port.h b/net/nic/nic_mac/hikp_nic_port.h new file mode 100644 index 0000000..ac00f55 --- /dev/null +++ b/net/nic/nic_mac/hikp_nic_port.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2022 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_NIC_PORT_H +#define HIKP_NIC_PORT_H + +#include "hikp_net_lib.h" + +#define MAC_LSPORT_LINK HI_BIT(0) +#define MAC_LSPORT_MAC HI_BIT(1) +#define MAC_LSPORT_PHY HI_BIT(2) +#define MAC_LSPORT_ARB HI_BIT(3) +#define MAC_HOT_PLUG_CARD HI_BIT(4) + +enum { + PORT_CFG_NOT_SET = 0, + PORT_CFG_AN_ON = 1, + PORT_CFG_AN_OFF = 2, +}; + +enum { + PORT_CFG_FEC_NOT_SET = 0, + PORT_CFG_FEC_RSFEC = 1, + PORT_CFG_FEC_BASEFEC = 2, + PORT_CFG_FEC_NOFEC = 3, + PORT_CFG_FEC_AUTO = 4, + PORT_CFG_FEC_LLRSFEC = 5 +}; + +enum { + PORT_SPEED_NOT_SET = 0, + PORT_SPEED_10MB = 1, + PORT_SPEED_100MB = 2, + PORT_SPEED_1GB = 3, + PORT_SPEED_10GB = 4, + PORT_SPEED_25GB = 5, + PORT_SPEED_40GB = 6, + PORT_SPEED_50GB = 7, + PORT_SPEED_100GB = 8, + PORT_SPEED_200GB = 9, + PORT_SPEED_UNKNOWN = 0xff, +}; + +enum { + PORT_CFG_ADAPT_NOT_SET = 0, + PORT_CFG_ADAPT_ON = 1, + PORT_CFG_ADAPT_OFF = 2, +}; + +enum { + HIKP_MAC_DUPLEX_UNKNOWN = 0, + HIKP_MAC_DUPLEX_FULL, + HIKP_MAC_DUPLEX_HALF +}; + +enum { + HIKP_MAC_SDS_RATE_UNKNOWN = 0, + HIKP_MAC_SDS_RATE_1P25G, + HIKP_MAC_SDS_RATE_10P3125G, + HIKP_MAC_SDS_RATE_25P78125G, + HIKP_MAC_SDS_RATE_26P5625G, + HIKP_MAC_SDS_RATE_53P125G +}; + +enum { + HIKP_MAC_LANES_UNKNOWN = 0, + HIKP_MAC_LANES_X1 = 1, + HIKP_MAC_LANES_X2 = 2, + HIKP_MAC_LANES_X4 = 4, + HIKP_MAC_LANES_X8 = 8, +}; + +enum { + HIKP_PHY_DUPLEX_HALF = 0, + HIKP_PHY_DUPLEX_FULL, +}; + +#define HIKP_MAC_PHY_ABI_10M_HALF HI_BIT(0) +#define HIKP_MAC_PHY_ABI_10M_FULL HI_BIT(1) +#define HIKP_MAC_PHY_ABI_100M_HALF HI_BIT(2) +#define HIKP_MAC_PHY_ABI_100M_FULL HI_BIT(3) +#define HIKP_MAC_PHY_ABI_1000M_HALF HI_BIT(4) +#define HIKP_MAC_PHY_ABI_1000M_FULL HI_BIT(5) +#define HIKP_MAC_PHY_ABI_AUTONEG HI_BIT(6) +#define HIKP_MAC_PHY_ABI_PAUSE HI_BIT(13) +#define HIKP_MAC_PHY_ABI_ASYM_PAUSE HI_BIT(14) + +struct mac_item { + uint32_t key; + const char *name; +}; + +struct mac_cmd_port_hardware { + uint8_t port_type; + uint8_t media_type; +}; + +struct mac_cmd_mac_dfx { + uint8_t autoneg; + uint8_t speed; + uint8_t fec; + uint8_t duplex; + uint8_t lanes; + uint8_t sds_rate; + uint8_t rf_lf; + uint8_t mac_tx_en : 1; + uint8_t mac_rx_en : 1; + uint8_t pma_ctrl : 2; + uint8_t pcs_link : 1; + uint8_t mac_link : 1; + uint8_t reserve : 2; + uint32_t pcs_err_cnt; +}; + +struct mac_port_param { + uint8_t adapt; + uint8_t an; + uint8_t speed; + uint8_t lanes; + uint8_t sds_rate; + uint8_t fec; + uint8_t duplex; + uint32_t rsvd; +}; + +struct mac_cmd_link_dfx { + struct mac_port_param port_cfg; + uint8_t port_link : 1; + uint8_t port_enable : 1; + uint8_t link_debug_en : 1; + uint8_t link_report_en : 1; + uint8_t reserve : 4; + uint8_t loop_type; + uint8_t reserve_1[2]; + uint32_t cur_link_machine; + uint32_t his_link_machine; +}; + +struct mac_cmd_arb_dfx { + struct mac_port_param default_cfg; + struct mac_port_param bios_cfg; + struct mac_port_param user_cfg; + struct mac_port_param port_cfg; +}; + +#define MAC_PHY_DFX_REG_NUM 12 +struct mac_cmd_phy_dfx { + uint16_t reg_val[MAC_PHY_DFX_REG_NUM]; +}; + +struct mac_cfg_phy_cfg { + uint32_t speed; + uint8_t duplex; + uint8_t autoneg; + uint8_t mac_tp_mdix; + uint8_t mac_tp_mdix_ctrl; + uint8_t port; + uint8_t transceiver; + uint8_t phy_addr; + uint8_t reserved; + uint32_t supported; + uint32_t advertising; + uint32_t lp_advertising; + /* reserved cfg */ + uint8_t master_slve_cfg; + uint8_t master_slave_state; + uint8_t rsvd[2]; +}; + +struct mac_cmd_phy_info { + struct mac_cfg_phy_cfg phy_cfg; + struct mac_cmd_phy_dfx phy_dfx; +}; + +struct mac_cmd_dfx_callback { + uint32_t mask; + void (*show_dfx)(struct major_cmd_ctrl *self); +}; + +struct cmd_port_info { + struct tool_target target; + bool port_flag; +}; + +struct cmd_hot_plug_card_info { + uint8_t in_pos; + uint8_t support_type; + uint8_t cur_type; +}; + +#endif diff --git a/net/nic/nic_mac/hikp_nic_xsfp.c b/net/nic/nic_mac/hikp_nic_xsfp.c new file mode 100644 index 0000000..d97a506 --- /dev/null +++ b/net/nic/nic_mac/hikp_nic_xsfp.c @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "hikptdev_plug.h" +#include "hikp_mac_cmd.h" +#include "hikp_nic_xsfp.h" + +static struct hikp_xsfp_ctrl g_xsfp_dump = {0}; +static struct sff_ext_comp g_sff_ext_spec_comp[] = { + {0x00, "Unspecified"}, + {0x01, "100G AOC (Active Optical Cable) or 25GAUI C2M AOC"}, + {0x02, "100GBASE-SR4 or 25GBASE-SR"}, + {0x03, "100GBASE-LR4 or 25GBASE-LR"}, + {0x04, "100GBASE-ER4 or 25GBASE-ER"}, + {0x05, "100GBASE-SR10"}, + {0x06, "100G CWDM4"}, + {0x07, "100G PSM4 Parallel SMF"}, + {0x08, "100G ACC (Active Copper Cable) or 25GAUI C2M ACC"}, + {0x0B, "100GBASE-CR4, 25GBASE-CR CA-25G-L or 50GBASE-CR2 with RS (Clause91) FEC"}, + {0x0C, "25GBASE-CR CA-25G-S or 50GBASE-CR2 with BASE-R (Clause 74 Fire code) FEC"}, + {0x0D, "25GBASE-CR CA-25G-N or 50GBASE-CR2 with no FEC"}, + {0x10, "40GBASE-ER4"}, + {0x11, "4x10GBASE-SR"}, + {0x12, "40G PSM4 Parallel SMF"}, + {0x16, "10GBASE-T with SFI electrical interface"}, + {0x17, "100G CLR4"}, + {0x18, "100G AOC or 25GAUI C2M AOC"}, + {0x19, "100G ACC or 25GAUI C2M ACC"}, + {0x1A, "100GE-DWDM2"}, + {0x1C, "10GBASE-T Short Reach (30 meters)"}, + {0x21, "100G PAM4 BiDi"}, + {0x25, "100GBASE-DR"}, + {0x26, "100G-FR or 100GBASE-FR1"}, + {0x27, "100G-LR or 100GBASE-LR1"}, + {0x40, "50GBASE-CR, 100GBASE-CR2, or 200GBASE-CR4"}, + {0x41, "50GBASE-SR, 100GBASE-SR2, or 200GBASE-SR4"}, + {0x42, "50GBASE-FR or 200GBASE-DR4"}, + {0x43, "200GBASE-FR4"}, + {0x44, "200G 1550 nm PSM4"}, + {0x45, "50GBASE-LR"}, + {0x46, "200GBASE-LR4"}, + {0x4A, "50GBASE-ER"}, +}; + +static int hikp_xsfp_get_cmd_data(struct hikp_cmd_ret **cmd_resp, uint32_t sub_cmd, uint32_t blk_id) +{ + struct hikp_xsfp_req req = {0}; + struct hikp_cmd_header req_header = {0}; + + req.bdf = g_xsfp_dump.target.bdf; + req.blk_id = blk_id; + hikp_cmd_init(&req_header, MAC_MOD, MAC_CMD_DUMP_XSFP, sub_cmd); + *cmd_resp = hikp_cmd_alloc(&req_header, &req, sizeof(req)); + if (*cmd_resp == NULL) + return -ENOSPC; + + if ((*cmd_resp)->status != 0) + return -EAGAIN; + + return 0; +} + +static void hikp_xsfp_dump_hex(const uint8_t *data, uint32_t size) +{ + uint32_t i; + + printf("-----------------show eeprom raw data------------------\n"); + printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); + for (i = 0; i < size; i++) { + if ((i % XSFP_PRINT_COL) == 0) + printf("0x%03x: ", i); + + printf("%02x ", data[i]); + if ((i % XSFP_PRINT_COL) == (XSFP_PRINT_COL - 1)) + printf("\n"); + + if ((i % XSFP_PRINT_BLK) == (XSFP_PRINT_BLK - 1)) + printf("-------------------------------------------------------\n"); + } +} + +static void sff_print_ext_comp_code(const uint8_t ext_comp) +{ + uint32_t i; + size_t size = HIKP_ARRAY_SIZE(g_sff_ext_spec_comp); + + for (i = 0; i < size; i++) { + if (ext_comp == g_sff_ext_spec_comp[i].val) + printf("%-24s: %s\n", "ext_spec_compliance", + g_sff_ext_spec_comp[i].module_cap); + } +} + +static void xsfp_print_data(const char *str, uint32_t len, const uint8_t *data, uint32_t type) +{ + uint32_t i; + + printf("%-24s: ", str); + for (i = 0; i < len; i++) { + if (type == PRINT_ASCII) + printf("%c", data[i]); + else + printf("0x%02x ", data[i]); + } + printf("\n"); +} + +static void xsfp_show_mask(const uint8_t val, const struct sff_comp_info *table, size_t size) +{ + bool flag = false; + uint32_t i; + + for (i = 0; i < size; i++) { + if ((val & table[i].mask) != 0) { + if (flag) { + printf("%s ", table[i].description); + } else { + printf("%-24s: %s ", "transceiver_compliance", + table[i].description); + flag = true; + } + } + } + if (flag) + printf("\n"); +} + +static void sfp_print_trans_comp_code(const struct sfp_page_info *info) +{ + const struct sff_comp_info sff_10g_comp[] = { + {SFP_10GBASE_SR_MASK, "10GBASE-SR"}, {SFP_10GBASE_LR_MASK, "10GBASE-LR"}, + {SFP_10GBASE_LRM_MASK, "10GBASE-LRM"}, {SFP_10GBASE_ER_MASK, "10GBASE-ER"}, + }; + const struct sff_comp_info sff_comp[] = { + {SFP_1000BASE_SX_MASK, "1000BASE-SX"}, {SFP_1000BASE_LX_MASK, "1000BASE-LX"}, + {SFP_1000BASE_CX_MASK, "1000BASE-CX"}, {SFP_1000BASE_T_MASK, "1000BASE-T"}, + {SFP_100BASE_LX_LX10_MASK, "100BASE-LX/LX10"}, {SFP_100BASE_FX_MASK, "100BASE-FX"}, + {SFP_BASE_BX10_MASK, "BASE-BX10"}, {SFP_BASE_PX_MASK, "BASE-PX"}, + }; + uint32_t i; + + printf("%-24s: ", "transceiver_code"); + for (i = 0; i < SFF_TRANCEIV_LEN; i++) + printf("0x%02x ", info->page_a0.transceiver[i]); + + printf("| ext: 0x%02x\n", info->page_a0.transceiver_code); + + xsfp_show_mask(info->page_a0.transceiver[0], sff_10g_comp, HIKP_ARRAY_SIZE(sff_10g_comp)); + xsfp_show_mask(info->page_a0.transceiver[3U], sff_comp, HIKP_ARRAY_SIZE(sff_comp)); + + sff_print_ext_comp_code(info->page_a0.transceiver_code); +} + +static void sfp_print_base_id_info(const struct sfp_page_info *info) +{ + printf("%-24s: 0x%02x\n", "identifier", info->page_a0.identifier); + printf("%-24s: 0x%02x\n", "ext_identifier", info->page_a0.ext_identifier); + printf("%-24s: 0x%02x\n", "connector", info->page_a0.connector); + printf("%-24s: 0x%02x\n", "encoding", info->page_a0.encoding); + printf("%-24s: %u (100MBd)\n", "br_nominal", info->page_a0.br_nominal); + printf("%-24s: 0x%02x\n", "rate_identifier", info->page_a0.rate_identifier); + printf("%-24s: %u (km)\n", "smf_len_km", info->page_a0.len_smf_km); + printf("%-24s: %u (100m)\n", "smf_len", info->page_a0.len_smf); + printf("%-24s: %u (10m)\n", "smf_om2_len", info->page_a0.len_smf_om2); + printf("%-24s: %u (10m)\n", "smf_om1_len", info->page_a0.len_smf_om1); + printf("%-24s: %u (m)\n", "cable_len", info->page_a0.len_cable); + printf("%-24s: %u (10m)\n", "om3_len", info->page_a0.len_om3); + printf("%-24s: %d (nm)\n", "wavelength", + ((uint16_t)info->page_a0.wave_leng[0] << 8U) | (uint16_t)info->page_a0.wave_leng[1]); + + xsfp_print_data("vendor_name", VEND_NAME_LEN, info->page_a0.vendor_name, PRINT_ASCII); + xsfp_print_data("vendor_oui", VEND_OUI_LEN, info->page_a0.vendor_oui, PRINT_HEX); + xsfp_print_data("vendor_pn", VEND_PN_LEN, info->page_a0.vendor_pn, PRINT_ASCII); + xsfp_print_data("vendor_rev", SFP_VEND_REV_LEN, info->page_a0.vendor_rev, PRINT_ASCII); + xsfp_print_data("vendor_sn", VEND_SN_LEN, info->page_a0.vendor_sn, PRINT_ASCII); + xsfp_print_data("vendor_date_code", VEND_DATE_CODE_LEN, + info->page_a0.date_code, PRINT_ASCII); + + printf("%-24s: 0x%02x(%s) support: 0x%02x(%s)\n", "tx_disable", + info->page_a2.soft_tx_dis_select, + (info->page_a2.soft_tx_dis_select == 0) ? "No" : "Yes", + info->page_a0.tx_disable_imp, (info->page_a0.tx_disable_imp == 0) ? "No" : "Yes"); + + sfp_print_trans_comp_code(info); +} + +static void sfp_print_dom_info(const struct sfp_page_info *info) +{ + /* if not implement diagnostic check or copper not support read power and temperature */ + if (info->page_a0.ddm_imp == 0 || info->page_a0.connector == SFF_CONNECTOR_COPPER) + return; + + printf("%-24s: %d uW\n", "tx_power", + ((uint16_t)info->page_a2.tx_power[0] << 8U) | (uint16_t)info->page_a2.tx_power[1]); + printf("%-24s: %d uW\n", "rx_power", + ((uint16_t)info->page_a2.rx_power[0] << 8U) | (uint16_t)info->page_a2.rx_power[1]); + printf("%-24s: %d.%02u\n", "temperature", + (int8_t)info->page_a2.temperature[0], info->page_a2.temperature[1]); +} + +static void hikp_show_sfp_info(const uint8_t *data, uint32_t size) +{ + struct sfp_page_info *sfp_data = (struct sfp_page_info *)data; + + printf("------------------------show sfp info-------------------------\n"); + sfp_print_base_id_info(sfp_data); + sfp_print_dom_info(sfp_data); + printf("--------------------------------------------------------------\n"); +} + +static void qsfp_print_trans_comp_code(const struct qsfp_page0_info *info) +{ + const struct sff_comp_info sff_40g_comp[] = { + {QSFP_40G_ACT_CABLE_MASK, "40G Active Cable (XLPPI)"}, + {QSFP_40GBASE_LR4_MASK, "40GBASE-LR4"}, + {QSFP_40GBASE_SR4_MASK, "40GBASE-SR4"}, {QSFP_40GBASE_CR4_MASK, "40GBASE-CR4"}, + {QSFP_10GBASE_SR_MASK, "10GBASE-SR"}, {QSFP_10GBASE_LR_MASK, "10GBASE-LR"}, + {QSFP_10GBASE_LRM_MASK, "10GBASE-LRM"}, + }; + const struct sff_comp_info sff_comp[] = { + {QSFP_1000BASE_SX_MASK, "1000BASE-SX"}, {QSFP_1000BASE_LX_MASK, "1000BASE-LX"}, + {QSFP_1000BASE_CX_MASK, "1000BASE-CX"}, {QSFP_1000BASE_T_MASK, "1000BASE-T"}, + }; + uint32_t i; + + printf("%-24s: ", "transceiver_code"); + for (i = 0; i < SFF_TRANCEIV_LEN; i++) + printf("0x%02x ", info->page_upper.spec_compliance[i]); + + printf("| ext: 0x%02x\n", info->page_upper.link_codes); + + xsfp_show_mask(info->page_upper.spec_compliance[0], + sff_40g_comp, HIKP_ARRAY_SIZE(sff_40g_comp)); + xsfp_show_mask(info->page_upper.spec_compliance[3U], + sff_comp, HIKP_ARRAY_SIZE(sff_comp)); + + sff_print_ext_comp_code(info->page_upper.link_codes); +} + +static void qsfp_print_base_id_info(const struct qsfp_page0_info *info) +{ + printf("%-24s: 0x%02x\n", "identifier", info->page_upper.identifier); + printf("%-24s: 0x%02x\n", "connector", info->page_upper.connector); + printf("%-24s: 0x%02x\n", "encoding", info->page_upper.encoding); + printf("%-24s: %u (100MBd)\n", "br_nominal", info->page_upper.br_nominal); + printf("%-24s: 0x%02x\n", "rate_identifier", info->page_upper.ext_rate_sel); + printf("%-24s: %u (km)\n", "smf_len_km", info->page_upper.smf_len_km); + printf("%-24s: %u (m)\n", "om3_len", + (uint32_t)(info->page_upper.om3_len * QSFP_OM3_LEN_UNIT)); + printf("%-24s: %u (m)\n", "om2_len", info->page_upper.om2_len); + printf("%-24s: %u (m)\n", "om1_len", info->page_upper.om1_len); + printf("%-24s: %u (m)\n", "om4_cable_copper_len", info->page_upper.om4_cable_copper_len); + printf("%-24s: %d (nm)\n", "wavelength", + (((uint16_t)info->page_upper.wavelength[0] << 8U) | + (uint16_t)info->page_upper.wavelength[1]) / QSFP_WAVE_LEN_DIV); + printf("%-24s: %d (nm)\n", "wavelength_tolerance", + (((uint16_t)info->page_upper.wavelength_tolerance[0] << 8U) | + (uint16_t)info->page_upper.wavelength_tolerance[1]) / QSFP_TOL_WAVE_LEN_DIV); + printf("%-24s: 0x%02x\n", "device_technology", info->page_upper.device_technology); + + xsfp_print_data("vendor_name", VEND_NAME_LEN, info->page_upper.vendor_name, PRINT_ASCII); + xsfp_print_data("vendor_oui", VEND_OUI_LEN, info->page_upper.vendor_oui, PRINT_HEX); + xsfp_print_data("vendor_pn", VEND_PN_LEN, info->page_upper.vendor_pn, PRINT_ASCII); + xsfp_print_data("vendor_rev", QSFP_VEND_REV_LEN, info->page_upper.vendor_rev, PRINT_ASCII); + xsfp_print_data("vendor_sn", VEND_SN_LEN, info->page_upper.vendor_sn, PRINT_ASCII); + xsfp_print_data("vendor_date_code", VEND_DATE_CODE_LEN, + info->page_upper.date_code, PRINT_ASCII); + + printf("%-24s: 0x%02x(%s) support: 0x%02x(%s)\n", "high_power", + info->page_lower.high_pw_en, (info->page_lower.high_pw_en == 0) ? "No" : "Yes", + info->page_upper.pw_class_5_7, (info->page_upper.pw_class_5_7 == 0) ? "No" : "Yes"); + printf("%-24s: 0x%02x(%s) support: 0x%02x(%s)\n", "tx_disable", + info->page_lower.tx_disable, (info->page_lower.tx_disable == 0) ? "No" : "Yes", + info->page_upper.tx_dis_imp, (info->page_upper.tx_dis_imp == 0) ? "No" : "Yes"); + + qsfp_print_trans_comp_code(info); +} + +static void qsfp_print_channel_power(const char *str, const uint8_t *power_data) +{ + uint32_t i; + + for (i = 0; i < QSFP_CHAN_NUM; i++) + printf("%s%-16u: %u uW\n", str, i, + ntohs(*((unsigned short *)&(power_data[i * 2U]))) / 10U); +} + +static void qsfp_print_dom_info(const struct qsfp_page0_info *info) +{ + /* from 0xa to 0xf is copper, not support read power and temperature */ + if ((info->page_upper.device_technology >> QSFP_TRANS_TECH_BIT) > QSFP_TRANS_OPTICAL_MAX) + return; + + qsfp_print_channel_power("tx_power", info->page_lower.tx_power); + qsfp_print_channel_power("rx_power", info->page_lower.rx_power); + printf("%-24s: %d.%02u\n", "temperature", + (int8_t)info->page_lower.temperature_msb, info->page_lower.temperature_lsb); +} + +static void hikp_show_qsfp_info(const uint8_t *data, uint32_t size) +{ + struct qsfp_page0_info *qsfp_data = (struct qsfp_page0_info *)(data); + + printf("------------------------show qsfp info------------------------\n"); + qsfp_print_base_id_info(qsfp_data); + qsfp_print_dom_info(qsfp_data); + printf("--------------------------------------------------------------\n"); +} + +static void hikp_xsfp_parse_info(const uint8_t *data, uint32_t size) +{ + if (data[SFF_ID_OFFSET] == ID_SFP) { + hikp_show_sfp_info(data, size); + } else if (data[SFF_ID_OFFSET] == ID_QSFP || + data[SFF_ID_OFFSET] == ID_QSFP_PLUS || + data[SFF_ID_OFFSET] == ID_QSFP28) { + hikp_show_qsfp_info(data, size); + } else { + /* unknown type just dump hex data */ + hikp_xsfp_dump_hex(data, size); + } +} + +static int hikp_xsfp_get_raw_data(uint8_t *buf, uint32_t size, uint32_t blk_num) +{ + struct hikp_cmd_ret *cmd_resp = NULL; + uint32_t left_size = size; + uint32_t offset = 0; + uint32_t len = 0; + int ret; + uint32_t i; + + for (i = 0; i < blk_num && left_size > 0; i++) { + ret = hikp_xsfp_get_cmd_data(&cmd_resp, NIC_XSFP_GET_EEPROM_DATA, i); + if (ret != 0) { + HIKP_ERROR_PRINT("get optical module eeprom data failed\n"); + free(cmd_resp); + cmd_resp = NULL; + return ret; + } + + len = HIKP_MIN(left_size, (cmd_resp->rsp_data_num * sizeof(uint32_t))); + memcpy(buf + offset, (uint8_t *)(cmd_resp->rsp_data), len); + left_size -= len; + offset += len; + + /* current cmd interaction is complete, so free cmd_buf */ + free(cmd_resp); + cmd_resp = NULL; + } + + return 0; +} + +static void hikp_xsfp_get_eeprom_data(struct major_cmd_ctrl *self, uint32_t size, uint32_t blk_num) +{ + uint8_t *raw_data = (uint8_t *)calloc(1, size * sizeof(uint8_t)); + int ret; + + if (!raw_data) { + self->err_no = -ENOSPC; + HIKP_ERROR_PRINT("no space left for dump eeprom data\n"); + return; + } + + ret = hikp_xsfp_get_raw_data(raw_data, size, blk_num); + if (ret != 0) + goto ERR_OUT; + + if ((g_xsfp_dump.dump_param & XSFP_RAW_DATA_BIT) != 0) + hikp_xsfp_dump_hex(raw_data, size); + else + hikp_xsfp_parse_info(raw_data, size); + +ERR_OUT: + free(raw_data); + raw_data = NULL; +} + +static int hikp_xsfp_dump_pre_check(const struct hikp_xsfp_basic *info) +{ + if (info->media_type != MEDIA_TYPE_FIBER) { + printf("port media type %u not support get optical module info\n", + info->media_type); + return -EOPNOTSUPP; + } + + if (info->present_status == MODULE_ABSENT) { + printf("port optical module not present, cannot get module info\n"); + return -ENXIO; + } + + if (info->data_size < SFF_XSFP_DATA_LEN) { + printf("get data size %u less than xsfp min size %u\n", + info->data_size, SFF_XSFP_DATA_LEN); + return -EPERM; + } + + return 0; +} + +static void hikp_xsfp_get_info(struct major_cmd_ctrl *self) +{ + struct hikp_xsfp_basic *info = NULL; + struct hikp_cmd_ret *cmd_resp = NULL; + int ret; + + if ((g_xsfp_dump.dump_param & XSFP_TARGET_BIT) == 0) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "need port id"); + return; + } + + /* first get port basic info */ + ret = hikp_xsfp_get_cmd_data(&cmd_resp, NIC_XSFP_GET_BASIC_INFO, 0); + if (ret != 0) { + HIKP_ERROR_PRINT("get port basic info failed\n"); + self->err_no = ret; + goto ERR_OUT; + } + + info = (struct hikp_xsfp_basic *)(cmd_resp->rsp_data); + ret = hikp_xsfp_dump_pre_check(info); + if (ret != 0) { + self->err_no = ret; + goto ERR_OUT; + } + + hikp_xsfp_get_eeprom_data(self, info->data_size, info->total_blk_num); + +ERR_OUT: + free(cmd_resp); + cmd_resp = NULL; +} + +static int hikp_xsfp_show_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i [-d]"); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~3 or 0000:35:00.0"); + printf(" %s, %-25s %s\n", "-d", "--dump=", "dump optical module eeprom raw data"); + printf("\n"); + + return 0; +} + +static int hikp_xsfp_get_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &g_xsfp_dump.target); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + g_xsfp_dump.dump_param |= XSFP_TARGET_BIT; + + return 0; +} + +static int hikp_xsfp_dump_raw_data(struct major_cmd_ctrl *self, const char *argv) +{ + g_xsfp_dump.dump_param |= XSFP_RAW_DATA_BIT; + + return 0; +} + +static void cmd_get_xsfp_info(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_xsfp_get_info; + + cmd_option_register("-h", "--help", false, hikp_xsfp_show_help); + cmd_option_register("-i", "--interface", true, hikp_xsfp_get_target); + cmd_option_register("-d", "--dump", false, hikp_xsfp_dump_raw_data); +} + +HIKP_CMD_DECLARE("nic_xsfp", "query port optical module information", cmd_get_xsfp_info); diff --git a/net/nic/nic_mac/hikp_nic_xsfp.h b/net/nic/nic_mac/hikp_nic_xsfp.h new file mode 100644 index 0000000..a378197 --- /dev/null +++ b/net/nic/nic_mac/hikp_nic_xsfp.h @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2022 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_NIC_XSFP_H +#define HIKP_NIC_XSFP_H +#include "hikp_net_lib.h" + +#define SFF_XSFP_DATA_LEN 640 + +#define XSFP_PRINT_BLK 128 +#define XSFP_PRINT_COL 16 + +#define SFF_TRANCEIV_LEN 8 +#define SFF_WAVE_LEN_UNIT 256 + +#define SFF_CONNECTOR_COPPER 0x21 + +#define VEND_NAME_LEN 16 +#define VEND_OUI_LEN 3 +#define VEND_PN_LEN 16 +#define VEND_SN_LEN 16 +#define VEND_DATE_CODE_LEN 8 +#define VEND_SPEC_EEPROM_LEN 32 +#define VEND_SPEC_LEN 7 +#define VEND_USER_EEPROM_LEN 120 +#define VEND_CTRL_LEN 8 + +#define SFP_VEND_REV_LEN 4 + +#define QSFP_CHAN_NUM 4 +#define QSFP_VEND_REV_LEN 2 +#define QSFP_WAVE_LEN_DIV 20 +#define QSFP_TOL_WAVE_LEN_DIV 200 + +#define QSFP_OM3_LEN_UNIT 2 + +/* reg3: 10G Ethernet Compliance Codes mask */ +#define SFP_10GBASE_SR_MASK HI_BIT(4) +#define SFP_10GBASE_LR_MASK HI_BIT(5) +#define SFP_10GBASE_LRM_MASK HI_BIT(6) +#define SFP_10GBASE_ER_MASK HI_BIT(7) + +/* reg6: Ethernet Compliance Codes mask */ +#define SFP_1000BASE_SX_MASK HI_BIT(0) +#define SFP_1000BASE_LX_MASK HI_BIT(1) +#define SFP_1000BASE_CX_MASK HI_BIT(2) +#define SFP_1000BASE_T_MASK HI_BIT(3) +#define SFP_100BASE_LX_LX10_MASK HI_BIT(4) +#define SFP_100BASE_FX_MASK HI_BIT(5) +#define SFP_BASE_BX10_MASK HI_BIT(6) +#define SFP_BASE_PX_MASK HI_BIT(7) + +/* reg134: Gigabit Ethernet Compliance Codes mask */ +#define QSFP_1000BASE_SX_MASK HI_BIT(0) +#define QSFP_1000BASE_LX_MASK HI_BIT(1) +#define QSFP_1000BASE_CX_MASK HI_BIT(2) +#define QSFP_1000BASE_T_MASK HI_BIT(3) + +/* reg131: 10/40G/100G Ethernet Compliance Codes mask */ +#define QSFP_40G_ACT_CABLE_MASK HI_BIT(0) +#define QSFP_40GBASE_LR4_MASK HI_BIT(1) +#define QSFP_40GBASE_SR4_MASK HI_BIT(2) +#define QSFP_40GBASE_CR4_MASK HI_BIT(3) +#define QSFP_10GBASE_SR_MASK HI_BIT(4) +#define QSFP_10GBASE_LR_MASK HI_BIT(5) +#define QSFP_10GBASE_LRM_MASK HI_BIT(6) + +enum print_type { + PRINT_ASCII = 0, + PRINT_HEX, +}; + +#define SFF_ID_OFFSET 0 +enum sff_id_val { + ID_UNDEF = 0x0, + ID_SFP = 0x3, + ID_QSFP = 0x0C, + ID_QSFP_PLUS = 0x0D, + ID_QSFP28 = 0x11, +}; + +struct sff_comp_info { + uint8_t mask; + const char *description; +}; + +struct sff_ext_comp { + uint8_t val; + const char *module_cap; +}; + +struct sfp_a0_page { + uint8_t identifier; /* reg 0: Identifier */ + uint8_t ext_identifier; /* reg 1: Ext. Identifier */ + uint8_t connector; /* reg 2: Connector */ + uint8_t transceiver[SFF_TRANCEIV_LEN]; /* reg 3-10: Transceiver */ + uint8_t encoding; /* reg 11: Encoding */ + uint8_t br_nominal; /* reg 12: Nominal signalling rate, units of 100MBd. */ + uint8_t rate_identifier; /* reg 13: Type of rate select functionality */ + /* reg 14: Link length supported for single mode fiber, units of km */ + uint8_t len_smf_km; + /* reg 15: Link length supported for single mode fiber, units of 100 m */ + uint8_t len_smf; + /* reg 16: Link length supported for 50 um OM2 fiber, units of 10 m */ + uint8_t len_smf_om2; + /* reg 17: Link length supported for 62.5 um OM1 fiber, units of 10 m */ + uint8_t len_smf_om1; + /* reg 18: Link length supported for copper or direct attach cable, units of m */ + uint8_t len_cable; + /* reg 19: Link length supported for 50 um OM3 fiber, units of 10 m */ + uint8_t len_om3; + uint8_t vendor_name[VEND_NAME_LEN]; /* reg 20-35: Vendor name */ + uint8_t transceiver_code; /* reg 36: Code for electronic or optical compatibility */ + uint8_t vendor_oui[VEND_OUI_LEN]; /* reg 37-39: SFP vendor IEEE company ID */ + /* reg 40-55: Part number provided by SFP vendor (ASCII) */ + uint8_t vendor_pn[VEND_PN_LEN]; + /* reg 56-59: Revision level for part number provided by vendor (ASCII) */ + uint8_t vendor_rev[SFP_VEND_REV_LEN]; + /* reg 60-61: Laser wavelength (Passive/Active Cable Specification Compliance) */ + uint8_t wave_leng[2]; + uint8_t un_allocated; /* reg 62 */ + uint8_t ccbase; /* reg 63: Check code for Base ID Fields (addresses 0 to 62) */ + struct { /* reg 64-65: Option Values */ + uint8_t option_val; + uint8_t rsvd0 : 1; + uint8_t rx_los_imp : 1; + uint8_t sign_detect_imp : 1; + uint8_t tx_fault_imp : 1; + uint8_t tx_disable_imp : 1; + uint8_t rate_sel_imp : 1; + uint8_t rsvd1 : 2; + }; + uint8_t br_max; /* reg 66: Signaling Rate, max */ + uint8_t br_min; /* reg 67: Signaling Rate, min */ + uint8_t vendor_sn[VEND_SN_LEN]; /* reg 68-83: Vendor SN */ + uint8_t date_code[VEND_DATE_CODE_LEN]; /* reg 84-91: Date code */ + struct { /* reg 92: Diagnostic check Type */ + uint8_t rsvd2 : 2; + uint8_t addr_chge : 1; + uint8_t rx_power_measure_type : 1; + uint8_t ext_cal : 1; + uint8_t inter_cal : 1; + uint8_t ddm_imp : 1; + uint8_t rsvd_dm : 1; + }; + uint8_t enhanced_options; /* reg 93: Enhanced Options */ + uint8_t Sff_8472_compliance; /* reg 94: SFF-8472 Compliance */ + uint8_t cc_ext; /* reg 95: Check code for the Extended ID Fields (addresses 64 to 94) */ + + /* 96~255 */ + uint8_t vendor_spec[VEND_SPEC_EEPROM_LEN]; /* reg 96-127: Vendor Specific */ + uint8_t rsvd[128]; /* reg 128-255: Reserved */ +}; + +struct sfp_a2_page { + uint8_t temp_alarm_high[2]; /* reg 0-1: Temp High Alarm */ + uint8_t temp_alarm_low[2]; /* reg 2-3: Temp Low Alarm */ + uint8_t temp_warning_high[2]; /* reg 4-5: Temp High Warning */ + uint8_t temp_warning_low[2]; /* reg 6-7: Temp Low Warning */ + uint8_t vcc_alarm_high[2]; /* reg 8-9: Voltage High Alarm */ + uint8_t vcc_alarm_low[2]; /* reg 10-11: Voltage Low Alarm */ + uint8_t vcc_warning_high[2]; /* reg 12-13: Voltage High Warning */ + uint8_t vcc_warning_low[2]; /* reg 14-15: Voltage Low Warning */ + uint8_t bias_alarm_high[2]; /* reg 16-17: Bias High Alarm */ + uint8_t bias_alarm_low[2]; /* reg 18-19: Bias Low Alarm */ + uint8_t bias_warning_high[2]; /* reg 20-21: Bias High Warning */ + uint8_t bias_warning_low[2]; /* reg 22-23: Bias Low Warning */ + uint8_t tx_alarm_high[2]; /* reg 24-25: TX Power High Alarm */ + uint8_t tx_alarm_low[2]; /* reg 26-27: TX Power Low Alarm */ + uint8_t tx_warning_high[2]; /* reg 28-29: TX Power High Warning */ + uint8_t tx_warning_low[2]; /* reg 30-31: TX Power Low Warning */ + uint8_t rx_alarm_high[2]; /* reg 32-33: RX Power High Alarm */ + uint8_t rx_alarm_low[2]; /* reg 34-35: RX Power Low Alarm */ + uint8_t rx_warning_high[2]; /* reg 36-37: RX Power High Warning */ + uint8_t rx_warning_low[2]; /* reg 38-39: RX Power Low Warning */ + uint8_t opt_thres[16]; /* reg 40-55: Optional A/W Thresholds */ + /* reg 56-91: Ext Cal Constants or Additional Enhanced Features */ + uint8_t ext_cal_constants[36]; + uint8_t un_allocated1[3]; /* reg 92-94: Reserved */ + uint8_t cc_dmi; /* reg 95: CC_DMI */ + uint8_t temperature[2]; /* reg 96-97: Temperature MSB/LSB */ + uint8_t vcc[2]; /* reg 98-99: Vcc MSB/LSB */ + uint8_t tx_bias[2]; /* reg 100-101: TX Bias MSB/LSB */ + uint8_t tx_power[2]; /* reg 102-103: TX Power MSB/LSB */ + uint8_t rx_power[2]; /* reg 104-105: RX Power MSB/LSB */ + /* reg 106-109: Optional Laser Temp/Wavelength and Optional TEC current */ + uint8_t optional_val[4]; + struct { /* reg 110: Optional Status/Control */ + uint8_t data_rdy_bar_state : 1; + uint8_t rx_los_state : 1; + uint8_t tx_fault_state : 1; + uint8_t soft_rate_sel_state : 1; + uint8_t rate_sel_state : 1; + uint8_t rs_state : 1; + uint8_t soft_tx_dis_select : 1; + uint8_t tx_dis_state : 1; + }; + uint8_t rsvd; /* reg 111: Reserved */ + uint8_t alarm_warn_flag[6]; /* reg 112-117: Optional Alarm and Warning Flag */ + uint8_t ext_status_ctrl[2]; /* reg 118-119: Extended Module Control/Status */ + uint8_t vendor_spec[VEND_SPEC_LEN]; /* reg: 120-126: Vendor Specific */ + uint8_t opt_page_sel; /* reg: 127: Optional Page Select */ + uint8_t user_eeprom[VEND_USER_EEPROM_LEN]; /* reg: 128-247: User EEPROM */ + /* reg: 248-255: Vendor specific control functions */ + uint8_t vendor_ctrl[VEND_CTRL_LEN]; +}; + +/* SFF-8472 Rev 10.4 SFP */ +struct sfp_page_info { + struct sfp_a0_page page_a0; + struct sfp_a2_page page_a2; +}; + +#define QSFP_TRANS_TECH_BIT 4 +#define QSFP_TRANS_OPTICAL_MAX 0x9 + +struct qsfp_page0_lower { + uint8_t Identifier; /* reg 0: Identifier (1 Byte) */ + uint8_t revision_comp; /* reg 1: Revision Compliance */ + uint8_t status_indicator; /* reg 2: Status Indicators */ + uint8_t tx_rx_los; /* reg 3: Latched Tx/Rx LOS indicator */ + /* reg 4: Latched Tx input Adaptive EQ/Transmitter/Laser fault indicator */ + uint8_t tx_fault; + uint8_t tx_rx_lol; /* reg 5: Latched Tx/Rx CDR LOL indicator */ + uint8_t mon_intr_flags[3]; /* reg 6-8: Free Side check Interrupt Flags */ + uint8_t l_rx_pw_alarm[2]; /* reg 9-10: Latched Rx high/low power alarm/warning */ + uint8_t l_tx_bias_alarm[2]; /* reg 11-12: Latched Tx high/low bias alarm/warning */ + uint8_t l_tx_pw_alarm[2]; /* reg 13-14: Latched Tx high/low power alarm/warning */ + uint8_t rsvd0[2]; /* reg 15-16: Reserved channel check flags, set 4 */ + uint8_t rsvd1[2]; /* reg 17-18: Reserved channel check flags, set 5 */ + uint8_t rsvd_spec[3]; /* reg 19-21: Vendor Specific */ + uint8_t temperature_msb; /* reg 22: Temperature MSB */ + uint8_t temperature_lsb; /* reg 23: Temperature LSB */ + uint8_t rsvd2[2]; /* reg 24-25: Reserved */ + uint8_t supply_vol[2]; /* reg 26-27: Supply Voltage MSB/LSB */ + uint8_t rsvd3[6]; /* reg 28-33: Reserved */ + uint8_t rx_power[8]; /* reg 34-41: Rx Power */ + uint8_t tx_bias[8]; /* reg 42-49: Tx Bias */ + uint8_t tx_power[8]; /* reg 50-57: Tx Power */ + uint8_t rsvd4[8]; /* reg 58-65: Reserved channel check set 4 */ + uint8_t rsvd5[8]; /* reg 66-73: Reserved channel check set 5 */ + uint8_t rsvd6[8]; /* reg 74-81: Vendor Specific */ + uint8_t rsvd7[4]; /* reg 82-85: Reserved (4 Bytes) */ + uint8_t tx_disable; /* reg 86: Read/Write bit for software disable of Tx */ + uint8_t rx_rate_sel; /* reg 87: Rx Software rate select */ + uint8_t tx_rate_sel; /* reg 88: Tx Software rate select */ + uint8_t rsvd8[4]; /* reg 89-92: Reserved */ + struct { /* reg 93: Power control */ + uint8_t pw_override : 1; + uint8_t pw_set : 1; + uint8_t high_pw_en : 2; + uint8_t rsvd9 : 3; + uint8_t sw_reset : 1; + }; + uint8_t rsvd10[4]; /* reg 94-97: Reserved */ + uint8_t tx_rx_cdr_ctrl; /* reg 98: Tx/Rx_CDR_control */ + uint8_t signal_ctrl; /* reg 99: IntL/LOSL output/LPMode/TxDis input signal control */ + uint8_t tx_rx_los_mask; /* reg 100: Masking bit for Tx/Rx LOS */ + uint8_t tx_fault_mask; /* reg 101: Masking bit for Tx Fault */ + uint8_t tx_rx_cdr_lol_mask; /* reg 102: Masking bit for Tx/Rx CDR Loss of Lock */ + uint8_t temp_alarm; /* reg 103: Masking bit for high/low-temperature alarm */ + uint8_t vcc_alarm; /* reg 104: Masking bit for Vcc high/low alarm */ + uint8_t rsvd11[2]; /* reg 105-106: Vendor Specific */ + uint8_t fs_dev_properties[12]; /* reg 107-118: Free Side Device Properties */ + uint8_t pwd_entry_chge[8]; /* reg 119-126: Password Entry and Change */ + uint8_t page_select; /* reg 127: Page Select */ +}; + +struct qsfp_page0_upper { + uint8_t identifier; /* reg 128: Identifier Type of serial transceiver */ + struct { /* reg 129: Extended identifier of serial transceiver */ + uint8_t pw_class_5_7 : 2; + uint8_t rx_cdr_present : 1; + uint8_t tx_cdr_present : 1; + uint8_t clei_code_present : 1; + uint8_t pw_class_8_imp : 1; + uint8_t pw_class_1_4 : 2; + }; + uint8_t connector; /* reg 130: Code for connector type */ + /* reg 131-138: Code for electronic + * compatibility or optical compatibility + */ + uint8_t spec_compliance[SFF_TRANCEIV_LEN]; + uint8_t encoding; /* reg 139: Code for serial encoding algorithm */ + uint8_t br_nominal; /* reg 140: Nominal bit rate, units of 100 MBits/s. */ + uint8_t ext_rate_sel; /* reg 141: Tags for Extended RateSelect compliance */ + uint8_t smf_len_km; /* reg 142: Link length supported for SMF fiber in km */ + /* reg 143: Link length supported for EBW 50/125 fiber, units of 2 m */ + uint8_t om3_len; + /* reg 144: Link length supported for 50/125 fiber, units of 1 m */ + uint8_t om2_len; + /* reg 145: Link length supported for 62.5/125 fiber, units of 1 m */ + uint8_t om1_len; + /* reg 146: Link length supported for copper, units of 1m */ + uint8_t om4_cable_copper_len; + uint8_t device_technology; /* reg 147: Device technology */ + uint8_t vendor_name[VEND_NAME_LEN]; /* reg 148-163: QSFP vendor name (ASCII) */ + uint8_t extended_module; /* reg 164: Extended Transceiver Codes for InfiniBand */ + uint8_t vendor_oui[VEND_OUI_LEN]; /* reg 165-167: QSFP vendor IEEE company ID */ + /* reg 168-183: Part number provided by QSFP vendor (ASCII) */ + uint8_t vendor_pn[VEND_PN_LEN]; + /* reg 184-185: Revision level for part number provided by vendor (ASCII) */ + uint8_t vendor_rev[QSFP_VEND_REV_LEN]; + /* reg 186-187: Nominal laser wavelength (Wavelength = value / 20 in nm) */ + uint8_t wavelength[2]; + /* reg 188-189: Guaranteed range of laser wavelength (+/- value) from + * Nominal wavelength.(Wavelength Tol. = value/200 in nm) + */ + uint8_t wavelength_tolerance[2]; + uint8_t max_case_temp; /* reg 190: Maximum Case Temperature in Degrees C. */ + uint8_t cc_base; /* reg 191: Check code for Base ID Fields (addresses 128-190) */ + uint8_t link_codes; /* reg 192: Extended Specification Compliance Codes */ + /* reg 193-194: Optional features implemented */ + uint8_t option[2]; + /* reg 195: Rate Select, TX Disable, TX Fault, LOS */ + struct { + uint8_t page_20_21h_imp : 1; + uint8_t tx_loss_sign_imp : 1; + uint8_t tx_squelch_imp : 1; + uint8_t tx_fault_imp : 1; + uint8_t tx_dis_imp : 1; + uint8_t rate_sel_imp : 1; + uint8_t page_01h_imp : 1; + uint8_t page_02h_imp : 1; + }; + /* reg 196-211: Serial number provided by vendor (ASCII) */ + uint8_t vendor_sn[VEND_SN_LEN]; + /* reg 212-219: Vendor's manufacturing date code */ + uint8_t date_code[VEND_DATE_CODE_LEN]; + /* reg 220: Indicates which type of diagnostic check is implemented + * (if any) in the transceiver. Bit 1, 0 Reserved + */ + uint8_t ddm_type; + /* reg 221: Indicates which optional enhanced features are + * implemented in the transceiver. + */ + uint8_t enhanced_option; + /* reg 222: Reserved */ + uint8_t br_nominal_ext; + /* reg 223: Check code for the Extended ID Fields (addresses 192-222) */ + uint8_t cc_ext; + /* reg 224-255 */ + uint8_t reserved_a0_up1[32]; +}; + +struct qsfp_page0_info { + struct qsfp_page0_lower page_lower; + struct qsfp_page0_upper page_upper; +}; + +#define XSFP_TARGET_BIT HI_BIT(0) +#define XSFP_RAW_DATA_BIT HI_BIT(1) + +enum hikp_port_media_type { + MEDIA_TYPE_UNKNOWN = 0, + MEDIA_TYPE_FIBER, + MEDIA_TYPE_PHY, + MEDIA_TYPE_BACKPLANE, +}; + +enum hikp_xsfp_present { + MODULE_ABSENT = 0, + MODULE_PRESENT, +}; + +struct hikp_xsfp_basic { + uint32_t media_type; /* only fiber type port support get eeprom data */ + uint32_t present_status; /* optical module is or not insert */ + uint32_t data_size; /* eeprom data size, unit Byte */ + uint32_t total_blk_num; +}; + +struct hikp_xsfp_req { + struct bdf_t bdf; + uint32_t blk_id; +}; + +struct hikp_xsfp_ctrl { + struct tool_target target; + uint32_t dump_param; +}; + +#endif -- Gitee From 7f768e340ab9f81d59a45239bc8003e76ef33da1 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 15:05:39 +0800 Subject: [PATCH 05/14] support querying SERDES module information add dump SERDES module register information Signed-off-by: wangkang (cherry picked from commit e7685802e9eac9b8f9605d5c751331b6c2567b2f) --- CMakeLists.txt | 1 + serdes/hikp_serdes.c | 513 +++++++++++++++++++++++++++++++++++++++++++ serdes/hikp_serdes.h | 214 ++++++++++++++++++ 3 files changed, 728 insertions(+) create mode 100644 serdes/hikp_serdes.c create mode 100644 serdes/hikp_serdes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cb2944..7a5a0cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ file(GLOB_RECURSE HIKPTOOL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/net/*.c ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/serdes/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c ${CMAKE_CURRENT_SOURCE_DIR}/hikp_init_main.c ) diff --git a/serdes/hikp_serdes.c b/serdes/hikp_serdes.c new file mode 100644 index 0000000..89e66e1 --- /dev/null +++ b/serdes/hikp_serdes.c @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "tool_lib.h" +#include "tool_cmd.h" +#include "hikp_serdes.h" + +static struct cmd_serdes_param g_serdes_param = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +#define SERDES_OUTPUT_MAX_SIZE 2048 +static char g_serdes_data_out_buf[SERDES_OUTPUT_MAX_SIZE] = {0}; + +static int cmd_serdes_maininfo_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, + "-i -s -n [-k]"); + printf("\n %s, e.g. hikptool serdes_info -i 0 -s m3d0 -n 4 -k\n", + self->cmd_ptr->help_info); + printf("\n Options:\n\n" + " -h --help display the help info\n" + " -i --chipid chipid, usage: -i [chip_id], e.g. -i 0\n" + " -s --start_lane_id the start of lane id, " + "usage: -s m[macro_id]d[lane_id], e.g. -s m3d0\n" + " -n --lane_num lane num, usage: -n [lane_num], e.g. -n 4\n" + " -k --key_info show detail info with -k, brief info without -k\n"); + return 0; +} + +static int cmd_serdes_chipid(struct major_cmd_ctrl *self, const char *argv) +{ + int err; + uint8_t chip_id; + size_t len = strlen("chip"); + char *p_index = (char *)argv; + + if (strncmp(p_index, "chip", len) == 0) + p_index = p_index + len; + + err = string_toub(p_index, &chip_id); + if (err) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid chipid."); + self->err_no = err; + return err; + } + + g_serdes_param.chip_id = chip_id; + return 0; +} + +static int cmd_serdes_start_lane_id(struct major_cmd_ctrl *self, const char *argv) +{ + int64_t macro_id; + int64_t ds_id; + char *endptr = NULL; + const char *ptr = argv; + + if ((*ptr != 'm') && (*ptr != 'M')) + goto _START_LANE_ID_ERR_PRO_; + + ptr++; + macro_id = strtol(ptr, &endptr, 10); /* 10:decimal */ + if (endptr <= ptr) + goto _START_LANE_ID_ERR_PRO_; + + ptr = endptr; + if ((*ptr != 'd') && (*ptr != 'D')) + goto _START_LANE_ID_ERR_PRO_; + + ptr++; + ds_id = strtol(ptr, &endptr, 10); /* 10:decimal */ + if ((endptr <= ptr) || (*endptr != 0)) + goto _START_LANE_ID_ERR_PRO_; + + if ((macro_id < 0) || (macro_id > UCHAR_MAX) || (ds_id < 0) || (ds_id > UCHAR_MAX)) + goto _START_LANE_ID_ERR_PRO_; + + g_serdes_param.macro_id = (uint8_t)macro_id; + g_serdes_param.start_sds_id = (uint8_t)ds_id; + return 0; + +_START_LANE_ID_ERR_PRO_: + snprintf(self->err_str, sizeof(self->err_str), "Invalid start_lane_id.e.g. m4d1"); + self->err_no = -EINVAL; + return -EINVAL; +} + +static int cmd_serdes_lane_num(struct major_cmd_ctrl *self, const char *argv) +{ + uint8_t lane_num; + + self->err_no = string_toub(argv, &lane_num); + if (self->err_no || lane_num == 0) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid lane_num."); + return self->err_no; + } + + g_serdes_param.sds_num = lane_num; + return 0; +} + +static int cmd_serdes_key_info_pro(struct major_cmd_ctrl *self, const char *argv) +{ + g_serdes_param.sub_cmd = 1; + return 0; +} + +#define USEMODE_SSC_STR_MAXLEN 20 +static void hikp_serdes_brief_info_print(struct major_cmd_ctrl *self, + const struct hilink_brief_info *data, uint32_t data_size) +{ + uint8_t ds_id; + uint8_t start_sds_id = g_serdes_param.start_sds_id; + uint8_t sds_num = g_serdes_param.sds_num; + char usemode_ssc_str[USEMODE_SSC_STR_MAXLEN] = {0}; + const char *usemode_array[HILINK_USE_MODE_END] = { + "default", "pcie", "sata", "sas", "hccs", + "eth", "fc", "cxl", "roh", "eth_roh", "roh_eth", "ubn" + }; + const char *ssc_type_array[HILINK_SSC_TYPE_END] = { + "nossc", "ssc", "mssc_in", "mssc_s", "mssc_n", "mssc_w", "mssc_e" + }; + + if (data_size != sds_num) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "serdes brief info data size is wrong."); + return; + } + + for (ds_id = 0; ds_id < sds_num; ds_id++) { + if (data[ds_id].usemode >= HILINK_USE_MODE_END) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "usemode[%u] is out of range.", data[ds_id].usemode); + return; + } + strncpy(usemode_ssc_str, usemode_array[data[ds_id].usemode], + sizeof(usemode_ssc_str) - 1); + + if (data[ds_id].ssc_type >= HILINK_SSC_TYPE_END) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "ssc_type[%u] is out of range.", data[ds_id].ssc_type); + return; + } + if (data[ds_id].usemode < HILINK_USE_MODE_HCCS) { + strncat(usemode_ssc_str, ",", HIKP_STR_BUF_LEFT_LEN(usemode_ssc_str)); + strncat(usemode_ssc_str, ssc_type_array[data[ds_id].ssc_type], + HIKP_STR_BUF_LEFT_LEN(usemode_ssc_str)); + } + printf("chip%u (M%u,ds%d) pll(%u, %u) pn(%u, %u) power(%u, %u)" + "(refclk_sel:%u) rate(%u, %u Mhz) usemode(%s)\n", + g_serdes_param.chip_id, g_serdes_param.macro_id, + ds_id + start_sds_id, data[ds_id].tx_cs_sel, data[ds_id].rx_cs_sel, + data[ds_id].tx_pn, data[ds_id].rx_pn, + data[ds_id].tx_power, data[ds_id].rx_power, + data[ds_id].refclk_sel, data[ds_id].tx_data_rate_mhz, + data[ds_id].rx_data_rate_mhz, usemode_ssc_str); + } +} + +#define KEY_INFO_TITLE \ + ("Brief Data format\n" \ + "FFE: [pre2 pre1 main post1 post2]\n" \ + "CTLE: [ALOS,LPBK,GN1,GN2,GN3,BST1,BST2,BST3,ZA1,ZA2,ZA3,SQH1,SQH2,SQH3," \ + "CMBAND1,CMBAND2,CMBAND3,RMBAND1,RMBAND2,RMBAND3]\n" \ + "DFE:[Tap1,Tap2,Tap3,Tap4,Tap5,Tap6,Tap7,Tap8,Tap9,Tap10,Tap11,Tap12,Tap13,Tap14,Tap15," \ + "Tap16,Tap17,Tap18,Tap19,Tap20]\n" \ + "FWFourEye: It only takes effect when the firmware is running and " \ + "continuous adaptation is turned on\n" \ + "-----------------------------------------------------" \ + "------------------------------------------------" \ + "-----------------------------------------------------" \ + "------------------------------------------------" \ + "-------------------\n" \ + " [ FFE ]" \ + "[ CTLE ]" \ + "[ " \ + "DFE ]" \ + "[ FWFourEye ][ snr ]\n" \ + "-----------------------------------------------------" \ + "-------------------------------------------------" \ + "-----------------------------------------------------" \ + "-------------------------------------------------" \ + "------------------\n") + +static void hikp_serdes_detail_info_print(struct major_cmd_ctrl *self, + const struct hilink_detail_info *data, + uint32_t data_size) +{ + uint32_t i; + uint8_t ds_id; + uint8_t start_sds_id = g_serdes_param.start_sds_id; + uint8_t sds_num = g_serdes_param.sds_num; + + if (data_size != sds_num) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "serdes detail info data size is wrong."); + return; + } + printf(KEY_INFO_TITLE); + for (ds_id = 0; ds_id < sds_num; ds_id++) { + printf("chip%u (M%u,ds%d) [%3d,%3d,%3u,%3d,%3d]", + g_serdes_param.chip_id, g_serdes_param.macro_id, ds_id + start_sds_id, + data[ds_id].tx_cfg.fir_pre2, data[ds_id].tx_cfg.fir_pre1, + data[ds_id].tx_cfg.fir_main, data[ds_id].tx_cfg.fir_post1, + data[ds_id].tx_cfg.fir_post2); + printf("[%u,%u", data[ds_id].alos_status, data[ds_id].loopback_type); + for (i = 0; i < HILINK_SERDES_RX_PARA_COUNT; i++) + printf(",%2u", data[ds_id].rx_ctle_cfg.data[i]); + + printf("]["); + for (i = 0; i < HILINK_SERDES_RX_TAP_COUNT; i++) + printf("%3d,", data[ds_id].rx_tap_cfg.tap_value[i]); + + printf("][%4d,%4d,%4d,%4d]", + data[ds_id].eye_diagram.top, data[ds_id].eye_diagram.bottom, + data[ds_id].eye_diagram.left, data[ds_id].eye_diagram.right); + printf("[%7d]\n", data[ds_id].snr); + } +} + +static void hikp_serdes_logout_init(struct hilink_cmd_out *logout, char *buffer, + uint32_t size, uint32_t type) +{ + logout->str_len = size; + logout->result_offset = 0; + logout->out_str = buffer; + logout->type = type; + logout->ret_val = 0; +} + +static int hikp_serdes_info_para_check(struct major_cmd_ctrl *self) +{ + if (g_serdes_param.chip_id == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need chip id."); + return self->err_no; + } + + if (g_serdes_param.macro_id == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need macro id."); + return self->err_no; + } + + if (g_serdes_param.start_sds_id == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need lane id."); + return self->err_no; + } + + if (g_serdes_param.sds_num == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need lane num."); + return self->err_no; + } + + if (g_serdes_param.sub_cmd == 0xff) + g_serdes_param.sub_cmd = 0; + + return 0; +} + +static void hikp_serdes_info_cmd_execute(struct major_cmd_ctrl *self) +{ + struct hikp_cmd_header req_header = {0}; + struct hikp_cmd_ret *cmd_ret; + struct hilink_cmd_in hilink_cmd = {0}; + struct hilink_brief_info *brief_info_data = NULL; + struct hilink_detail_info *detail_info_data = NULL; + struct hilink_cmd_out out_put; + size_t out_out_header_size; + int ret; + + ret = hikp_serdes_info_para_check(self); + if (ret != 0) + return; + + hikp_serdes_logout_init(&out_put, g_serdes_data_out_buf, SERDES_OUTPUT_MAX_SIZE, 0); + + hilink_cmd.cmd_type = SERDES_KEY_INFO; + hilink_cmd.sub_cmd = g_serdes_param.sub_cmd; + hilink_cmd.cmd_para.chip_id = g_serdes_param.chip_id; + hilink_cmd.cmd_para.macro_id = g_serdes_param.macro_id; + hilink_cmd.cmd_para.start_sds_id = g_serdes_param.start_sds_id; + hilink_cmd.cmd_para.sds_num = g_serdes_param.sds_num; + + hikp_cmd_init(&req_header, SERDES_MOD, SERDES_KEY_INFO, g_serdes_param.sub_cmd); + cmd_ret = hikp_cmd_alloc(&req_header, &hilink_cmd, sizeof(hilink_cmd)); + if (cmd_ret == NULL) { + snprintf(self->err_str, sizeof(self->err_str), "hikp_cmd_alloc err."); + self->err_no = -EINVAL; + return; + } + out_out_header_size = sizeof(out_put.str_len) + sizeof(out_put.result_offset) + + sizeof(out_put.type) + sizeof(out_put.ret_val); + memcpy(&out_put, cmd_ret->rsp_data, out_out_header_size); + + if ((cmd_ret->rsp_data_num * sizeof(uint32_t) - out_out_header_size) > + SERDES_OUTPUT_MAX_SIZE) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "serdes_info rsp_data data copy size error, data size:0x%x max size:0x%x.", + (cmd_ret->rsp_data_num * sizeof(uint32_t) - out_out_header_size), + SERDES_OUTPUT_MAX_SIZE); + goto err_out; + } + memcpy(out_put.out_str, cmd_ret->rsp_data + out_out_header_size / sizeof(uint32_t), + cmd_ret->rsp_data_num * sizeof(uint32_t) - out_out_header_size); + + if (g_serdes_param.sub_cmd > 0) { + detail_info_data = (struct hilink_detail_info *)out_put.out_str; + hikp_serdes_detail_info_print(self, detail_info_data, + out_put.result_offset / + sizeof(struct hilink_detail_info)); + } else { + brief_info_data = (struct hilink_brief_info *)out_put.out_str; + hikp_serdes_brief_info_print(self, brief_info_data, + out_put.result_offset / + sizeof(struct hilink_brief_info)); + } + +err_out: + free(cmd_ret); +} + +static void cmd_serdes_maininfo_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_serdes_info_cmd_execute; + + cmd_option_register("-h", "--help", false, cmd_serdes_maininfo_help); + cmd_option_register("-i", "--chipid", true, cmd_serdes_chipid); + cmd_option_register("-s", "--start_lane_id", true, cmd_serdes_start_lane_id); + cmd_option_register("-n", "--lane_num", true, cmd_serdes_lane_num); + cmd_option_register("-k", "--key_info", false, cmd_serdes_key_info_pro); +} + +static int cmd_serdes_dump_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, + "-c -i -s "); + printf("\n %s, e.g. hikptool serdes_dump -c cs -i 0 -s m0d0\n", + self->cmd_ptr->help_info); + printf("\n Options:\n\n" + " -h --help display the help info\n" + " -i --chipid chipid, usage: -i [chip_id], e.g. -i 0\n" + " -s --start_lane_id the start of lane id, " + "usage: -s m[macro_id]d[lane_id], e.g. -s m3d0\n" + " -c --subcmd subcmd, usage: -c [subcmd], e.g. -c cs/ds/subctrl\n"); + return 0; +} + +static int cmd_serdes_dump_subcmds(struct major_cmd_ctrl *self, const char *argv) +{ + const char *set_cmds[HILINK_DUMP_TYPE_END] = { "cs", "ds", "csds", "ram", "subctrl"}; + uint8_t i; + + for (i = 0; i < HILINK_DUMP_TYPE_END; i++) { + if (strcmp(argv, set_cmds[i]) == 0) + goto _SERDES_DUMP_SUBCMD_PRO_; + } + + snprintf(self->err_str, sizeof(self->err_str), "Invalid dump subcmd."); + self->err_no = -EINVAL; + return -EINVAL; + +_SERDES_DUMP_SUBCMD_PRO_: + g_serdes_param.sub_cmd = (enum hilink_dump_type_e)i; + return 0; +} + +static void hikp_serdes_dump_print(struct major_cmd_ctrl *self, + const uint32_t *data, uint32_t data_size) +{ + uint32_t i; + + /* 2: Check whether addresses and values are paired */ + if (data_size == 0 || data_size % 2 != 0) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "serdes dump data size is wrong."); + return; + } + + printf("\n[-------Macro%uCS/DS%u-------]\nAddr Value", + g_serdes_param.macro_id, g_serdes_param.start_sds_id); + for (i = 0; i < data_size; i += 2) { /* 2: Addresses and values are paired */ + printf("\n0x%04x 0x%08x", data[i], data[i + 1]); + } + printf("\n"); +} + +static int hikp_serdes_dump_para_check(struct major_cmd_ctrl *self) +{ + if (g_serdes_param.sub_cmd == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need subcmd."); + return self->err_no; + } + + if (g_serdes_param.chip_id == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need chip id."); + return self->err_no; + } + + if (g_serdes_param.macro_id == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need macro id."); + return self->err_no; + } + + if (g_serdes_param.start_sds_id == 0xff) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Need lane id."); + return self->err_no; + } + + return 0; +} + +static void hikp_serdes_dump_cmd_execute(struct major_cmd_ctrl *self) +{ + struct hikp_cmd_header req_header = {0}; + struct hikp_cmd_ret *cmd_ret; + struct hilink_cmd_in hilink_cmd = {0}; + uint32_t *dump_data = NULL; + struct hilink_cmd_out out_put; + size_t out_out_header_size; + int ret; + + ret = hikp_serdes_dump_para_check(self); + if (ret != 0) + return; + + hikp_serdes_logout_init(&out_put, g_serdes_data_out_buf, SERDES_OUTPUT_MAX_SIZE, 0); + + hilink_cmd.cmd_type = SERDES_DUMP_REG; + hilink_cmd.sub_cmd = g_serdes_param.sub_cmd; + hilink_cmd.cmd_para.chip_id = g_serdes_param.chip_id; + hilink_cmd.cmd_para.macro_id = g_serdes_param.macro_id; + hilink_cmd.cmd_para.start_sds_id = g_serdes_param.start_sds_id; + + hikp_cmd_init(&req_header, SERDES_MOD, SERDES_DUMP_REG, g_serdes_param.sub_cmd); + cmd_ret = hikp_cmd_alloc(&req_header, &hilink_cmd, sizeof(hilink_cmd)); + if (cmd_ret == NULL) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "hikp_cmd_alloc err."); + return; + } + out_out_header_size = sizeof(out_put.str_len) + sizeof(out_put.result_offset) + + sizeof(out_put.type) + sizeof(out_put.ret_val); + memcpy(&out_put, cmd_ret->rsp_data, out_out_header_size); + + if ((cmd_ret->rsp_data_num * sizeof(uint32_t) - out_out_header_size) > + SERDES_OUTPUT_MAX_SIZE) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "serdes_dump rsp_data data copy size error, data size:0x%x max size:0x%x.", + (cmd_ret->rsp_data_num * sizeof(uint32_t) - out_out_header_size), + SERDES_OUTPUT_MAX_SIZE); + goto err_out; + } + memcpy(out_put.out_str, cmd_ret->rsp_data + out_out_header_size / sizeof(uint32_t), + cmd_ret->rsp_data_num * sizeof(uint32_t) - out_out_header_size); + if (out_put.type == 1) { /* 0:data; 1:string */ + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "serdes dump data type is string, buffer is not enough."); + goto err_out; + } + + dump_data = (uint32_t *)out_put.out_str; + hikp_serdes_dump_print(self, dump_data, out_put.result_offset / sizeof(uint32_t)); +err_out: + free(cmd_ret); +} + +static void cmd_serdes_dump_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_serdes_dump_cmd_execute; + + cmd_option_register("-h", "--help", false, cmd_serdes_dump_help); + cmd_option_register("-c", "--subcmd", true, cmd_serdes_dump_subcmds); + cmd_option_register("-i", "--chipid", true, cmd_serdes_chipid); + cmd_option_register("-s", "--start_lane_id", true, cmd_serdes_start_lane_id); +} + +HIKP_CMD_DECLARE("serdes_dump", "serdes_dump cmd", cmd_serdes_dump_init); +HIKP_CMD_DECLARE("serdes_info", "serdes_info cmd", cmd_serdes_maininfo_init); diff --git a/serdes/hikp_serdes.h b/serdes/hikp_serdes.h new file mode 100644 index 0000000..99b9b15 --- /dev/null +++ b/serdes/hikp_serdes.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2022 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_SERDES_H__ +#define __HIKP_SERDES_H__ + +#include +#include +#include +#include +#include +#include "tool_lib.h" + +#define __SERDES_DESC(x) 1 + +enum serdes_cmd_type_e { + SERDES_SYS_RESERVE0 = 0, + SERDES_SYS_RESERVE1 = 1, + SERDES_SYS_RESERVE2 = 2, + SERDES_HILINK_INIT = 3, + SERDES_NORMAL_ADAPT = 4, + SERDES_DATA_RATE_SWITCH = 5, + SERDES_GET_DS_POWER_STATE = 6, + SERDES_SET_DS_POWER_DOWN = 7, + SERDES_MACRO_POWER_UP = 8, + SERDES_MACRO_POWER_DOWN = 9, + SERDES_PLL_POWER_DOWN = 10, + SERDES_LANE_RESET = 11, + SERDES_MCU_RESET = 12, + SERDES_GET_TX_CFG = 13, + SERDES_SET_TX_CFG = 14, + SERDES_GET_RX_CFG = 15, + SERDES_SET_RX_CFG = 16, + SERDES_CDR_CFG = 17, + SERDES_RX_ADAPT = 18, + SERDES_GET_VOLTAGE = 19, + SERDES_COUPLE_SEL = 20, + SERDES_GET_IMPEDANCE = 21, + SERDES_LOOPBACK = 22, + SERDES_PRBS = 23, + SERDES_FOUR_EYE_SCAN = 24, + SERDES_FULL_EYE_SCAN = 25, + SERDES_GET_SNR = 26, + SERDES_SSC = 27, + SERDES_GET_PN = 28, + SERDES_SET_PN = 29, + SERDES_GET_BITORDER = 30, + SERDES_SET_BITORDER = 31, + SERDES_KEY_INFO = 32, + SERDES_DPM_INFO = 33, + SERDES_REG_READ_BY_ADDR = 34, + SERDES_REG_READ_BY_NAME = 35, + SERDES_REG_WRITE_BY_ADDR = 36, + SERDES_REG_WRITE_BY_NAME = 37, + SERDES_DUMP_REG = 38, + SERDES_GET_ADAPT_LOG = 39, + SERDES_GET_PCIE_LINK_LOG = 40, + SERDES_GREENBOX = 41, + SERDES_GET_FW_VERSION = 42, + SERDES_FW_LOAD = 43, + SERDES_GET_VERSION = 44, + SERDES_TYPE_NUM +}; + +enum hilink_dump_type_e { + HILINK_SERDES_REG_CS = 0, + HILINK_SERDES_REG_DS, + HILINK_SERDES_REG_CSDS, + HILINK_SERDES_REG_RAM, + HILINK_SUBCTRL_REG, + HILINK_DUMP_TYPE_END +}; + +enum hilink_use_mode_e { + HILINK_USE_MODE_NORMAL = 0, + HILINK_USE_MODE_PCIE, + HILINK_USE_MODE_SATA, + HILINK_USE_MODE_SAS, + HILINK_USE_MODE_HCCS, + HILINK_USE_MODE_ETH, + HILINK_USE_MODE_FC, + HILINK_USE_MODE_CXL, + HILINK_USE_MODE_ROH, + HILINK_USE_MODE_ETH_ROH, /* lane0~3:roh, lane4~7:eth */ + HILINK_USE_MODE_ROH_ETH, /* lane0~3:eth, lane4~7:roh */ + HILINK_USE_MODE_UBN, + HILINK_USE_MODE_END +}; + +enum hilink_ssc_type_e { + HILINK_NO_SSC = 0, + HILINK_SINGLE_SSC, + HILINK_MULTI_SSC_FROM_INSIDE, + HILINK_MULTI_SSC_FROM_SOUTH, + HILINK_MULTI_SSC_FROM_NORTH, + HILINK_MULTI_SSC_FROM_WEST, + HILINK_MULTI_SSC_FROM_EAST, + HILINK_SSC_TYPE_END +}; + +struct cmd_serdes_param { + uint8_t chip_id; + uint8_t macro_id; + uint8_t start_sds_id; + uint8_t sds_num; + uint8_t val; + uint8_t sub_cmd; + uint8_t rsvd1; + uint8_t rsvd2; +}; + +struct hilink_cmd_general { + uint32_t chip_id : 16; + uint32_t macro_id : 16; + uint32_t start_sds_id : 16; + uint32_t sds_num : 16; +}; + +#define CMD_ARRAY_BUF_SIZE 64 + +struct hilink_cmd_in { + struct hilink_cmd_general cmd_para; + + uint32_t cmd_type : 8; + uint32_t sub_cmd : 8; + uint32_t rw : 1; /* 0: read, 1: write */ + uint32_t rsvd : 15; + + uint32_t val; + union { + char field[CMD_ARRAY_BUF_SIZE]; + uint32_t addr; + void *ex_param; /* Extended parameters */ + }; +}; + +struct hilink_cmd_out { + uint32_t str_len; /* out_str length */ + uint32_t result_offset; + uint32_t type; /* 0:data; 1:string */ + unsigned int ret_val; + char *out_str; +}; + +struct hilink_tx_param { + int8_t fir_pre3; /* -16~15 */ + int8_t fir_pre2; /* -16~15 */ + int8_t fir_pre1; /* -30~30 */ + uint8_t fir_main; /* 0~63 */ + int8_t fir_post1; /* -30~30 */ + int8_t fir_post2; /* -16~15 */ + uint8_t swing; /* H60: hswing_en; Other: swing */ + int8_t rsv; +}; + +#define HILINK_SERDES_RX_PARA_COUNT 18 +struct hilink_rx_param { + uint8_t data[HILINK_SERDES_RX_PARA_COUNT]; + uint8_t hilink_ip; /* defined by HILINK_IP_E */ + uint8_t rsvd; +}; + +#define HILINK_SERDES_RX_TAP_COUNT 24 +struct hilink_serdes_rx_tap { + int16_t tap_value[HILINK_SERDES_RX_TAP_COUNT]; + uint8_t hilink_ip; /* defined by HILINK_IP_E */ + uint8_t rsvd_0; + uint16_t rsvd_1; +}; + +struct hilink_4p_eye_result { + int32_t bottom; + int32_t top; + int32_t left; + int32_t right; +}; + +struct hilink_detail_info { + struct hilink_tx_param tx_cfg; + uint8_t alos_status; + uint8_t loopback_type; + struct hilink_rx_param rx_ctle_cfg; + struct hilink_serdes_rx_tap rx_tap_cfg; + struct hilink_4p_eye_result eye_diagram; + uint32_t snr; +}; + +struct hilink_brief_info { + uint32_t tx_cs_sel : 1; /* [0] */ + uint32_t rx_cs_sel : 1; /* [1] */ + uint32_t tx_pn : 1; /* [2] */ + uint32_t rx_pn : 1; /* [3] */ + uint32_t tx_power : 1; /* [4] */ + uint32_t rx_power : 1; /* [5] */ + uint32_t refclk_sel : 1; /* [6] */ + uint32_t rsvd_0 : 9; /* [7:15] */ + uint32_t usemode : 8; /* [16:23] */ + uint32_t ssc_type : 8; /* [24:31] */ + uint32_t tx_data_rate_mhz; + uint32_t rx_data_rate_mhz; + uint32_t rsvd_1; +}; + +#endif -- Gitee From 34fc831262951b7845684222d357ed6c52963727 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:20:56 +0800 Subject: [PATCH 06/14] support querying CXL module information including the I/O link, MEM link, CPA/DL register, MEMAR_BAR, and RCRB information Signed-off-by: hesiyuan (cherry picked from commit 99eb7b4e6a07a14a00e6cb3d239e65d5e81dcad7) --- CMakeLists.txt | 1 + cxl/func_lib/cxl_func/cxl_feature.c | 387 ++++++++++++++++++ cxl/func_lib/cxl_func/cxl_feature.h | 410 ++++++++++++++++++++ cxl/usr_cmd/cmd_analysis/cxl_cmd_cpa.c | 145 +++++++ cxl/usr_cmd/cmd_analysis/cxl_cmd_dl.c | 145 +++++++ cxl/usr_cmd/cmd_analysis/cxl_cmd_membar.c | 122 ++++++ cxl/usr_cmd/cmd_analysis/cxl_cmd_rcrb.c | 134 +++++++ cxl/usr_cmd/cmd_analysis/cxl_tool_include.h | 24 ++ 8 files changed, 1368 insertions(+) create mode 100644 cxl/func_lib/cxl_func/cxl_feature.c create mode 100644 cxl/func_lib/cxl_func/cxl_feature.h create mode 100644 cxl/usr_cmd/cmd_analysis/cxl_cmd_cpa.c create mode 100644 cxl/usr_cmd/cmd_analysis/cxl_cmd_dl.c create mode 100644 cxl/usr_cmd/cmd_analysis/cxl_cmd_membar.c create mode 100644 cxl/usr_cmd/cmd_analysis/cxl_cmd_rcrb.c create mode 100644 cxl/usr_cmd/cmd_analysis/cxl_tool_include.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a5a0cf..b38417f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ macro(get_header_dir_recurse HEADER_DIR_LIST) endmacro() file(GLOB_RECURSE HIKPTOOL_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/cxl/*.c ${CMAKE_CURRENT_SOURCE_DIR}/net/*.c ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c diff --git a/cxl/func_lib/cxl_func/cxl_feature.c b/cxl/func_lib/cxl_func/cxl_feature.c new file mode 100644 index 0000000..6de3f89 --- /dev/null +++ b/cxl/func_lib/cxl_func/cxl_feature.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "cxl_feature.h" + +static void cxl_cpa_err_print(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_cpa err msg info:\n"); + for (i = 0; i < data_unit_len; i++) + printf(" [0x%04x] : 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_cpa_config_print(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_cpa key cfg info:\n"); + for (i = 0; i < data_unit_len; i++) + printf(" [0x%04x] : 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_cpa_mmrg_window_print(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i, j, offset, data_each_port; + + data_each_port = data_unit_len / CXL_HDM_CNT_EACH_PORT; + if (data_unit_len % CXL_HDM_CNT_EACH_PORT != 0 || + data_each_port != CPA_MMRG_MSG_INFO_CNT) { + printf(" data alignment alarm: data len[%u]\n", data_unit_len); + goto nonformat_print; + } + + printf(" cxl_cpa mmrg info:\n"); + for (i = 0; i < CXL_HDM_CNT_EACH_PORT; i++) { + printf(" Hdm%u mmrg window show list:\n", i); + offset = i * data_each_port; + for (j = 0; j < data_each_port; j++) + printf(" [0x%04x] : 0x%08x\n", + data[j + offset].data_addr, data[j + offset].data); + } + return; +nonformat_print: + printf(" cxl_cpa mmrg info:\n"); + for (i = 0; i < data_unit_len; i++) + printf(" [0x%04x] : 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_cpa_dump_reg_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_cpa reg dump list:\n"); + printf(" Addr Value\n"); + for (i = 0; i < data_unit_len; i++) + printf(" 0x%04x 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_dl_fsm_str_get(struct cxl_fsm_state_str *fsm_str_table, + char **fsm_s, uint32_t fsm_state) +{ + int i = 0; + + while (fsm_str_table[i].fsm_state >= 0) { + if ((uint32_t)fsm_str_table[i].fsm_state != fsm_state) { + i++; + continue; + } + break; + } + + *fsm_s = fsm_str_table[i].fsm_str; +} + +static void cxl_dl_fsm_state_print(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + union cxl_dl_fsm_state_reg reg; + char *fsm_s = NULL; + struct cxl_fsm_state_str rrsm_state[] = { + {0x0, "retry_remote_normal"}, + {0x1, "retry_llrack"}, + {-1, "unknow"} + }; + struct cxl_fsm_state_str lrsm_state[] = { + {0x1, "retry_local_normal"}, + {0x2, "retry_llrreq"}, + {0x4, "retry_phy_reinit"}, + {0x8, "retry_local_idle"}, + {0x10, "retry_abort"}, + {-1, "unknow"} + }; + struct cxl_fsm_state_str init_fsm_state[] = { + {0x1, "inactive"}, + {0x2, "retry"}, + {0x4, "param"}, + {0x8, "active"}, + {-1, "unknow"} + }; + + if (data_unit_len == 0) { + printf("cxl dump data size is wrong.\n"); + return; + } + reg.val = data[0].data; + cxl_dl_fsm_str_get(rrsm_state, &fsm_s, reg.bits.rrsm_state); + printf(" %-25s : %s[%04x]\n", "cxl_dl_rrsm_state", fsm_s, reg.bits.rrsm_state); + cxl_dl_fsm_str_get(lrsm_state, &fsm_s, reg.bits.lrsm_state); + printf(" %-25s : %s[%04x]\n", "cxl_dl_lrsm_state", fsm_s, reg.bits.lrsm_state); + cxl_dl_fsm_str_get(init_fsm_state, &fsm_s, reg.bits.init_fsm_state); + printf(" %-25s : %s[%04x]\n", "cxl_dl_init_fsm_state", fsm_s, reg.bits.init_fsm_state); +} + +static void cxl_dl_dfx_print(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_dl dfx info:\n"); + for (i = 0; i < data_unit_len; i++) + printf(" [0x%04x] : [0x%08x]\n", data[i].data_addr, data[i].data); +} + +static void cxl_dl_dump_reg_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_dl reg dump list:\n"); + printf(" Addr Value\n"); + for (i = 0; i < data_unit_len; i++) + printf(" 0x%04x 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_dl_error_info_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_dl err info:\n"); + for (i = 0; i < data_unit_len; i++) + printf(" [0x%04x] : 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_link_info0_prt(uint32_t data) +{ + union cxl_rcrb_vendor_spec_header reg; + + reg.val = data; + printf(" %-20s : 0x%x\n", "cxl.cache capable", reg.bits.cache_capable); + printf(" %-20s : 0x%x\n", "cxl.io capable", reg.bits.io_capable); + printf(" %-20s : 0x%x\n", "cxl.mem capable", reg.bits.mem_capable); +} + +static void cxl_link_info1_prt(uint32_t data) +{ + union cxl_rcrb_flex_bus_ctrl reg; + + reg.val = data; + printf(" %-20s : 0x%x\n", "cxl.cache enable", reg.bits.cache_enable); + printf(" %-20s : 0x%x\n", "cxl.io enable", reg.bits.io_enable); + printf(" %-20s : 0x%x\n", "cxl.mem enable", reg.bits.mem_enable); + printf("\n %s:\n", "cxl link status"); + printf(" %-20s : %s\n", "cxl.cache", + (reg.bits.cache_enabled == 1) ? "link up" : "link down"); + printf(" %-20s : %s\n", "cxl.io", (reg.bits.io_enabled == 1) ? "link up" : "link down"); + printf(" %-20s : %s\n", "cxl.mem", + (reg.bits.mem_enabled == 1) ? "link up" : "link down"); +} + +static void cxl_rcrb_link_info_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + struct cxl_info_desc cxl_link_info[CXL_RCRB_LINK_INFO_CNT] = { + {"cxl_rcrb_link_info0", cxl_link_info0_prt}, + {"cxl_rcrb_link_info1", cxl_link_info1_prt}, + }; + + printf("\n %s list:\n", "cxl link cfg"); + for (i = 0; i < data_unit_len && i < CXL_RCRB_LINK_INFO_CNT; i++) + cxl_link_info[i].info_prt(data[i].data); +} + +static void cxl_rcrb_cfg_header_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + const char *cxl_rcrb_hdr_msg[CXL_RCRB_CFG_HEADER_INFO_CNT] = { + "cxl_rcrb_hdr_id", + "cxl_rcrb_hdr_cmd", + "cxl_rcrb_hdr_clserv", + "cxl_rcrb_hdr_misc", + "cxl_rcrb_hdr_bar0", + "cxl_rcrb_hdr_bar1", + "cxl_rcrb_hdr_busnum", + "cxl_rcrb_hdr_membase_limit", + "cxl_rcrb_hdr_pre_membase_limit", + "cxl_rcrb_hdr_pre_membase_32upadr", + "cxl_rcrb_hdr_pre_memlimit_32upadr", + "cxl_rcrb_hdr_int_info" + }; + + printf(" cxl_rcrb cfg_header info:\n"); + for (i = 0; i < data_unit_len && i < CXL_RCRB_CFG_HEADER_INFO_CNT; i++) + printf(" %-40s : 0x%x\n", cxl_rcrb_hdr_msg[i], data[i].data); +} + +static void cxl_rcrb_dump_reg_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_rcrb reg dump list:\n"); + printf(" Addr Value\n"); + for (i = 0; i < data_unit_len; i++) + printf(" 0x%04x 0x%08x\n", data[i].data_addr, data[i].data); +} + +static void cxl_mem_uncorrect_err_prt(uint32_t data) +{ + union cxl_mem_uncorrect_err reg; + + reg.val = data; + printf(" %-25s : 0x%x\n", "cache_data_parity", reg.bits.cache_data_parity); + printf(" %-25s : 0x%x\n", "cache_addr_parity", reg.bits.cache_addr_parity); + printf(" %-25s : 0x%x\n", "cache_be_parity", reg.bits.cache_be_parity); + printf(" %-25s : 0x%x\n", "cache_data_ecc", reg.bits.cache_data_ecc); + printf(" %-25s : 0x%x\n", "mem_data_parity", reg.bits.mem_data_parity); + printf(" %-25s : 0x%x\n", "mem_address_parity", reg.bits.mem_address_parity); + printf(" %-25s : 0x%x\n", "mem_be_parity", reg.bits.mem_be_parity); + printf(" %-25s : 0x%x\n", "mem_data_ecc", reg.bits.mem_data_ecc); + printf(" %-25s : 0x%x\n", "reinit_threshold", reg.bits.reinit_threshold); + printf(" %-25s : 0x%x\n", "rsvd_encoding_violation", reg.bits.rsvd_encoding_violation); + printf(" %-25s : 0x%x\n", "poison_received", reg.bits.poison_received); + printf(" %-25s : 0x%x\n", "receiver_overflow", reg.bits.receiver_overflow); +} + +static void cxl_mem_correct_err_prt(uint32_t data) +{ + union cxl_mem_correct_err reg; + + reg.val = data; + printf(" %-25s : 0x%x\n", "cache_data_ecc", reg.bits.cache_data_ecc); + printf(" %-25s : 0x%x\n", "mem_data_ecc", reg.bits.mem_data_ecc); + printf(" %-25s : 0x%x\n", "crc_threshold", reg.bits.crc_threshold); + printf(" %-25s : 0x%x\n", "retry_threshold", reg.bits.retry_threshold); + printf(" %-25s : 0x%x\n", "cache_poison_received", reg.bits.cache_poison_received); + printf(" %-25s : 0x%x\n", "mem_poison_received", reg.bits.mem_poison_received); + printf(" %-25s : 0x%x\n", "physical_layer_error", reg.bits.physical_layer_error); +} + +static void cxl_mem_err_ctrl_prt(uint32_t data) +{ + union cxl_mem_error_ctrl reg; + + reg.val = data; + printf(" %-25s : 0x%x\n", "first_error_pointer", reg.bits.first_error_pointer); + printf(" %-25s : 0x%x\n", "multiple_header_recording_capability", + reg.bits.multiple_header_recording_capability); + printf(" %-25s : 0x%x\n", "poison_enable", reg.bits.poison_enable); +} + +static void cxl_membar_err_info_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + struct cxl_info_desc cxl_membar_err[CXL_MEMBAR_ERR_INFO_CNT] = { + {"cxl_mem_uncorrect_err_status", cxl_mem_uncorrect_err_prt}, + {"cxl_mem_uncorrect_err_mask", cxl_mem_uncorrect_err_prt}, + {"cxl_mem_uncorrect_err_severity", cxl_mem_uncorrect_err_prt}, + {"cxl_mem_correct_err_status", cxl_mem_correct_err_prt}, + {"cxl_mem_correct_err_mask", cxl_mem_correct_err_prt}, + {"cxl_mem_err_ctrl", cxl_mem_err_ctrl_prt} + }; + + for (i = 0; i < data_unit_len && i < CXL_MEMBAR_ERR_INFO_CNT; i++) { + printf("\n %s list:\n", cxl_membar_err[i].info_msg); + cxl_membar_err[i].info_prt(data[i].data); + } + + if (data_unit_len < CXL_MEM_HEADER_LOG_UNIT) { + printf("dump cxl_mem headerlog size invalid, data_len is %u\n", data_unit_len); + return; + } + printf("\n HeaderLog :\n"); + for (; i <= data_unit_len - CXL_MEM_HEADER_LOG_UNIT; i += CXL_MEM_HEADER_LOG_UNIT) { + printf(" [%04x] : 0x%08x 0x%08x 0x%08x 0x%08x\n", + i - CXL_MEMBAR_ERR_INFO_CNT, data[i + CXL_HEADER_LOG0].data, + data[i + CXL_HEADER_LOG1].data, data[i + CXL_HEADER_LOG2].data, + data[i + CXL_HEADER_LOG3].data); + } +} + +static void cxl_membar_dump_reg_prt(const struct cxl_data_unit *data, uint32_t data_unit_len) +{ + uint32_t i; + + printf(" cxl_membar reg dump list:\n"); + printf(" Addr Value\n"); + for (i = 0; i < data_unit_len; i++) + printf(" 0x%04x 0x%08x\n", data[i].data_addr, data[i].data); +} + +static int cxl_data_unit_buf_check(uint32_t data_offset, + size_t data_len, uint32_t rsp_data_num) +{ + size_t expect_end_pos; + size_t rsp_data_end_pos; + + expect_end_pos = data_offset * sizeof(uint32_t) + data_len; + rsp_data_end_pos = rsp_data_num * sizeof(uint32_t); + if (expect_end_pos > rsp_data_end_pos) + return -EINVAL; + + return 0; +} + +static struct cxl_prt_func g_prtf[] = { + {CXL_CPA, CPA_ERR, cxl_cpa_err_print}, + {CXL_CPA, CPA_MMRG, cxl_cpa_mmrg_window_print}, + {CXL_CPA, CPA_DUMP, cxl_cpa_dump_reg_prt}, + {CXL_CPA, CPA_CONFIG, cxl_cpa_config_print}, + {CXL_DL, CXL_DL_FSM_STATE, cxl_dl_fsm_state_print}, + {CXL_DL, CXL_DL_DFX, cxl_dl_dfx_print}, + {CXL_DL, CXL_DL_DUMP, cxl_dl_dump_reg_prt}, + {CXL_DL, CXL_DL_ERR, cxl_dl_error_info_prt}, + {CXL_RCRB, CXL_RCRB_LINK, cxl_rcrb_link_info_prt}, + {CXL_RCRB, CXL_RCRB_HDR, cxl_rcrb_cfg_header_prt}, + {CXL_RCRB, CXL_RCRB_DUMP, cxl_rcrb_dump_reg_prt}, + {CXL_MEMBAR, CXL_MEMBAR_ERR, cxl_membar_err_info_prt}, + {CXL_MEMBAR, CXL_MEMBAR_DUMP, cxl_membar_dump_reg_prt}, +}; + +int cxl_reg_show_execute(uint32_t port_id, uint32_t mode_code, uint32_t cmd_type) +{ + int ret; + uint32_t i; + size_t data_unit_len; + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct cxl_cmd_paras_in req_para; + struct cxl_out_data *data_head = NULL; + struct cxl_data_unit *data_unit_buf = NULL; + + req_para.port_id = port_id; + hikp_cmd_init(&req_header, CXL_MOD, mode_code, cmd_type); + cmd_ret = hikp_cmd_alloc(&req_header, &req_para, sizeof(req_para)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) { + printf("cxl_cmd mode_code: %u cmd_type: %u, hikp_get_data_proc err, ret : %d\n", + mode_code, cmd_type, ret); + if (cmd_ret) + free(cmd_ret); + return ret; + } + + data_head = (struct cxl_out_data *)cmd_ret->rsp_data; + data_unit_buf = (struct cxl_data_unit *)(cmd_ret->rsp_data + data_head->data_offset); + data_unit_len = data_head->length / sizeof(struct cxl_data_unit); + + ret = cxl_data_unit_buf_check(data_head->data_offset, data_unit_len, cmd_ret->rsp_data_num); + if (ret) { + free(cmd_ret); + return ret; + } + + for (i = 0; i < (sizeof(g_prtf) / sizeof((g_prtf)[0])); i++) { + if (mode_code == g_prtf[i].mode_code && + cmd_type == g_prtf[i].cmd_type && g_prtf[i].cxl_prt_handle) { + g_prtf[i].cxl_prt_handle(data_unit_buf, data_unit_len); + free(cmd_ret); + return 0; + } + } + + free(cmd_ret); + return -EINVAL; +} diff --git a/cxl/func_lib/cxl_func/cxl_feature.h b/cxl/func_lib/cxl_func/cxl_feature.h new file mode 100644 index 0000000..4d30ebe --- /dev/null +++ b/cxl/func_lib/cxl_func/cxl_feature.h @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2022 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 __CXL_FEATURE_H_ +#define __CXL_FEATURE_H_ + +#include "tool_cmd.h" + +#define CPA_ERR_MSG_INFO_CNT 8 +#define CPA_CFG_MSG_INFO_CNT 5 +#define CPA_MMRG_MSG_INFO_CNT 10 +#define CXL_DL_DFX_MSG_INFO_CNT 6 +#define CXL_DL_ERR_MSG_INFO_CNT 6 +#define CXL_RCRB_LINK_INFO_CNT 2 +#define CXL_RCRB_CFG_HEADER_INFO_CNT 12 +#define CXL_MEMBAR_ERR_INFO_CNT 6 +#define CXL_DL_FSM_STATE_STR_NUM 0x20 +#define CXL_HDM_CNT_EACH_PORT 2 +#define CXL_DATA_UNIT_SIZE 2 // reg addr + data +#define CXL_MEM_HEADER_LOG_UNIT 4 + +enum cxl_cmd_type { + CXL_CPA = 0, + CXL_DL, + CXL_RCRB, + CXL_MEMBAR +}; + +enum cxl_cpa_type { + CPA_UNKNOWN_TYPE = 0, + CPA_ERR, + CPA_MMRG, + CPA_DUMP, + CPA_CONFIG +}; + +enum cxl_dl_type { + CXL_DL_UNKNOWN_TYPE = 0, + CXL_DL_FSM_STATE, + CXL_DL_DFX, + CXL_DL_DUMP, + CXL_DL_ERR +}; + +enum cxl_rcrb_type { + CXL_RCRB_UNKNOWN_TYPE = 0, + CXL_RCRB_LINK, + CXL_RCRB_HDR, + CXL_RCRB_DUMP +}; + +enum cxl_membar_type { + CXL_MEMBAR_UNKNOWN_TYPE = 0, + CXL_MEMBAR_ERR, + CXL_MEMBAR_DUMP +}; + +enum cxl_membar_header_log { + CXL_HEADER_LOG0 = 0, + CXL_HEADER_LOG1, + CXL_HEADER_LOG2, + CXL_HEADER_LOG3 +}; + +struct cxl_cmd_paras_in { + uint32_t port_id; +}; + +struct cxl_out_data { + uint32_t length; + uint32_t data_offset; +}; + +struct cxl_data_unit { + uint32_t data_addr; + uint32_t data; +}; + +struct cxl_info_desc { + const char *info_msg; + void (*info_prt)(uint32_t data); +}; + +struct cxl_fsm_state_str { + int fsm_state; + char fsm_str[CXL_DL_FSM_STATE_STR_NUM]; +}; + +struct cxl_prt_func { + uint32_t mode_code; + uint32_t cmd_type; + void (*cxl_prt_handle)(const struct cxl_data_unit *data, uint32_t data_size); +}; + +int cxl_reg_show_execute(uint32_t port_id, uint32_t mode_code, uint32_t cmd_type); + +union cpa_cfg_key { + struct { + uint32_t cfg_cpa_port_en : 4; /* [3..0] */ + uint32_t cfg_cpa_dmt_disable : 1; /* [4] */ + uint32_t cfg_cpa_send_32byte : 1; /* [5] */ + uint32_t cfg_cpa_wcud_send_en : 1; /* [6] */ + uint32_t cfg_cpa_icg_en : 1; /* [7] */ + uint32_t cfg_cpa_mee_ns_sel : 1; /* [8] */ + uint32_t cfg_cpa_pmicg_en : 1; /* [9] */ + uint32_t cfg_cpa_rxdatreq_cango_th : 9; /* [18..10] */ + uint32_t cfg_cpa_port_remap : 1; /* [19] */ + uint32_t reserved_0 : 1; /* [20] */ + uint32_t reserved_1 : 1; /* [21] */ + uint32_t cfg_cpa_m2s_req_a5_tie0 : 1; /* [22] */ + uint32_t cfg_cpa_pcie_err_rpt_enable : 1; /* [23] */ + uint32_t cfg_cpa_retry_switch : 2; /* [25..24] */ + uint32_t reserved_2 : 6; /* [31..26] */ + } bits; + + uint32_t val; +}; + +union cpa_ctl_cfg { + struct { + uint32_t cpa_csp_en : 1; /* [0] */ + uint32_t cpa_comp_blk_en : 1; /* [1] */ + uint32_t cpa_wnsp_early_cmp_en : 1; /* [2] */ + uint32_t cpa_wtnsnp_cmpdbid_en : 1; /* [3] */ + uint32_t cpa_ptl_access_en : 1; /* [4] */ + uint32_t cpa_reqrsdata_bps_en : 1; /* [5] */ + uint32_t cpa_reqrsp_intrl_en : 1; /* [6] */ + uint32_t cpa_rspdat_intrl_en : 1; /* [7] */ + uint32_t cpa_wtevict_drop_en : 1; /* [8] */ + uint32_t cpa_resp_sc_drop_en : 1; /* [9] */ + uint32_t cfg_be_azero_drop_en : 1; /* [10] */ + uint32_t cpa_timeout_poison_en : 1; /* [11] */ + uint32_t cpa_err_reqcmd_send_en : 1; /* [12] */ + uint32_t cpa_req_err_rsp_en : 1; /* [13] */ + uint32_t cpa_rsp_exok_en : 1; /* [14] */ + uint32_t reserved_0 : 1; /* [15] */ + uint32_t cpa_rwd_pend_crd : 1; /* [16] */ + uint32_t cpa_wr_metavl : 2; /* [18..17] */ + uint32_t cpa_wr_metafd : 2; /* [20..19] */ + uint32_t cpa_wr_snptype : 3; /* [23..21] */ + uint32_t cpa_rd_metavl : 2; /* [25..24] */ + uint32_t cpa_rd_metafd : 2; /* [27..26] */ + uint32_t cpa_rd_snptype : 3; /* [30..28] */ + uint32_t cpa_drs_pend_crd : 1; /* [31] */ + } bits; + + uint32_t val; +}; + +union cpa_err_send_ctl { + struct { + uint32_t acc2core_resperr_en : 1; /* [0] */ + uint32_t acc2core_poison_en : 1; /* [1] */ + uint32_t core2acc_resperr_en : 1; /* [2] */ + uint32_t core2acc_poison_en : 1; /* [3] */ + uint32_t cfg_cpa_rspcmd_halt_en : 1; /* [4] */ + uint32_t cfg_cpa_rspcmd_halt_clr : 1; /* [5] */ + uint32_t cfg_cpa_reqcmd_halt_en : 1; /* [6] */ + uint32_t cfg_cpa_reqcmd_halt_clr : 1; /* [7] */ + uint32_t reserved_0 : 24; /* [31..8] */ + } bits; + + uint32_t val; +}; + +union cpa_timeout_ctl { + struct { + uint32_t cfg_timeout_rsp_fb : 1; /* [0] */ + uint32_t reserved_0 : 3; /* [3..1] */ + uint32_t cfg_timeout_th : 16; /* [19..4] */ + uint32_t reserved_1 : 12; /* [31..20] */ + } bits; + + uint32_t val; +}; + +union cpa_cfg_mee_enable { + struct { + uint32_t p0_cfg_cpa_mee_enable : 1; /* [0] */ + uint32_t p1_cfg_cpa_mee_enable : 1; /* [1] */ + uint32_t reserved_0 : 30; /* [31..2] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_fsm_state_reg { + struct { + uint32_t init_fsm_state : 4; /* [3..0] */ + uint32_t lrsm_state : 5; /* [8..4] */ + uint32_t reserved_0 : 3; /* [11..9] */ + uint32_t rrsm_state : 1; /* [12] */ + uint32_t reserved_1 : 19; /* [31..13] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_retry_buffer_status { + struct { + uint32_t dl_cxl_retry_buffer_w_ptr : 10; /* [9..0] */ + uint32_t dl_cxl_retry_buffer_r_ptr : 10; /* [19..10] */ + uint32_t dl_cxl_retry_buffer_full : 1; /* [20] */ + uint32_t dl_cxl_retry_buffer_empty : 1; /* [21] */ + uint32_t reserved_0 : 10; /* [31..22] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_dfx_rx_status { + struct { + uint32_t numack : 8; /* [7..0] */ + uint32_t rcv_eseq : 8; /* [15..8] */ + uint32_t g0_num_going : 5; /* [20..16] */ + uint32_t g0_num_going_rollover : 1; /* [21] */ + uint32_t g0_num_going_rollover_clr : 1; /* [22] */ + uint32_t rxflit_err_ind : 1; /* [23] */ + uint32_t rcv_empty : 1; /* [24] */ + uint32_t rcv_viral : 1; /* [25] */ + uint32_t reserved_0 : 6; /* [31..26] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_dfx_llr_var { + struct { + uint32_t eseq : 8; /* [7..0] */ + uint32_t llrb_wrptr : 8; /* [15..8] */ + uint32_t llrb_rdptr : 8; /* [23..16] */ + uint32_t numfreebuf : 8; /* [31..24] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_dfx_alm_err_num { + struct { + uint32_t alm_err_num : 8; /* [7..0] */ + uint32_t reserved_0 : 24; /* [31..8] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_init_signal { + struct { + uint32_t rcv_vld_flit_flag : 1; /* [0] */ + uint32_t rcv_init_param_flit_flag : 1; /* [1] */ + uint32_t init_flit_send_flag : 1; /* [2] */ + uint32_t cpa_receive_flit_rdy : 1; /* [3] */ + uint32_t alm_sch_en : 1; /* [4] */ + uint32_t reserved_0 : 27; /* [31..5] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_dfx_retry_num { + struct { + uint32_t num_retry : 5; /* [4..0] */ + uint32_t num_phy_reinit : 5; /* [9..5] */ + uint32_t reserved_0 : 22; /* [31..10] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_int_info { + struct { + uint32_t init_timeout_int : 1; /* [0] */ + uint32_t cxldl_down_int : 1; /* [1] */ + uint32_t reach_max_retry_num_int : 1; /* [2] */ + uint32_t retry_abort_int : 1; /* [3] */ + uint32_t rcv_retry_ack_error_int : 1; /* [4] */ + uint32_t rcv_static_error_int : 1; /* [5] */ + uint32_t ecc_1b_err_cxldl_int : 1; /* [6] */ + uint32_t ecc_2b_err_cxldl_int : 1; /* [7] */ + uint32_t rcv_non_retry_before_init_int : 1; /* [8] */ + uint32_t rcv_dup_init_param_int : 1; /* [9] */ + uint32_t rcv_viral_retry_ack_int : 1; /* [10] */ + uint32_t cpa_indicate_viral_int : 1; /* [11] */ + uint32_t reserved_0 : 4; /* [15..12] */ + uint32_t cxldl_up_int : 1; /* [16] */ + uint32_t reserved_1 : 15; /* [31..17] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_ecc_err_cnt { + struct { + uint32_t ram0_dl_ecc_err_cnt : 5; /* [4..0] */ + uint32_t ram1_dl_ecc_err_cnt : 5; /* [9..5] */ + uint32_t reserved_0 : 22; /* [31..10] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_ram_ecc_err_addr { + struct { + uint32_t dl_ecc_1bit_err_addr : 10; /* [9..0] */ + uint32_t reserved_0 : 6; /* [15..10] */ + uint32_t dl_ecc_2bit_err_addr : 10; /* [25..16] */ + uint32_t reserved_1 : 6; /* [31..26] */ + } bits; + + uint32_t val; +}; + +union cxl_dl_ram_ecc_state { + struct { + uint32_t ram0_1bit_ecc_err_status : 1; /* [0] */ + uint32_t ram0_2bit_ecc_err_status : 1; /* [1] */ + uint32_t ram1_1bit_ecc_err_status : 1; /* [2] */ + uint32_t ram1_2bit_ecc_err_status : 1; /* [3] */ + uint32_t reserved_0 : 28; /* [31..4] */ + } bits; + + uint32_t val; +}; + +union cxl_rcrb_vendor_spec_header { + struct { + uint32_t dvsec_id : 16; /* [15..0] */ + uint32_t cache_capable : 1; /* [16] */ + uint32_t io_capable : 1; /* [17] */ + uint32_t mem_capable : 1; /* [18] */ + uint32_t reserved_0 : 13; /* [31..19] */ + } bits; + + uint32_t val; +}; + +union cxl_rcrb_flex_bus_ctrl { + struct { + uint32_t cache_enable : 1; /* [0] */ + uint32_t io_enable : 1; /* [1] */ + uint32_t mem_enable : 1; /* [2] */ + uint32_t reserved_0 : 13; /* [15..3] */ + uint32_t cache_enabled : 1; /* [16] */ + uint32_t io_enabled : 1; /* [17] */ + uint32_t mem_enabled : 1; /* [18] */ + uint32_t reserved_1 : 13; /* [31..19] */ + } bits; + + uint32_t val; +}; + +union cxl_mem_uncorrect_err { + struct { + uint32_t cache_data_parity : 1; /* [0] */ + uint32_t cache_addr_parity : 1; /* [1] */ + uint32_t cache_be_parity : 1; /* [2] */ + uint32_t cache_data_ecc : 1; /* [3] */ + uint32_t mem_data_parity : 1; /* [4] */ + uint32_t mem_address_parity : 1; /* [5] */ + uint32_t mem_be_parity : 1; /* [6] */ + uint32_t mem_data_ecc : 1; /* [7] */ + uint32_t reinit_threshold : 1; /* [8] */ + uint32_t rsvd_encoding_violation : 1; /* [9] */ + uint32_t poison_received : 1; /* [10] */ + uint32_t receiver_overflow : 1; /* [11] */ + uint32_t reserved_0 : 20; /* [31..12] */ + } bits; + + uint32_t val; +}; + +union cxl_mem_correct_err { + struct { + uint32_t cache_data_ecc : 1; /* [0] */ + uint32_t mem_data_ecc : 1; /* [1] */ + uint32_t crc_threshold : 1; /* [2] */ + uint32_t retry_threshold : 1; /* [3] */ + uint32_t cache_poison_received : 1; /* [4] */ + uint32_t mem_poison_received : 1; /* [5] */ + uint32_t physical_layer_error : 1; /* [6] */ + uint32_t reserved_0 : 25; /* [31..7] */ + } bits; + + uint32_t val; +}; + +union cxl_mem_error_ctrl { + struct { + uint32_t first_error_pointer : 4; /* [3..0] */ + uint32_t reserved_0 : 5; /* [8..4] */ + uint32_t multiple_header_recording_capability : 1; /* [9] */ + uint32_t reserved_1 : 3; /* [12..10] */ + uint32_t poison_enable : 1; /* [13] */ + uint32_t reserved_2 : 18; /* [31..14] */ + } bits; + + uint32_t val; +}; + +#endif diff --git a/cxl/usr_cmd/cmd_analysis/cxl_cmd_cpa.c b/cxl/usr_cmd/cmd_analysis/cxl_cmd_cpa.c new file mode 100644 index 0000000..2607705 --- /dev/null +++ b/cxl/usr_cmd/cmd_analysis/cxl_cmd_cpa.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "cxl_tool_include.h" +#include "cxl_feature.h" +#include "hikptdev_plug.h" + +struct tool_cxl_cmd g_cxl_cpa_cmd = { + .cmd_type = CPA_UNKNOWN_TYPE, + .port_id = (uint32_t)(-1), +}; + +static int cxl_cpa_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf(" Usage: %s\n", self->cmd_ptr->name); + printf(" %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first"); + printf(" Options:\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-e", "--error", "show cpa error info"); + printf(" %s, %-25s %s\n", "-d", "--dump", "dump cpa Key config"); + printf(" %s, %-25s %s\n", "-m", "--mmrg", "show cpa mmrg window config"); + printf(" %s, %-25s %s\n", "-c", "--config", "show cpa config"); + printf("\n"); + + return 0; +} + +static int cxl_port_id_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("cpa set port id err %d\n", ret); + return ret; + } + g_cxl_cpa_cmd.port_id = val; + + return 0; +} + +static int cxl_cpa_err_status_show(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_cpa_cmd.cmd_type = CPA_ERR; + + return 0; +} + +static int cxl_cpa_mmrg_show(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_cpa_cmd.cmd_type = CPA_MMRG; + + return 0; +} + +static int cxl_cpa_dump(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_cpa_cmd.cmd_type = CPA_DUMP; + + return 0; +} + +static int cxl_cpa_config(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_cpa_cmd.cmd_type = CPA_CONFIG; + + return 0; +} + +static int cxl_cpa_execute_process(void) +{ + uint32_t port_id = g_cxl_cpa_cmd.port_id; + uint32_t cmd_type = g_cxl_cpa_cmd.cmd_type; + + if (cmd_type == CPA_ERR || cmd_type == CPA_MMRG || + cmd_type == CPA_DUMP || cmd_type == CPA_CONFIG) { + return cxl_reg_show_execute(port_id, CXL_CPA, cmd_type); + } + + g_cxl_cpa_cmd.cmd_type = CPA_UNKNOWN_TYPE; + return -EPERM; +} + +static void cxl_cpa_execute(struct major_cmd_ctrl *self) +{ + int ret; + uint32_t cmd_type; + static const char *cxl_cpa_succ_msg[] = { + "", + "cxl_cpa_err_status_show success!", + "cxl_cpa_mmrg_cfg_show success!", + "cxl_cpa_dump_reg_show success!", + "cxl_cpa_config_show success!" + }; + static const char *cxl_cpa_err_msg[] = { + "Error : unknown param_type!", + "cxl_cpa_err_status_show failed!", + "cxl_cpa_mmrg_cfg_show failed!", + "cxl_cpa_dump_reg_show failed!", + "cxl_cpa_config_show failed!" + }; + + ret = cxl_cpa_execute_process(); + cmd_type = g_cxl_cpa_cmd.cmd_type; + if (ret) { + /* In error branches, errors are printed and copied, and no check is required. */ + snprintf(self->err_str, sizeof(self->err_str), "%s\n", cxl_cpa_err_msg[cmd_type]); + } else { + printf("%s\n", cxl_cpa_succ_msg[cmd_type]); + } + + self->err_no = ret; +} + +static void cmd_cxl_cpa_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = cxl_cpa_execute; + + cmd_option_register("-h", "--help", false, cxl_cpa_help); + cmd_option_register("-i", "--interface", true, cxl_port_id_set); + cmd_option_register("-e", "--error", false, cxl_cpa_err_status_show); + cmd_option_register("-d", "--dump", false, cxl_cpa_dump); + cmd_option_register("-c", "--config", false, cxl_cpa_config); + cmd_option_register("-m", "--mmrg", false, cxl_cpa_mmrg_show); +} + +HIKP_CMD_DECLARE("cxl_cpa", "cxl_cpa maininfo", cmd_cxl_cpa_init); diff --git a/cxl/usr_cmd/cmd_analysis/cxl_cmd_dl.c b/cxl/usr_cmd/cmd_analysis/cxl_cmd_dl.c new file mode 100644 index 0000000..226db1e --- /dev/null +++ b/cxl/usr_cmd/cmd_analysis/cxl_cmd_dl.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "cxl_tool_include.h" +#include "cxl_feature.h" +#include "hikptdev_plug.h" + +struct tool_cxl_cmd g_cxl_dl_cmd = { + .cmd_type = CXL_DL_UNKNOWN_TYPE, + .port_id = (uint32_t)(-1), +}; + +static int cxl_dl_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf(" Usage: %s\n", self->cmd_ptr->name); + printf(" %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first"); + printf(" Options:\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-f", "--fsm_state", "show cxl dl fsm state"); + printf(" %s, %-25s %s\n", "-s", "--dfx_status", "show cxl dl dfx count"); + printf(" %s, %-25s %s\n", "-d", "--dump", "dump cxl dl Key reg"); + printf(" %s, %-25s %s\n", "-e", "--error", "show cxl dl err info"); + printf("\n"); + + return 0; +} + +static int cxl_dl_port_id_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("cxl dl set port id err %d\n", ret); + return ret; + } + g_cxl_dl_cmd.port_id = val; + + return 0; +} + +static int cxl_dl_err_status(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_dl_cmd.cmd_type = CXL_DL_ERR; + + return 0; +} + +static int cxl_dl_dump(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_dl_cmd.cmd_type = CXL_DL_DUMP; + + return 0; +} + +static int cxl_dl_dfx(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_dl_cmd.cmd_type = CXL_DL_DFX; + + return 0; +} + +static int cxl_dl_fsm_state(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_dl_cmd.cmd_type = CXL_DL_FSM_STATE; + + return 0; +} + +static int cxl_dl_execute_process(void) +{ + uint32_t port_id = g_cxl_dl_cmd.port_id; + uint32_t cmd_type = g_cxl_dl_cmd.cmd_type; + + if (cmd_type == CXL_DL_FSM_STATE || cmd_type == CXL_DL_DFX || + cmd_type == CXL_DL_DUMP || cmd_type == CXL_DL_ERR) { + return cxl_reg_show_execute(port_id, CXL_DL, cmd_type); + } + + g_cxl_dl_cmd.cmd_type = CXL_DL_UNKNOWN_TYPE; + return -EPERM; +} + +static void cxl_dl_execute(struct major_cmd_ctrl *self) +{ + int ret; + uint32_t cmd_type; + static const char *cxl_dl_succ_msg[] = { + "", + "cxl_dl_fsm_state_show success!", + "cxl_dl_dfx_show success!", + "cxl_dl_dump_show success!", + "cxl_dl_error_info success!" + }; + static const char *cxl_dl_err_msg[] = { + "Error : unknown param_type!", + "cxl_dl_fsm_state_show failed!", + "cxl_dl_dfx_show failed!", + "cxl_dl_dump_show failed!", + "cxl_dl_error_info failed!" + }; + + ret = cxl_dl_execute_process(); + cmd_type = g_cxl_dl_cmd.cmd_type; + if (ret) { + /* In error branches, errors are printed and copied, and no check is required. */ + snprintf(self->err_str, sizeof(self->err_str), "%s\n", cxl_dl_err_msg[cmd_type]); + } else { + printf("%s\n", cxl_dl_succ_msg[cmd_type]); + } + + self->err_no = ret; +} + +static void cmd_cxl_dl_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = cxl_dl_execute; + + cmd_option_register("-h", "--help", false, cxl_dl_help); + cmd_option_register("-i", "--interface", true, cxl_dl_port_id_set); + cmd_option_register("-f", "--fsm_state", false, cxl_dl_fsm_state); + cmd_option_register("-s", "--dfx_status", false, cxl_dl_dfx); + cmd_option_register("-d", "--dump", false, cxl_dl_dump); + cmd_option_register("-e", "--error", false, cxl_dl_err_status); +} + +HIKP_CMD_DECLARE("cxl_dl", "cxl_dl maininfo", cmd_cxl_dl_init); diff --git a/cxl/usr_cmd/cmd_analysis/cxl_cmd_membar.c b/cxl/usr_cmd/cmd_analysis/cxl_cmd_membar.c new file mode 100644 index 0000000..f444b56 --- /dev/null +++ b/cxl/usr_cmd/cmd_analysis/cxl_cmd_membar.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "cxl_tool_include.h" +#include "cxl_feature.h" +#include "hikptdev_plug.h" + +struct tool_cxl_cmd g_cxl_membar_cmd = { + .cmd_type = CXL_MEMBAR_UNKNOWN_TYPE, + .port_id = (uint32_t)(-1), +}; + +static int cxl_membar_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf(" Usage: %s\n", self->cmd_ptr->name); + printf(" %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first"); + printf(" Options:\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-e", "--error_info", "show cxl.mem aer info"); + printf(" %s, %-25s %s\n", "-d", "--dump", "dump cxl membar reg"); + printf("\n"); + + return 0; +} + +static int cxl_membar_port_id_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("cxl membar set port id err %d\n", ret); + return ret; + } + g_cxl_membar_cmd.port_id = val; + + return 0; +} + +static int cxl_membar_err_info(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_membar_cmd.cmd_type = CXL_MEMBAR_ERR; + + return 0; +} + +static int cxl_membar_dump(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_membar_cmd.cmd_type = CXL_MEMBAR_DUMP; + + return 0; +} + +static int cxl_membar_execute_process(void) +{ + uint32_t port_id = g_cxl_membar_cmd.port_id; + uint32_t cmd_type = g_cxl_membar_cmd.cmd_type; + + if (cmd_type == CXL_MEMBAR_ERR || cmd_type == CXL_MEMBAR_DUMP) + return cxl_reg_show_execute(port_id, CXL_MEMBAR, cmd_type); + + g_cxl_membar_cmd.cmd_type = CXL_MEMBAR_UNKNOWN_TYPE; + return -EPERM; +} + +static void cxl_membar_execute(struct major_cmd_ctrl *self) +{ + int ret; + uint32_t cmd_type; + const char *cxl_membar_succ_msg[] = { + "", + "cxl_membar_err_info_show success!", + "cxl_membar_dump_show success!" + }; + const char *cxl_membar_err_msg[] = { + "Error : unknown param_type!", + "cxl_membar_err_info_show failed!", + "cxl_membar_dump_show failed!" + }; + + ret = cxl_membar_execute_process(); + cmd_type = g_cxl_membar_cmd.cmd_type; + if (ret) { + /* In error branches, errors are printed and copied, and no check is required. */ + snprintf(self->err_str, sizeof(self->err_str), "%s\n", + cxl_membar_err_msg[cmd_type]); + } else { + printf("%s\n", cxl_membar_succ_msg[cmd_type]); + } + + self->err_no = ret; +} + +static void cmd_cxl_membar_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = cxl_membar_execute; + + cmd_option_register("-h", "--help", false, cxl_membar_help); + cmd_option_register("-i", "--interface", true, cxl_membar_port_id_set); + cmd_option_register("-e", "--error_info", false, cxl_membar_err_info); + cmd_option_register("-d", "--dump", false, cxl_membar_dump); +} + +HIKP_CMD_DECLARE("cxl_membar", "cxl_membar maininfo", cmd_cxl_membar_init); diff --git a/cxl/usr_cmd/cmd_analysis/cxl_cmd_rcrb.c b/cxl/usr_cmd/cmd_analysis/cxl_cmd_rcrb.c new file mode 100644 index 0000000..f83b64d --- /dev/null +++ b/cxl/usr_cmd/cmd_analysis/cxl_cmd_rcrb.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "cxl_tool_include.h" +#include "cxl_feature.h" +#include "hikptdev_plug.h" + +struct tool_cxl_cmd g_cxl_rcrb_cmd = { + .cmd_type = CXL_RCRB_UNKNOWN_TYPE, + .port_id = (uint32_t)(-1), +}; + +static int cxl_rcrb_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf(" Usage: %s\n", self->cmd_ptr->name); + printf(" %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first"); + printf(" Options:\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-l", "--link_info", "show cxl.io and cxl.mem link info"); + printf(" %s, %-25s %s\n", "-p", "--pci_hdr_info", "show cxl rcrb cfg space header"); + printf(" %s, %-25s %s\n", "-d", "--dump", "dump cxl rcrb reg"); + printf("\n"); + + return 0; +} + +static int cxl_rcrb_port_id_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("cxl rcrb set port id err %d\n", ret); + return ret; + } + g_cxl_rcrb_cmd.port_id = val; + + return 0; +} + +static int cxl_rcrb_link_status(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_rcrb_cmd.cmd_type = CXL_RCRB_LINK; + + return 0; +} + +static int cxl_rcrb_header_info(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_rcrb_cmd.cmd_type = CXL_RCRB_HDR; + + return 0; +} + +static int cxl_rcrb_dump(struct major_cmd_ctrl *self, const char *argv) +{ + g_cxl_rcrb_cmd.cmd_type = CXL_RCRB_DUMP; + + return 0; +} + +static int cxl_rcrb_execute_process(void) +{ + uint32_t port_id = g_cxl_rcrb_cmd.port_id; + uint32_t cmd_type = g_cxl_rcrb_cmd.cmd_type; + + if (cmd_type == CXL_RCRB_LINK || cmd_type == CXL_RCRB_HDR || + cmd_type == CXL_RCRB_DUMP) { + return cxl_reg_show_execute(port_id, CXL_RCRB, cmd_type); + } + + g_cxl_rcrb_cmd.cmd_type = CXL_RCRB_UNKNOWN_TYPE; + return -EPERM; +} + +static void cxl_rcrb_execute(struct major_cmd_ctrl *self) +{ + int ret; + uint32_t cmd_type; + const char *cxl_rcrb_succ_msg[] = { + "", + "cxl_rcrb_link_status_show success!", + "cxl_rcrb_cfg_header_show success!", + "cxl_rcrb_dump_show success!" + }; + const char *cxl_rcrb_err_msg[] = { + "Error : unknown param_type!", + "cxl_rcrb_link_status_show failed!", + "cxl_rcrb_cfg_header_show failed!", + "cxl_rcrb_dump_show failed!" + }; + + ret = cxl_rcrb_execute_process(); + cmd_type = g_cxl_rcrb_cmd.cmd_type; + if (ret) { + /* In error branches, errors are printed and copied, and no check is required. */ + snprintf(self->err_str, sizeof(self->err_str), "%s\n", cxl_rcrb_err_msg[cmd_type]); + } else { + printf("%s\n", cxl_rcrb_succ_msg[cmd_type]); + } + + self->err_no = ret; +} + +static void cmd_cxl_rcrb_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = cxl_rcrb_execute; + + cmd_option_register("-h", "--help", false, cxl_rcrb_help); + cmd_option_register("-i", "--interface", true, cxl_rcrb_port_id_set); + cmd_option_register("-l", "--link_info", false, cxl_rcrb_link_status); + cmd_option_register("-p", "--pci_hdr_info", false, cxl_rcrb_header_info); + cmd_option_register("-d", "--dump", false, cxl_rcrb_dump); +} + +HIKP_CMD_DECLARE("cxl_rcrb", "cxl_rcrb maininfo", cmd_cxl_rcrb_init); diff --git a/cxl/usr_cmd/cmd_analysis/cxl_tool_include.h b/cxl/usr_cmd/cmd_analysis/cxl_tool_include.h new file mode 100644 index 0000000..5028056 --- /dev/null +++ b/cxl/usr_cmd/cmd_analysis/cxl_tool_include.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 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 __CXL_TOOL_INCLUDE_H_ +#define __CXL_TOOL_INCLUDE_H_ + +#include + +struct tool_cxl_cmd { + uint32_t cmd_type; + uint32_t port_id; +}; + +#endif -- Gitee From 6d9eedfec373ea301a055a6619fd35cb1be2c649 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:22:32 +0800 Subject: [PATCH 07/14] support querying DPDK module information querying information including the fd/fec/gro/ppp/qos/queue/rss module Signed-off-by: lihuisong Signed-off-by: fengchengwen (cherry picked from commit 2201b393f6501e9fe1ca4d8fc708d997a253125d) --- net/nic/nic_fd/hikp_nic_fd.c | 1051 ++++++++++++++++++++++++++ net/nic/nic_fd/hikp_nic_fd.h | 227 ++++++ net/nic/nic_fec/hikp_nic_fec.c | 166 +++++ net/nic/nic_fec/hikp_nic_fec.h | 72 ++ net/nic/nic_gro/hikp_nic_gro.c | 105 +++ net/nic/nic_gro/hikp_nic_gro.h | 46 ++ net/nic/nic_ppp/hikp_nic_ppp.c | 1110 ++++++++++++++++++++++++++++ net/nic/nic_ppp/hikp_nic_ppp.h | 249 +++++++ net/nic/nic_qos/hikp_nic_qos.c | 284 +++++++ net/nic/nic_qos/hikp_nic_qos.h | 116 +++ net/nic/nic_queue/hikp_nic_queue.c | 493 ++++++++++++ net/nic/nic_queue/hikp_nic_queue.h | 155 ++++ net/nic/nic_rss/hikp_nic_rss.c | 491 ++++++++++++ net/nic/nic_rss/hikp_nic_rss.h | 94 +++ 14 files changed, 4659 insertions(+) create mode 100644 net/nic/nic_fd/hikp_nic_fd.c create mode 100644 net/nic/nic_fd/hikp_nic_fd.h create mode 100644 net/nic/nic_fec/hikp_nic_fec.c create mode 100644 net/nic/nic_fec/hikp_nic_fec.h create mode 100644 net/nic/nic_gro/hikp_nic_gro.c create mode 100644 net/nic/nic_gro/hikp_nic_gro.h create mode 100644 net/nic/nic_ppp/hikp_nic_ppp.c create mode 100644 net/nic/nic_ppp/hikp_nic_ppp.h create mode 100644 net/nic/nic_qos/hikp_nic_qos.c create mode 100644 net/nic/nic_qos/hikp_nic_qos.h create mode 100644 net/nic/nic_queue/hikp_nic_queue.c create mode 100644 net/nic/nic_queue/hikp_nic_queue.h create mode 100644 net/nic/nic_rss/hikp_nic_rss.c create mode 100644 net/nic/nic_rss/hikp_nic_rss.h diff --git a/net/nic/nic_fd/hikp_nic_fd.c b/net/nic/nic_fd/hikp_nic_fd.c new file mode 100644 index 0000000..5a87c30 --- /dev/null +++ b/net/nic/nic_fd/hikp_nic_fd.c @@ -0,0 +1,1051 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_fd.h" + +struct key_info { + const char *key_name; + uint16_t key_type; + uint8_t key_length; +}; + +static const struct key_info g_meta_data_key_info[] = { + {"packet_type_id", PACKET_TYPE_ID, 6}, + {"fragement", IP_FRAGEMENT, 1}, + {"roce_type", ROCE_TYPE, 1}, + {"next_key", NEXT_KEY, 5}, + {"vlan_num", VLAN_NUMBER, 2}, + {"src_port", SRC_VPORT, 12}, + {"des_port", DST_VPORT, 12}, + {"tunnel_packet", TUNNEL_PACKET, 1}, +}; + +static const struct key_info g_tuple_key_info[] = { + {"ot_dmac", OUTER_DST_MAC, 48}, + {"ot_smac", OUTER_SRC_MAC, 48}, + {"ot_vlan_tag_fst", OUTER_VLAN_TAG_FST, 16}, + {"ot_vlan_tag_sec", OUTER_VLAN_TAG_SEC, 16}, + {"ot_eth_type", OUTER_ETH_TYPE, 16}, + {"ot_l2_rsv", OUTER_L2_RSV, 16}, + {"ot_ip_tos", OUTER_IP_TOS, 8}, + {"ot_ip_proto", OUTER_IP_PROTO, 8}, + {"ot_sip", OUTER_SRC_IP, 32}, + {"ot_dip", OUTER_DST_IP, 32}, + {"ot_l3_rsv", OUTER_L3_RSV, 16}, + {"ot_sp", OUTER_SRC_PORT, 16}, + {"ot_dp", OUTER_DST_PORT, 16}, + {"ot_l4_rsv", OUTER_L4_RSV, 32}, + {"ot_tun_vni", OUTER_TUN_VNI, 24}, + {"ot_tun_flow_id", OUTER_TUN_FLOW_ID, 8}, + {"in_dmac", INNER_DST_MAC, 48}, + {"in_smac", INNER_SRC_MAC, 48}, + {"in_vlan_tag_fst", INNER_VLAN_TAG_FST, 16}, + {"in_vlan_tag_sec", INNER_VLAN_TAG_SEC, 16}, + {"in_eth_type", INNER_ETH_TYPE, 16}, + {"in_l2_rsv", INNER_L2_RSV, 16}, + {"in_ip_tos", INNER_IP_TOS, 8}, + {"in_ip_proto", INNER_IP_PROTO, 8}, + {"in_sip", INNER_SRC_IP, 32}, + {"in_dip", INNER_DST_IP, 32}, + {"in_l3_rsv", INNER_L3_RSV, 16}, + {"in_sp", INNER_SRC_PORT, 16}, + {"in_dp", INNER_DST_PORT, 16}, + {"in_l4_rsv", INNER_L4_RSV, 32}, +}; + +struct nic_fd_action { + bool drop; + bool q_vid; + uint16_t qid; + bool cnt_vld; + uint16_t cnt_id; + bool nxt_vld; + uint16_t next_input_key; + bool rule_id_vld; + uint16_t rule_id; + bool tc_ovrd_en; + uint16_t queue_region_size; +}; + +static struct nic_fd_param g_fd_param = {0}; +static struct nic_fd_hw_info g_fd_hw_info = {0}; + +static int hikp_nic_query_fd_hw_info(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len); +static int hikp_nic_query_fd_rules(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len); +static int hikp_nic_query_fd_counter(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len); + +static void hikp_nic_show_fd_hw_info(const void *data); +static void hikp_nic_show_fd_rules(const void *data); +static void hikp_nic_show_fd_counter(const void *data); + +#define NIC_FD_HW_INFO_NAME "hw_info" +#define NIC_FD_RULES_NAME "rules" +#define NIC_FD_COUNTER_NAME "counter" + +static const struct fd_feature_cmd g_fd_feature_cmd[] = { + {NIC_FD_HW_INFO_NAME, NIC_FD_HW_INFO_DUMP, false, + hikp_nic_query_fd_hw_info, hikp_nic_show_fd_hw_info}, + {NIC_FD_RULES_NAME, NIC_FD_RULES_INFO_DUMP, true, + hikp_nic_query_fd_rules, hikp_nic_show_fd_rules}, + {NIC_FD_COUNTER_NAME, NIC_FD_COUNTER_STATS_DUMP, true, + hikp_nic_query_fd_counter, hikp_nic_show_fd_counter}, +}; + +static int hikp_nic_fd_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + printf("%s\n", + " [-du/--dump hw_info ]\n" + " dump fd hardware info.\n" + " [-du/--dump rules -st/--stage -id/--index ]\n" + " dump all rules or one rule info of certain stage fd.\n" + " [-du/--dump counter -st/--stage -id/--index ]\n" + " dump all counters or one counter stats of certain stage fd.\n"); + printf(" Note: dump all entries without '-id/--index'\n"); + + return 0; +} + +static uint16_t hikp_nic_get_tcam_data_size(uint16_t key_max_bit) +{ + uint16_t max_key_bytes; + + max_key_bytes = HIKP_DIV_ROUND_UP(key_max_bit / HIKP_BITS_PER_BYTE, HIKP_DWORDS_BYTE); + max_key_bytes = max_key_bytes * HIKP_DWORDS_BYTE; + + return max_key_bytes; +} + +static void hikp_nic_show_fd_key_info(struct nic_fd_hw_info *hw_info) +{ + struct nic_fd_key_cfg *key_cfg; + size_t fd_mask_cnt; + uint16_t i; + size_t j; + + for (i = 0; i < NIC_FD_STAGE_NUM; i++) { + if (hw_info->alloc.stage_entry_num[i] == 0) + continue; + + key_cfg = &hw_info->key_cfg[i]; + printf("fd stage%u key info:\n", (uint16_t)(i + 1)); + printf(" key_select: %s\n", + key_cfg->key_select == HNS3_FD_KEY_BASE_ON_TUPLE ? "tuple" : "packet"); + printf(" inner_src_ipv6_word_en: 0x%x\n", key_cfg->inner_src_ipv6_word_en); + printf(" inner_dest_ipv6_word_en: 0x%x\n", key_cfg->inner_dest_ipv6_word_en); + printf(" outer_src_ipv6_word_en: 0x%x\n", key_cfg->outer_src_ipv6_word_en); + printf(" outer_dest_ipv6_word_en: 0x%x\n", key_cfg->outer_dest_ipv6_word_en); + + if (key_cfg->key_select == HNS3_FD_KEY_BASE_ON_PTYPE) { + HIKP_WARN_PRINT("Unsupport for parsing packet type key.\n"); + continue; + } + + printf(" fd enable key info[mask: 0x%x]:\n", key_cfg->tuple_mask); + fd_mask_cnt = HIKP_ARRAY_SIZE(g_tuple_key_info); + for (j = 0; j < fd_mask_cnt; j++) { + if (hikp_get_bit(key_cfg->tuple_mask, j) == 0) + printf(" %s\n", g_tuple_key_info[j].key_name); + } + + printf(" fd meta info[mask: 0x%x]:\n", key_cfg->meta_data_mask); + fd_mask_cnt = HIKP_ARRAY_SIZE(g_meta_data_key_info); + for (j = 0; j < fd_mask_cnt; j++) { + if (hikp_get_bit(key_cfg->meta_data_mask, j) == 0) + printf(" %s\n", g_meta_data_key_info[j].key_name); + } + } +} + +static const char *hikp_nic_get_fd_mode_name(uint8_t mode) +{ + struct hikp_nic_fd_mode_info { + uint8_t mode; + const char *name; + } mode_info[] = { + {FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1, "one level mode, 2k * 400b"}, + {FD_MODE_DEPTH_1K_WIDTH_400B_STAGE_2, "two level mode, 1k * 400b per level"}, + {FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1, "one level mode, 4k * 200b"}, + {FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2, "two level mode, 2k * 200 per level"}, + }; + size_t i; + + for (i = 0; i < HIKP_ARRAY_SIZE(mode_info); i++) { + if (mode_info[i].mode == mode) + return mode_info[i].name; + } + + return "unknown mode"; +} + +static void hikp_nic_show_fd_hw_info(const void *data) +{ + struct nic_fd_hw_info *hw_info = (struct nic_fd_hw_info *)data; + uint16_t i; + + printf("fd hardware info:\n"); + printf(" fd_mode: %s\n", hikp_nic_get_fd_mode_name(hw_info->mode)); + printf(" fd_enable=%s\n", hw_info->enable ? "enable" : "disable"); + printf(" max key bit width: %u\n", hw_info->key_max_bit); + for (i = 0; i < NIC_FD_STAGE_NUM; i++) { + printf(" stage%u_entry_num=%u\n", (uint16_t)(i + 1), + hw_info->alloc.stage_entry_num[i]); + printf(" stage%u_counter_num=%u\n", (uint16_t)(i + 1), + hw_info->alloc.stage_counter_num[i]); + } + + hikp_nic_show_fd_key_info(hw_info); +} + +static uint16_t hikp_nic_get_max_key_len(uint8_t mode) +{ + if (mode == FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1 || + mode == FD_MODE_DEPTH_1K_WIDTH_400B_STAGE_2) + return NIC_KEY_LEN_400B; + else if (mode == FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1 || + mode == FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2) + return NIC_KEY_LEN_200B; + + return 0; +} + +static void hikp_nic_print_tuple(const struct key_info *tuple_key, + const uint8_t *tcam_x, const uint8_t *tcam_y) +{ +#define HIKP_NIC_FD_TUPLE_KEY_LEN_6_BYTES 6 +#define HIKP_NIC_FD_TUPLE_KEY_LEN_4_BYTES 4 +#define HIKP_NIC_FD_TUN_VNI_LEN 3 + uint32_t tun_vni = 0; + uint64_t mask = 0; + uint8_t i; + + /* The bit width of all tuple type key are less than 64Bit. */ + for (i = 0; i < HIKP_DIV_ROUND_UP(tuple_key->key_length, HIKP_BITS_PER_BYTE); i++) + mask |= (((uint64_t)(*(tcam_x + i) ^ *(tcam_y + i))) << (i * HIKP_BITS_PER_BYTE)); + + /* The mask isn't zero, means that the tuple key is valid. */ + if (mask == 0) + return; + + switch (tuple_key->key_type) { + case OUTER_DST_MAC: + case OUTER_SRC_MAC: + case INNER_DST_MAC: + case INNER_SRC_MAC: + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *(tcam_y + 5), *(tcam_y + 4), + *(tcam_y + 3), *(tcam_y + 2), *(tcam_y + 1), *tcam_y); + break; + case OUTER_ETH_TYPE: + case INNER_ETH_TYPE: + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("0x%x\n", *(uint16_t *)tcam_y); + break; + case OUTER_VLAN_TAG_FST: + case OUTER_VLAN_TAG_SEC: + case INNER_VLAN_TAG_FST: + case INNER_VLAN_TAG_SEC: + case OUTER_L2_RSV: + case INNER_L2_RSV: + case OUTER_L3_RSV: + case INNER_L3_RSV: + case OUTER_SRC_PORT: + case OUTER_DST_PORT: + case INNER_SRC_PORT: + case INNER_DST_PORT: + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("%u\n", *(uint16_t *)tcam_y); + break; + case OUTER_IP_TOS: + case INNER_IP_TOS: + case OUTER_IP_PROTO: + case INNER_IP_PROTO: + case OUTER_TUN_FLOW_ID: + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("0x%x\n", *tcam_y); + break; + case OUTER_SRC_IP: + case OUTER_DST_IP: + case INNER_SRC_IP: + case INNER_DST_IP: + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("%u.%u.%u.%u\n", *(tcam_y + 3), *(tcam_y + 2), *(tcam_y + 1), *tcam_y); + break; + case OUTER_L4_RSV: + case INNER_L4_RSV: + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("%u\n", *(uint32_t *)tcam_y); + break; + case OUTER_TUN_VNI: + for (i = 0; i < HIKP_NIC_FD_TUN_VNI_LEN; i++) + tun_vni |= (((uint32_t)*(tcam_y + i)) << (i * HIKP_BITS_PER_BYTE)); + printf("\t %s[mask=0x%llx]: ", tuple_key->key_name, mask); + printf("0x%x\n", tun_vni); + break; + default: + printf("unknown tuple key type(%u)\n", tuple_key->key_type); + break; + } +} + +static void hikp_nic_print_meta_data(uint16_t type, uint32_t val) +{ + const char *vlan_str[] = {"no tag", "tag2 only", "tag1 only", "tag1+tag2"}; + + switch (type) { + case PACKET_TYPE_ID: + case NEXT_KEY: + printf("%u", val); + break; + case IP_FRAGEMENT: + printf("%s", val == 0 ? "NON-IP frag packet" : "IP frag packet"); + break; + case ROCE_TYPE: + printf("%s", val == 0 ? "NIC packet" : "RoCE packet"); + break; + case VLAN_NUMBER: + printf("%s", vlan_str[val]); + break; + case SRC_VPORT: + case DST_VPORT: + printf("0x%x", val); + break; + case TUNNEL_PACKET: + printf("%s", val == 0 ? "non-tunnel packet" : "tunnel packet"); + break; + default: + printf("unknown meta type(%u)", type); + break; + } + printf("\n"); +} + +static void hikp_nic_fd_print_key(const struct nic_fd_rule_info *rule, + const struct nic_fd_key_cfg *key_cfg, uint16_t max_key_bytes) +{ + uint32_t tcam_offset; + const uint8_t *key_x; + const uint8_t *key_y; + uint16_t tuple_cnt; + uint16_t j; + + printf("\tKey:\n"); + tcam_offset = 0; + key_x = rule->tcam_data; + key_y = rule->tcam_data + max_key_bytes; + for (j = 0; j < MAX_TUPLE; j++) { + if (hikp_get_bit(key_cfg->tuple_mask, j) == 0) { + tuple_cnt = g_tuple_key_info[j].key_length / HIKP_BITS_PER_BYTE; + hikp_nic_print_tuple(&g_tuple_key_info[j], key_x + tcam_offset, + key_y + tcam_offset); + tcam_offset += tuple_cnt; + } + } +} + +static uint16_t hikp_nic_get_active_meta_width(uint32_t meta_mask) +{ + uint16_t width = 0; + uint16_t i; + + for (i = 0; i < MAX_META_DATA; i++) { + if (hikp_get_bit(meta_mask, i) == 0) + width += g_meta_data_key_info[i].key_length; + } + + return width; +} + +static void hikp_nic_fd_print_meta_data(struct nic_fd_rule_info *rule) +{ + struct nic_fd_key_cfg *key_cfg; + uint16_t active_meta_width; + uint16_t active_tcam_size; + uint16_t meta_data_region; + uint64_t meta_data = 0; + uint16_t max_key_bytes; + uint16_t max_key_len; + uint16_t meta_bytes; + uint16_t tuple_size; + uint16_t cur_pos; + uint8_t *key_y; + uint16_t end; + uint16_t val; + int i; + + max_key_bytes = hikp_nic_get_tcam_data_size(g_fd_hw_info.key_max_bit); + key_y = rule->tcam_data + max_key_bytes; + + max_key_len = hikp_nic_get_max_key_len(g_fd_hw_info.mode); + active_tcam_size = max_key_len / HIKP_BITS_PER_BYTE; + + key_cfg = &g_fd_hw_info.key_cfg[NIC_FD_STAGE_1]; + active_meta_width = hikp_nic_get_active_meta_width(key_cfg->meta_data_mask); + meta_bytes = HIKP_DIV_ROUND_UP(active_meta_width, HIKP_BITS_PER_BYTE); + meta_data_region = active_tcam_size - meta_bytes; + if (meta_bytes > sizeof(meta_data)) { + printf("meta data copy size error, data size: 0x%x, max size: 0x%x\n", + meta_bytes, sizeof(meta_data)); + return; + } + memcpy(&meta_data, &key_y[meta_data_region], meta_bytes); + printf("\t meta_data[meta_data=0x%llx]:\n", meta_data); + cur_pos = meta_bytes * HIKP_BITS_PER_BYTE; + end = cur_pos - 1; + for (i = MAX_META_DATA - 1; i >= 0; i--) { + if (hikp_get_bit(key_cfg->meta_data_mask, i) == 0) { + tuple_size = g_meta_data_key_info[i].key_length; + cur_pos -= tuple_size; + val = hikp_get_field(meta_data, GENMASK(end, cur_pos), cur_pos); + printf("\t %s: ", g_meta_data_key_info[i].key_name); + end -= tuple_size; + hikp_nic_print_meta_data(g_meta_data_key_info[i].key_type, val); + } + } +} + +static void hikp_nic_parse_ad_data(const struct nic_fd_rule_info *rule, + struct nic_fd_action *action) +{ + uint32_t ad_data_h = rule->ad_data_h; + uint32_t ad_data_l = rule->ad_data_l; + + action->drop = !!(ad_data_l & HI_BIT(NIC_FD_AD_DROP_B)); + action->cnt_vld = !!(ad_data_l & HI_BIT(NIC_FD_AD_USE_COUNTER_B)); + if (action->cnt_vld) { + action->cnt_id = ad_data_h & HI_BIT(NIC_FD_AD_COUNTER_HIGH_BIT_B) ? 1 : 0; + action->cnt_id <<= NIC_FD_AD_COUNTER_HIGH_BIT; + action->cnt_id |= hikp_get_field(ad_data_l, NIC_FD_AD_COUNTER_NUM_M, + NIC_FD_AD_COUNTER_NUM_S); + } + action->nxt_vld = !!(ad_data_l & HI_BIT(NIC_FD_AD_NXT_STEP_B)); + if (action->nxt_vld) + action->next_input_key = hikp_get_field(ad_data_l, NIC_FD_AD_NXT_KEY_M, + NIC_FD_AD_NXT_KEY_S); + + action->rule_id_vld = !!(ad_data_h & HI_BIT(NIC_FD_AD_WR_RULE_ID_B)); + if (action->rule_id_vld) + action->rule_id = hikp_get_field(ad_data_h, NIC_FD_AD_RULE_ID_M, + NIC_FD_AD_RULE_ID_S); + + action->tc_ovrd_en = !!(ad_data_h & HI_BIT(NIC_FD_AD_QUEUE_REGION_EN_B)); + if (action->tc_ovrd_en) { + action->queue_region_size = hikp_get_field(ad_data_h, NIC_FD_AD_QUEUE_REGION_SIZE_M, + NIC_FD_AD_QUEUE_REGION_SIZE_S); + } + action->q_vid = !!(ad_data_l & HI_BIT(NIC_FD_AD_DIRECT_QID_B)); + if (action->q_vid || action->tc_ovrd_en) { + action->qid = ad_data_h & HI_BIT(NIC_FD_AD_QUEUE_ID_HIGH_BIT_B) ? 1 : 0; + action->qid <<= NIC_FD_AD_QUEUE_ID_HIGH_BIT; + action->qid |= hikp_get_field(ad_data_l, NIC_FD_AD_QID_M, NIC_FD_AD_QID_S); + } +} + +static void hikp_nic_fd_print_ad_data(struct nic_fd_rule_info *rule) +{ + struct nic_fd_action action = {0}; + uint64_t ad_data; + + ad_data = (uint64_t)rule->ad_data_h << NIC_FD_AD_DATA_S | rule->ad_data_l; + printf("\n\tAction[ad data: 0x%llx]:\n", ad_data); + + hikp_nic_parse_ad_data(rule, &action); + + if (action.drop) + printf("\t Drop/accecpt: Drop"); + + if (action.q_vid) + printf("\t Direct Queue id: %u", action.qid); + + if (action.cnt_vld) + printf("\t Counter id: %u", action.cnt_id); + + if (action.nxt_vld) + printf("\t Next input key: %u", action.next_input_key); + + if (action.rule_id_vld) + printf("\t Rule id: %u", action.rule_id); + + if (action.tc_ovrd_en) + printf("\t start qid:%u Queue region size: %u", + action.qid, 1u << action.queue_region_size); +} + +static void hikp_nic_show_fd_rules(const void *data) +{ + struct nic_fd_rules *rules = ((union nic_fd_feature_info *)data)->rules; + uint16_t stage_no = g_fd_param.stage_no - 1; + struct nic_fd_rules *stage_rules; + struct nic_fd_key_cfg *key_cfg; + struct nic_fd_rule_info *rule; + uint16_t max_key_bytes; + size_t one_rule_size; + uint16_t i; + + key_cfg = &g_fd_hw_info.key_cfg[stage_no]; + stage_rules = &rules[stage_no]; + + max_key_bytes = hikp_nic_get_tcam_data_size(g_fd_hw_info.key_max_bit); + one_rule_size = sizeof(struct nic_fd_rule_info) + + sizeof(uint8_t) * max_key_bytes * HIKP_NIC_KEY_DIR_NUM; + + printf("fd stage%d rules info[rule_num=%u]:\n", g_fd_param.stage_no, stage_rules->rule_cnt); + for (i = 0; i < stage_rules->rule_cnt; i++) { + rule = (struct nic_fd_rule_info *)((uint8_t *)(stage_rules->rule) + + i * one_rule_size); + printf(" rule_idx: %u\n", rule->idx); + if (rule->valid == 0) { + printf("\tDriver doesn't configure the rule with this id!\n"); + return; + } + + hikp_nic_fd_print_key(rule, key_cfg, max_key_bytes); + + /* The meta data position is unknown if fd mode is unknown. */ + if (g_fd_hw_info.mode <= FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2) + hikp_nic_fd_print_meta_data(rule); + + hikp_nic_fd_print_ad_data(rule); + printf("\n"); + } +} + +static void hikp_nic_show_fd_counter(const void *data) +{ + struct nic_fd_counter *counter = ((union nic_fd_feature_info *)data)->counter; + uint16_t stage_no = g_fd_param.stage_no - 1; + struct nic_counter_entry *entry; + uint32_t i; + + printf("fd stage%d counter info:\n", g_fd_param.stage_no); + printf(" idx | hit_cnt\n"); + for (i = 0; i < counter[stage_no].counter_size; i++) { + entry = &counter[stage_no].entry[i]; + printf(" %3u | %llu\n", entry->idx, entry->value); + } +} + +static int hikp_nic_fd_get_blk(struct hikp_cmd_header *req_header, + const struct nic_fd_req_para *req_data, + void *buf, uint32_t buf_len, struct nic_fd_rsp_head *rsp_head) +{ + struct hikp_cmd_ret *cmd_ret; + struct nic_fd_rsp *rsp; + uint16_t idx; + int ret = 0; + + cmd_ret = hikp_cmd_alloc(req_header, req_data, sizeof(*req_data)); + if (cmd_ret == NULL) + return -EIO; + + rsp = (struct nic_fd_rsp *)cmd_ret->rsp_data; + if (rsp->rsp_head.cur_blk_size > buf_len) { + HIKP_ERROR_PRINT("nic_fd block context copy size error, " + "buffer size=%u, data size=%u.\n", + buf_len, rsp->rsp_head.cur_blk_size); + ret = -EINVAL; + goto out; + } + memcpy(buf, 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; + rsp_head->next_entry_idx = rsp->rsp_head.next_entry_idx; + rsp_head->cur_blk_entry_cnt = rsp->rsp_head.cur_blk_entry_cnt; + +out: + free(cmd_ret); + return ret; +} + +static int hikp_nic_query_fd_hw_info(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len) +{ + struct nic_fd_rsp_head rsp_head = {0}; + struct nic_fd_req_para req_data = {0}; + uint32_t total_blk_size; + uint8_t total_blk_num; + uint8_t blk_id = 0; + int ret = 0; + + req_data.bdf = *bdf; + req_data.block_id = blk_id; + req_data.stage = stage; + ret = hikp_nic_fd_get_blk(req_header, &req_data, data, len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get block-%u context.\n", blk_id); + return ret; + } + total_blk_num = rsp_head.total_blk_num; + total_blk_size = rsp_head.cur_blk_size; + + /* Copy the remaining block content if total block number is greater than 1. */ + for (blk_id = 1; blk_id < total_blk_num; blk_id++) { + req_data.block_id = blk_id; + ret = hikp_nic_fd_get_blk(req_header, &req_data, (uint8_t *)data + total_blk_size, + len - total_blk_size, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get block-%u context.\n", blk_id); + return ret; + } + total_blk_size += rsp_head.cur_blk_size; + } + + return ret; +} + +static int hikp_nic_query_fd_rules(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len) +{ + struct nic_fd_rsp_head rsp_head = {0}; + struct nic_fd_req_para req_data = {0}; + struct nic_fd_rule_info *entry; + struct nic_fd_rules *rules; + uint32_t entry_cnt = 0; + uint16_t max_key_bytes; + uint32_t left_buf_len; + size_t one_rule_size; + uint16_t idx; + int ret = 0; + + if (stage >= NIC_FD_STAGE_NUM) { + HIKP_ERROR_PRINT("The fd stage number(%d) is error!\n", stage + 1); + return -EIO; + } + + rules = (struct nic_fd_rules *)data + stage; + entry = rules->rule; + max_key_bytes = hikp_nic_get_tcam_data_size(g_fd_hw_info.key_max_bit); + one_rule_size = sizeof(struct nic_fd_rule_info) + max_key_bytes * HIKP_NIC_KEY_DIR_NUM; + + req_data.bdf = *bdf; + req_data.stage = stage; + req_data.query_single_entry = g_fd_param.id != -1 ? 1 : 0; + idx = g_fd_param.id != -1 ? g_fd_param.id : 0; + while (idx < g_fd_hw_info.alloc.stage_entry_num[stage]) { + req_data.cur_entry_idx = idx; + left_buf_len = one_rule_size * + (g_fd_hw_info.alloc.stage_entry_num[stage] - entry_cnt); + ret = hikp_nic_fd_get_blk(req_header, &req_data, + (uint8_t *)entry + entry_cnt * one_rule_size, + left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get rules after entry idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_cnt += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + if (req_data.query_single_entry == 1) + break; + } + rules->rule_cnt = entry_cnt; + + return ret; +} + +static int hikp_nic_query_fd_counter(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len) +{ + struct nic_fd_rsp_head rsp_head = {0}; + struct nic_fd_req_para req_data = {0}; + struct nic_counter_entry *entry; + struct nic_fd_counter *counter; + uint32_t entry_size = 0; + size_t left_buf_len; + uint16_t idx; + int ret = 0; + + if (stage >= NIC_FD_STAGE_NUM) { + HIKP_ERROR_PRINT("The fd stage number(%d) is error!\n", stage + 1); + return -EIO; + } + + counter = (struct nic_fd_counter *)data + stage; + entry = counter->entry; + + req_data.bdf = *bdf; + req_data.stage = stage; + req_data.query_single_entry = g_fd_param.id != -1 ? 1 : 0; + idx = g_fd_param.id != -1 ? g_fd_param.id : 0; + while (idx < g_fd_hw_info.alloc.stage_counter_num[stage]) { + req_data.cur_entry_idx = idx; + left_buf_len = sizeof(struct nic_counter_entry) * + (g_fd_hw_info.alloc.stage_counter_num[stage] - entry_size); + ret = hikp_nic_fd_get_blk(req_header, &req_data, entry + entry_size, + left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get the counter after entry idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_size += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + if (req_data.query_single_entry == 1) + break; + } + counter->counter_size = entry_size; + + return ret; +} + +static int hikp_nic_get_fd_hw_info(const struct bdf_t *bdf, struct nic_fd_hw_info *hw_info) +{ + struct hikp_cmd_header req_header = {0}; + + if (!g_fd_feature_cmd[g_fd_param.feature_idx].need_query_hw_spec) + return 0; + + hikp_cmd_init(&req_header, NIC_MOD, GET_FD_INFO_CMD, NIC_FD_HW_INFO_DUMP); + return hikp_nic_query_fd_hw_info(&req_header, bdf, NIC_FD_STAGE_1, (void *)hw_info, + sizeof(*hw_info)); +} + +static int hikp_nic_fd_alloc_rules_buf(struct nic_fd_rules *rules, uint8_t stage_num, + struct nic_fd_hw_info *hw_info, uint16_t stage_no) +{ + uint16_t max_key_bytes; + + max_key_bytes = hikp_nic_get_tcam_data_size(hw_info->key_max_bit); + rules[stage_no].rule = + (struct nic_fd_rule_info *)calloc(hw_info->alloc.stage_entry_num[stage_no], + sizeof(struct nic_fd_rule_info) + + sizeof(uint8_t) * max_key_bytes * HIKP_NIC_KEY_DIR_NUM); + if (rules[stage_no].rule == NULL) { + HIKP_ERROR_PRINT("Fail to alloc rule memory of stage1.\n"); + return -ENOMEM; + } + + return 0; +} + +static int hikp_nic_fd_alloc_counter_buf(struct nic_fd_counter *counter, uint8_t stage_num, + struct nic_fd_hw_info *hw_info, uint16_t stage_no) +{ + counter[stage_no].entry = + (struct nic_counter_entry *)calloc(hw_info->alloc.stage_counter_num[stage_no], + sizeof(struct nic_counter_entry)); + if (counter[stage_no].entry == NULL) { + HIKP_ERROR_PRINT("Fail to alloc counter memory of stage1.\n"); + return -ENOMEM; + } + + return 0; +} + +static union nic_fd_feature_info *hikp_nic_fd_data_alloc(const struct fd_feature_cmd *fd_cmd, + const struct nic_fd_hw_info *hw_cfg) +{ + uint16_t stage_no = g_fd_param.stage_no - 1; + union nic_fd_feature_info *fd_data; + int ret = 0; + + fd_data = (union nic_fd_feature_info *)calloc(1, sizeof(union nic_fd_feature_info)); + if (fd_data == NULL) { + HIKP_ERROR_PRINT("Fail to allocate nic_ppp_feature_info memory.\n"); + return NULL; + } + + if (strcmp(fd_cmd->feature_name, NIC_FD_RULES_NAME) == 0) + ret = hikp_nic_fd_alloc_rules_buf(fd_data->rules, NIC_FD_STAGE_NUM, + &g_fd_hw_info, stage_no); + else if (strcmp(fd_cmd->feature_name, NIC_FD_COUNTER_NAME) == 0) + ret = hikp_nic_fd_alloc_counter_buf(fd_data->counter, NIC_FD_STAGE_NUM, + &g_fd_hw_info, stage_no); + if (ret != 0) + goto out; + + return fd_data; + +out: + free(fd_data); + return NULL; +} + +static void hikp_nic_fd_data_free(union nic_fd_feature_info *fd_data) +{ + uint16_t stage_no = g_fd_param.stage_no - 1; + const struct fd_feature_cmd *fd_cmd; + + fd_cmd = &g_fd_feature_cmd[g_fd_param.feature_idx]; + if (strcmp(fd_cmd->feature_name, NIC_FD_RULES_NAME) == 0) + free(fd_data->rules[stage_no].rule); + else if (strcmp(fd_cmd->feature_name, NIC_FD_COUNTER_NAME) == 0) + free(fd_data->counter[stage_no].entry); + + free(fd_data); +} + +static int hikp_nic_check_fd_hw_info(const struct nic_fd_hw_info *hw_info, + const struct fd_feature_cmd *fd_cmd) +{ + uint16_t i; + + if (strcmp(fd_cmd->feature_name, NIC_FD_RULES_NAME) == 0) { + if (hw_info->mode > FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2) + HIKP_WARN_PRINT("Unknown fd mode(%u), " + "unsupport for displaying meta data info.\n", + hw_info->mode); + + for (i = 0; i < NIC_FD_STAGE_NUM; i++) { + if (hw_info->alloc.stage_entry_num[i] != 0 && + hw_info->key_cfg[i].key_select != HNS3_FD_KEY_BASE_ON_TUPLE) { + HIKP_ERROR_PRINT("Only support for displaying the tuple key info, " + "stage-%d key_select=%u\n", + i + 1, hw_info->key_cfg[i].key_select); + return -EOPNOTSUPP; + } + } + } + + return 0; +} + +static int hikp_nic_fd_check_entry_index_valid(struct major_cmd_ctrl *self, + struct nic_fd_param *fd_param, + const struct fd_feature_cmd *fd_cmd, + const struct nic_fd_hw_info *hw_info) +{ + uint32_t hw_entry_size; + uint8_t stage_no; + + /* Querying single entry info need to check entry_id validity. */ + if (fd_param->id != -1) { + stage_no = fd_param->stage_no - 1; + hw_entry_size = fd_cmd->sub_cmd_code == NIC_FD_RULES_INFO_DUMP ? + hw_info->alloc.stage_entry_num[stage_no] : + hw_info->alloc.stage_counter_num[stage_no]; + if (fd_param->id >= hw_entry_size) { + snprintf(self->err_str, sizeof(self->err_str), + "entry id(%d) must be less than hardware specifications(%u).", + fd_param->id, hw_entry_size); + self->err_no = -EINVAL; + return self->err_no; + } + } + + return 0; +} + +static int hikp_nic_fd_check_input_param(struct major_cmd_ctrl *self, + const struct nic_fd_param *fd_param) +{ + const struct bdf_t *bdf = &fd_param->target.bdf; + const struct fd_feature_cmd *fd_cmd; + + if (bdf->dev_id != 0) { + snprintf(self->err_str, sizeof(self->err_str), "VF does not support query!"); + self->err_no = -EINVAL; + return self->err_no; + } + + if (fd_param->feature_idx == -1) { + hikp_nic_fd_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-du/--dump parameter error!"); + self->err_no = -EINVAL; + return self->err_no; + } + + fd_cmd = &g_fd_feature_cmd[g_fd_param.feature_idx]; + if (fd_param->stage_no == -1 && fd_cmd->sub_cmd_code != NIC_FD_HW_INFO_DUMP) { + snprintf(self->err_str, sizeof(self->err_str), + "please input '-st/--stage' parameter."); + self->err_no = -EINVAL; + return self->err_no; + } + + if (fd_cmd->sub_cmd_code == NIC_FD_HW_INFO_DUMP && + (fd_param->id != -1 || fd_param->stage_no != -1)) { + snprintf(self->err_str, sizeof(self->err_str), + "no need '-id/--index' and '-st/--stage' parameter."); + self->err_no = -EINVAL; + return self->err_no; + } + + return 0; +} + +static void hikp_nic_fd_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_fd_param.target.bdf; + const struct fd_feature_cmd *fd_cmd; + union nic_fd_feature_info *fd_data; + struct hikp_cmd_header req_header = {0}; + uint8_t stage_no; + int ret; + + ret = hikp_nic_fd_check_input_param(self, &g_fd_param); + if (ret != 0) + return; + + ret = hikp_nic_get_fd_hw_info(bdf, &g_fd_hw_info); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), + "fail to obtain fd hardware configuration."); + self->err_no = ret; + return; + } + + fd_cmd = &g_fd_feature_cmd[g_fd_param.feature_idx]; + ret = hikp_nic_check_fd_hw_info(&g_fd_hw_info, fd_cmd); + if (ret != 0) { + self->err_no = ret; + return; + } + + ret = hikp_nic_fd_check_entry_index_valid(self, &g_fd_param, fd_cmd, &g_fd_hw_info); + if (ret != 0) + return; + + fd_data = hikp_nic_fd_data_alloc(fd_cmd, &g_fd_hw_info); + if (fd_data == NULL) { + HIKP_ERROR_PRINT("Fail to alloc fd data memory.\n"); + self->err_no = -ENOMEM; + return; + } + + /* The 'hw_info' cmd no need to input stage number, + * because it queries all stages information. + */ + stage_no = fd_cmd->sub_cmd_code == NIC_FD_HW_INFO_DUMP ? 0 : g_fd_param.stage_no - 1; + hikp_cmd_init(&req_header, NIC_MOD, GET_FD_INFO_CMD, fd_cmd->sub_cmd_code); + ret = fd_cmd->query(&req_header, bdf, g_fd_param.stage_no - 1, fd_data, sizeof(*fd_data)); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "failed to query %s info, ret = %d.", + fd_cmd->feature_name, ret); + self->err_no = ret; + goto out; + } + + printf("############## NIC FD: %s info ############\n", fd_cmd->feature_name); + fd_cmd->show(fd_data); + printf("#################### END #######################\n"); + +out: + hikp_nic_fd_data_free(fd_data); +} + +static int hikp_nic_cmd_get_fd_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_fd_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_cmd_fd_feature_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t feat_size = HIKP_ARRAY_SIZE(g_fd_feature_cmd); + size_t i; + + for (i = 0; i < feat_size; i++) { + if (strcmp(argv, g_fd_feature_cmd[i].feature_name) == 0) { + g_fd_param.feature_idx = i; + return 0; + } + } + + hikp_nic_fd_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "please input valid subfunction."); + self->err_no = -EINVAL; + + return self->err_no; +} + +static int hikp_nic_cmd_fd_parse_index(struct major_cmd_ctrl *self, const char *argv) +{ +#define HIKP_UINT16_MAX 0xffff + uint32_t id; + + self->err_no = string_toui(argv, &id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "parse --id/--index parameter failed."); + return self->err_no; + } + + if (id > HIKP_UINT16_MAX) { + snprintf(self->err_str, sizeof(self->err_str), + "the id is truncated. it should less than %u.", HIKP_UINT16_MAX); + self->err_no = -EINVAL; + return self->err_no; + } + + g_fd_param.id = (uint16_t)id; + + return 0; +} + +static int hikp_nic_cmd_fd_parse_stage(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t stage_no; + + self->err_no = string_toui(argv, &stage_no); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "parse -stage/--stage_no parameter failed."); + return self->err_no; + } + + if (stage_no == 0 || stage_no > NIC_FD_STAGE_NUM) { + snprintf(self->err_str, sizeof(self->err_str), + "-stage/--stage_no parameter is invalid, please use 1 or 2!"); + self->err_no = -EINVAL; + return self->err_no; + } + + if (stage_no - 1 == NIC_FD_STAGE_2) { + snprintf(self->err_str, sizeof(self->err_str), + "unsupport for querying stage%u entry!", stage_no); + self->err_no = -EOPNOTSUPP; + return self->err_no; + } + + g_fd_param.stage_no = (uint16_t)stage_no; + + return 0; +} + +static void cmd_nic_get_fd_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_fd_param.id = -1; + g_fd_param.stage_no = -1; + g_fd_param.feature_idx = -1; + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_fd_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_fd_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_get_fd_target); + cmd_option_register("-du", "--dump", true, hikp_nic_cmd_fd_feature_select); + cmd_option_register("-id", "--index", true, hikp_nic_cmd_fd_parse_index); + cmd_option_register("-st", "--stage", true, hikp_nic_cmd_fd_parse_stage); +} + +HIKP_CMD_DECLARE("nic_fd", "dump fd info of nic!", cmd_nic_get_fd_init); diff --git a/net/nic/nic_fd/hikp_nic_fd.h b/net/nic/nic_fd/hikp_nic_fd.h new file mode 100644 index 0000000..3f409d0 --- /dev/null +++ b/net/nic/nic_fd/hikp_nic_fd.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2022 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_NIC_FD_H +#define HIKP_NIC_FD_H + +#include "hikp_net_lib.h" + +/* OUTER_XXX indicates tuples in tunnel header of tunnel packet + * INNER_XXX indicate tuples in tunneled header of tunnel packet or + * tuples of non-tunnel packet + */ +enum nic_fd_tuple { + OUTER_DST_MAC = 0, + OUTER_SRC_MAC, + OUTER_VLAN_TAG_FST, + OUTER_VLAN_TAG_SEC, + OUTER_ETH_TYPE, + OUTER_L2_RSV, + OUTER_IP_TOS, + OUTER_IP_PROTO, + OUTER_SRC_IP, + OUTER_DST_IP, + OUTER_L3_RSV, + OUTER_SRC_PORT, + OUTER_DST_PORT, + OUTER_L4_RSV, + OUTER_TUN_VNI, + OUTER_TUN_FLOW_ID, + INNER_DST_MAC, + INNER_SRC_MAC, + INNER_VLAN_TAG_FST, + INNER_VLAN_TAG_SEC, + INNER_ETH_TYPE, + INNER_L2_RSV, + INNER_IP_TOS, + INNER_IP_PROTO, + INNER_SRC_IP, + INNER_DST_IP, + INNER_L3_RSV, + INNER_SRC_PORT, + INNER_DST_PORT, + INNER_L4_RSV, + MAX_TUPLE, +}; + +enum nic_fd_meta_data { + PACKET_TYPE_ID = 0, + IP_FRAGEMENT, + ROCE_TYPE, + NEXT_KEY, + VLAN_NUMBER, + SRC_VPORT, + DST_VPORT, + TUNNEL_PACKET, + MAX_META_DATA, +}; + +enum nic_fd_sub_cmd_type { + NIC_FD_HW_INFO_DUMP = 0, + NIC_FD_RULES_INFO_DUMP, + NIC_FD_COUNTER_STATS_DUMP, +}; + +enum HNS3_FD_KEY_TYPE { + HNS3_FD_KEY_BASE_ON_PTYPE, + HNS3_FD_KEY_BASE_ON_TUPLE, +}; + +#define NIC_KEY_LEN_400B 400 +#define NIC_KEY_LEN_200B 200 + +enum nic_fd_mode { + FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1 = 0, + FD_MODE_DEPTH_1K_WIDTH_400B_STAGE_2, + FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1, + FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2, +}; + +enum nic_fd_stage { + NIC_FD_STAGE_1 = 0, + NIC_FD_STAGE_2, + NIC_FD_STAGE_NUM, +}; + +struct nic_fd_alloc { + uint32_t stage_entry_num[NIC_FD_STAGE_NUM]; + uint16_t stage_counter_num[NIC_FD_STAGE_NUM]; +}; + +struct nic_fd_key_cfg { + uint8_t stage; + uint8_t key_select; + uint8_t inner_src_ipv6_word_en; + uint8_t inner_dest_ipv6_word_en; + uint8_t outer_src_ipv6_word_en; + uint8_t outer_dest_ipv6_word_en; + uint8_t rsv1[2]; + uint32_t tuple_mask; + uint32_t meta_data_mask; +}; + +struct nic_fd_hw_info { + uint8_t mode; + uint8_t enable; + uint16_t key_max_bit; + struct nic_fd_alloc alloc; + struct nic_fd_key_cfg key_cfg[NIC_FD_STAGE_NUM]; +}; + +#define NIC_FD_AD_DATA_S 32 +#define NIC_FD_AD_DROP_B 0 +#define NIC_FD_AD_DIRECT_QID_B 1 +#define NIC_FD_AD_QID_S 2 +#define NIC_FD_AD_QID_M GENMASK(11, 2) +#define NIC_FD_AD_USE_COUNTER_B 12 +#define NIC_FD_AD_COUNTER_NUM_S 13 +#define NIC_FD_AD_COUNTER_NUM_M GENMASK(19, 13) +#define NIC_FD_AD_NXT_STEP_B 20 +#define NIC_FD_AD_NXT_KEY_S 21 +#define NIC_FD_AD_NXT_KEY_M GENMASK(25, 21) +#define NIC_FD_AD_WR_RULE_ID_B 0 +#define NIC_FD_AD_RULE_ID_S 1 +#define NIC_FD_AD_RULE_ID_M GENMASK(12, 1) +#define NIC_FD_AD_QUEUE_REGION_EN_B 16 +#define NIC_FD_AD_QUEUE_REGION_SIZE_S 17 +#define NIC_FD_AD_QUEUE_REGION_SIZE_M GENMASK(20, 17) +#define NIC_FD_AD_COUNTER_HIGH_BIT 7 +#define NIC_FD_AD_COUNTER_HIGH_BIT_B 26 +#define NIC_FD_AD_QUEUE_ID_HIGH_BIT 10 +#define NIC_FD_AD_QUEUE_ID_HIGH_BIT_B 21 + +#define HIKP_DWORDS_BYTE 4 + +#define HIKP_NIC_KEY_DIR_NUM 2 +struct nic_fd_rule_info { + uint32_t idx; /* relative idx */ + uint8_t valid; + uint8_t rsv[3]; + uint32_t ad_data_l; + uint32_t ad_data_h; + /* Note: TCAM data must be an integer multiple of 4. This is an agreement with the firmware. + * The memory will be allocated to save key_x and key_y. + * Memory order: first key_x, then key_y. + */ + uint8_t tcam_data[0]; /* first key_x, then key_y memory */ +}; + +/* Data from firmware is rule info, rule_cnt is accumulated on tool side. */ +struct nic_fd_rules { + uint32_t rule_cnt; + struct nic_fd_rule_info *rule; +}; + +struct nic_counter_entry { + uint16_t idx; + uint16_t rsv1[3]; + uint64_t value; +}; + +/* Data from firmware is counter entry, counter_size is accumulated on tool side. */ +struct nic_fd_counter { + uint32_t counter_size; + struct nic_counter_entry *entry; +}; + +union nic_fd_feature_info { + struct nic_fd_hw_info hw_info; + struct nic_fd_rules rules[NIC_FD_STAGE_NUM]; + struct nic_fd_counter counter[NIC_FD_STAGE_NUM]; +}; + +struct nic_fd_rsp_head { + uint8_t total_blk_num; + uint8_t cur_blk_size; /* real data size, not contain head size. */ + uint16_t rsv1; + /* firmware must set following fields when query fd rules and counter. */ + uint32_t next_entry_idx; + uint16_t cur_blk_entry_cnt; + uint16_t rsv2; +}; + +#define NIC_FD_MAX_RSP_DATA 57 +struct nic_fd_rsp { + struct nic_fd_rsp_head rsp_head; /* 12 Byte */ + uint32_t rsp_data[NIC_FD_MAX_RSP_DATA]; +}; + +struct nic_fd_req_para { + struct bdf_t bdf; + uint8_t block_id; + uint8_t stage; /* 0: stage1, 1: stage2 */ + uint8_t query_single_entry; + uint8_t rsv1; + uint32_t cur_entry_idx; +}; + +struct nic_fd_param { + struct tool_target target; + int feature_idx; + /* The following fields for querying one rule or counter entry. */ + int id; + int stage_no; + bool query_single_entry; +}; + +#define HIKP_FD_MAX_FEATURE_NAME_LEN 20 +struct fd_feature_cmd { + const char feature_name[HIKP_FD_MAX_FEATURE_NAME_LEN]; + uint32_t sub_cmd_code; + bool need_query_hw_spec; + int (*query)(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + uint8_t stage, void *data, size_t len); + void (*show)(const void *data); +}; + +#endif /* HIKP_NIC_FD_H */ diff --git a/net/nic/nic_fec/hikp_nic_fec.c b/net/nic/nic_fec/hikp_nic_fec.c new file mode 100644 index 0000000..5d9025c --- /dev/null +++ b/net/nic/nic_fec/hikp_nic_fec.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_fec.h" + +static struct tool_target g_fec_target; + +static int hikp_nic_fec_err_query(const struct bdf_t *bdf, struct nic_fec_err_info *info) +{ + struct nic_fec_req_para req = { 0 }; + struct hikp_cmd_header header = { 0 }; + struct hikp_cmd_ret *cmd_ret; + struct nic_fec_rsp *rsp; + + req.bdf = *bdf; + hikp_cmd_init(&header, NIC_MOD, GET_FEC_INFO_CMD, NIC_FEC_ERR_INFO_DUMP); + cmd_ret = hikp_cmd_alloc(&header, &req, sizeof(req)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("fail to get fec info, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + free(cmd_ret); + return -EIO; + } + + rsp = (struct nic_fec_rsp *)cmd_ret->rsp_data; + *info = *(struct nic_fec_err_info *)rsp->data; + free(cmd_ret); + + if (info->fec_mode >= NIC_FEC_MODE_BUTT) { + HIKP_ERROR_PRINT("unknown fec mode: %u\n", info->fec_mode); + return -EINVAL; + } + + return 0; +} + +static const char *hikp_nic_fec_mode_name(const uint32_t mode) +{ + static const char *name[] = { "Off", "BaseR", "RS", "LLRS" }; + + if (mode < HIKP_ARRAY_SIZE(name)) + return name[mode]; + else + return "unknown"; +} + +static void hikp_nic_fec_err_show_basefec(const struct nic_fec_err_info *info) +{ + uint32_t lane_num = HIKP_MIN(info->basefec.lane_num, NIC_FEC_MAX_LANES); + uint64_t total; + uint32_t i; + + printf("Statistics:\n"); + + /* show corrected blocks */ + for (total = 0, i = 0; i < lane_num; i++) + total += info->basefec.lane_corr_block_cnt[i]; + + printf(" corrected_blocks: %llu\n", total); + for (i = 0; i < lane_num; i++) + printf(" Lane %u: %u\n", i, info->basefec.lane_corr_block_cnt[i]); + + /* show uncorrected blocks */ + for (total = 0, i = 0; i < lane_num; i++) + total += info->basefec.lane_uncorr_block_cnt[i]; + + printf(" uncorrectable_blocks: %llu\n", total); + for (i = 0; i < lane_num; i++) + printf(" Lane %u: %u\n", i, info->basefec.lane_uncorr_block_cnt[i]); +} + +static void hikp_nic_fec_err_show_rsfec(const struct nic_fec_err_info *info) +{ + printf("Statistics:\n"); + printf(" corrected_blocks: %u\n", info->rsfec.corr_cw_cnt); + printf(" uncorrectable_blocks: %u\n", info->rsfec.uncorr_cw_cnt); +} + +static void hikp_nic_fec_err_show(const struct nic_fec_err_info *info) +{ + printf("############## NIC FEC err info ################\n"); + /* The output format similar to 'ethtool -I --show-fec ethx' */ + printf("Active FEC encoding: %s\n", hikp_nic_fec_mode_name(info->fec_mode)); + if (info->fec_mode == NIC_FEC_MODE_BASEFEC) { + hikp_nic_fec_err_show_basefec(info); + } else if (info->fec_mode == NIC_FEC_MODE_RSFEC || + info->fec_mode == NIC_FEC_MODE_LLRSFEC) { + hikp_nic_fec_err_show_rsfec(info); + } else { + /* Do nothing */ + } + printf("#################### END #######################\n"); +} + +static void hikp_nic_fec_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_fec_target.bdf; + struct nic_fec_err_info info; + int ret; + + ret = hikp_nic_fec_err_query(bdf, &info); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "fail to obtain fec err info."); + self->err_no = ret; + return; + } + + hikp_nic_fec_err_show(&info); +} + +static int hikp_nic_fec_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + + return 0; +} + +static int hikp_nic_fec_get_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &g_fec_target); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + if (g_fec_target.bdf.dev_id != 0) { + snprintf(self->err_str, sizeof(self->err_str), "VF is not supported!"); + self->err_no = -EINVAL; + return self->err_no; + } + + return 0; +} + +static void cmd_nic_fec_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_fec_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_fec_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_fec_get_target); +} + +HIKP_CMD_DECLARE("nic_fec", "dump fec info of nic!", cmd_nic_fec_init); diff --git a/net/nic/nic_fec/hikp_nic_fec.h b/net/nic/nic_fec/hikp_nic_fec.h new file mode 100644 index 0000000..7996273 --- /dev/null +++ b/net/nic/nic_fec/hikp_nic_fec.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 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_NIC_FEC_H +#define HIKP_NIC_FEC_H + +#include "hikp_net_lib.h" + +enum nic_fec_sub_cmd_type { + NIC_FEC_ERR_INFO_DUMP, +}; + +enum nic_fec_mode_type { + NIC_FEC_MODE_NOFEC = 0, + NIC_FEC_MODE_BASEFEC, + NIC_FEC_MODE_RSFEC, + NIC_FEC_MODE_LLRSFEC, + NIC_FEC_MODE_BUTT +}; + +struct nic_fec_req_para { + struct bdf_t bdf; + uint8_t block_id; + uint8_t rsv[3]; +}; + +struct nic_fec_rsp_head { + uint8_t total_blk_num; + uint8_t curr_blk_size; /* real data size, not contain head size. */ + uint16_t rsv; +}; + +#define NIC_FEC_MAX_RSP_DATA 59 +struct nic_fec_rsp { + struct nic_fec_rsp_head head; + uint32_t data[NIC_FEC_MAX_RSP_DATA]; +}; + +#define NIC_FEC_MAX_LANES 8 +struct nic_basefec_stats { + uint32_t corr_block_cnt; + uint32_t uncorr_block_cnt; + uint32_t lane_num; + uint32_t lane_corr_block_cnt[NIC_FEC_MAX_LANES]; + uint32_t lane_uncorr_block_cnt[NIC_FEC_MAX_LANES]; +}; + +struct nic_rsfec_stats { + uint32_t corr_cw_cnt; + uint32_t uncorr_cw_cnt; + uint32_t err_cw_cnt; +}; + +struct nic_fec_err_info { + uint32_t fec_mode; + union { + struct nic_basefec_stats basefec; + struct nic_rsfec_stats rsfec; + }; +}; + +#endif /* HIKP_NIC_FEC_H */ diff --git a/net/nic/nic_gro/hikp_nic_gro.c b/net/nic/nic_gro/hikp_nic_gro.c new file mode 100644 index 0000000..84b54c8 --- /dev/null +++ b/net/nic/nic_gro/hikp_nic_gro.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_gro.h" + +static struct tool_target g_gro_target; + +static int hikp_nic_gro_query(const struct bdf_t *bdf, struct nic_gro_info *info) +{ + struct nic_gro_req_para req = { 0 }; + struct hikp_cmd_header header = { 0 }; + struct hikp_cmd_ret *cmd_ret; + struct nic_gro_rsp *rsp; + + req.bdf = *bdf; + hikp_cmd_init(&header, NIC_MOD, GET_GRO_INFO_CMD, NIC_GRO_INFO_DUMP); + cmd_ret = hikp_cmd_alloc(&header, &req, sizeof(req)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("fail to get gro info, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + free(cmd_ret); + return -EIO; + } + + rsp = (struct nic_gro_rsp *)cmd_ret->rsp_data; + *info = *(struct nic_gro_info *)rsp->data; + free(cmd_ret); + + return 0; +} + +static void hikp_nic_gro_show(const struct nic_gro_info *info) +{ + printf("################ NIC GRO info ##################\n"); + printf("gro_en: %s\n", info->gro_en ? "true" : "false"); + printf("max_coal_bd_num: %u\n", info->max_coal_bd_num); + printf("#################### END #######################\n"); +} + +static void hikp_nic_gro_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_gro_target.bdf; + struct nic_gro_info info; + int ret; + + ret = hikp_nic_gro_query(bdf, &info); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "fail to obtain gro info."); + self->err_no = ret; + return; + } + + hikp_nic_gro_show(&info); +} + +static int hikp_nic_gro_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + + return 0; +} + +static int hikp_nic_gro_get_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &g_gro_target); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + return 0; +} + +static void cmd_nic_gro_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_gro_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_gro_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_gro_get_target); +} + +HIKP_CMD_DECLARE("nic_gro", "dump gro info of nic!", cmd_nic_gro_init); diff --git a/net/nic/nic_gro/hikp_nic_gro.h b/net/nic/nic_gro/hikp_nic_gro.h new file mode 100644 index 0000000..49328e6 --- /dev/null +++ b/net/nic/nic_gro/hikp_nic_gro.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 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_NIC_GRO_H +#define HIKP_NIC_GRO_H + +#include "hikp_net_lib.h" + +enum nic_gro_sub_cmd_type { + NIC_GRO_INFO_DUMP, +}; + +struct nic_gro_req_para { + struct bdf_t bdf; + uint8_t block_id; + uint8_t rsv[3]; +}; + +struct nic_gro_rsp_head { + uint8_t total_blk_num; + uint8_t curr_blk_size; /* real data size, not contain head size. */ + uint16_t rsv; +}; + +#define NIC_GRO_MAX_RSP_DATA 59 +struct nic_gro_rsp { + struct nic_gro_rsp_head head; + uint32_t data[NIC_GRO_MAX_RSP_DATA]; +}; + +struct nic_gro_info { + uint32_t gro_en; + uint32_t max_coal_bd_num; +}; + +#endif /* HIKP_NIC_GRO_H */ diff --git a/net/nic/nic_ppp/hikp_nic_ppp.c b/net/nic/nic_ppp/hikp_nic_ppp.c new file mode 100644 index 0000000..28c867d --- /dev/null +++ b/net/nic/nic_ppp/hikp_nic_ppp.c @@ -0,0 +1,1110 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_ppp.h" + +static struct hikp_nic_ppp_hw_resources g_ppp_hw_res = { 0 }; +static struct nic_ppp_param g_ppp_param = { 0 }; + +static void hikp_nic_ppp_show_mac_tbl(const void *data); +static void hikp_nic_ppp_show_vlan_tbl(const void *data); +static void hikp_nic_ppp_show_promisc_tbl(const void *data); +static void hikp_nic_ppp_show_manager_tbl(const void *data); +static void hikp_nic_ppp_show_vlan_offload(const void *data); + +static int hikp_nic_query_ppp_by_blkid(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + void *data, size_t len); +static int hikp_nic_query_ppp_by_entryid(struct hikp_cmd_header *req_header, + const struct bdf_t *bdf, + void *data, size_t len); + +#define HIKP_NIC_FUNC_NAME_LEN 8 +#define HIKP_NIC_PPP_FUNC_BITMAP_SIZE 32 + +#define HIKP_NIC_PPP_VLAN_ID_NUM_PER_LEN 6 + +#define NIC_PPP_MAC_TBL_NAME "mac" +#define NIC_PPP_VLAN_TBL_NAME "vlan" +#define NIC_PPP_MNG_TBL_NAME "mng" + +static const struct ppp_feature_cmd g_ppp_feature_cmd[] = { + {NIC_PPP_MAC_TBL_NAME, NIC_MAC_TBL_DUMP, true, + hikp_nic_query_ppp_by_entryid, hikp_nic_ppp_show_mac_tbl}, + {NIC_PPP_VLAN_TBL_NAME, NIC_VLAN_TBL_DUMP, true, + hikp_nic_query_ppp_by_entryid, hikp_nic_ppp_show_vlan_tbl}, + {NIC_PPP_MNG_TBL_NAME, NIC_MNG_TBL_DUMP, true, + hikp_nic_query_ppp_by_entryid, hikp_nic_ppp_show_manager_tbl}, + {"promisc", NIC_PROMISCUOUS_TBL_DUMP, false, + hikp_nic_query_ppp_by_blkid, hikp_nic_ppp_show_promisc_tbl}, + {"vlan_offload", NIC_VLAN_OFFLOAD_DUMP, false, + hikp_nic_query_ppp_by_blkid, hikp_nic_ppp_show_vlan_offload}, +}; + +static int hikp_nic_ppp_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + printf("%s\n", + " [-du/--dump mac -func/--func_id -uc/--unicast <1/0>]\n" + " dump MAC table info.\n" + " dump unicast/multicast MAC address for a function.\n" + " [-du/--dump vlan -func/--function ]\n" + " dump VLAN table info.\n" + " dump VLAN of a function.\n" + " [-du/--dump mng]\n" + " dump manager table info.\n" + " [-du/--dump promisc]\n" + " dump promiscuous info.\n" + " [-du/--dump vlan_offload]\n" + " dump VLAN offload info.\n"); + + return 0; +} + +static uint16_t hikp_nic_ppp_get_abs_func_id(const struct bdf_t *bdf, int relative_func_id) +{ + uint16_t abs_func_id; + + if (relative_func_id == 0) + abs_func_id = bdf->fun_id; + else + abs_func_id = g_ppp_hw_res.abs_func_id_base + relative_func_id - 1; + + return abs_func_id; +} + +static void hikp_nic_ppp_get_func_name(char *buf, uint8_t len, uint8_t id) +{ + if (id > 0) + snprintf(buf, len, "vf%d", id - 1); + else + snprintf(buf, len, "pf"); +} + +static void hikp_nic_ppp_get_overflow_mac(struct nic_mac_tbl *of_tbl, struct nic_mac_tbl *tbl) +{ + struct mac_vlan_uc_tbl *of_uc_tbl = &of_tbl->uc_tbl; + struct mac_vlan_mc_tbl *of_mc_tbl = &of_tbl->mc_tbl; + struct mac_vlan_uc_tbl *uc_tbl = &tbl->uc_tbl; + struct mac_vlan_mc_tbl *mc_tbl = &tbl->mc_tbl; + uint32_t idx = 0; + uint32_t i; + + for (i = 0; i < uc_tbl->entry_size; i++) { + struct mac_vlan_uc_entry *entry = &uc_tbl->entry[i]; + + if (entry->idx >= g_ppp_hw_res.max_key_mem_size) + of_uc_tbl->entry[idx++] = *entry; + } + of_uc_tbl->entry_size = idx; + + idx = 0; + for (i = 0; i < mc_tbl->entry_size; i++) { + struct mac_vlan_mc_entry *entry = &mc_tbl->entry[i]; + + if (entry->idx >= g_ppp_hw_res.max_key_mem_size) + of_mc_tbl->entry[idx++] = *entry; + } + of_mc_tbl->entry_size = idx; +} + +static void hikp_nic_ppp_show_key_mem(struct nic_mac_tbl *tbl, bool is_key_mem) +{ + struct mac_vlan_uc_tbl *uc_tbl = &tbl->uc_tbl; + struct mac_vlan_mc_tbl *mc_tbl = &tbl->mc_tbl; + char mac_str[HIKP_NIC_ETH_ADDR_FMT_SIZE]; + struct mac_vlan_uc_entry *uc_entry; + struct mac_vlan_mc_entry *mc_entry; + uint32_t idx; + + printf("%s[total_entry_size=%u]:\n", is_key_mem ? "Key mem" : "Overflow cam", + is_key_mem ? g_ppp_hw_res.max_key_mem_size : g_ppp_hw_res.overflow_cam_size); + printf("Unicast MAC table[entry number=%u]:\n", uc_tbl->entry_size); + printf("index | valid | mac_addr | " + "vlan_id | VMDq1 | mac_en | in_port(mac_id) | E_vPort_type | E_vPort\n"); + for (idx = 0; idx < uc_tbl->entry_size; idx++) { + uc_entry = &uc_tbl->entry[idx]; + if (uc_entry->idx < g_ppp_hw_res.max_key_mem_size || !is_key_mem) { + hikp_ether_format_addr(mac_str, + HIKP_NIC_ETH_ADDR_FMT_SIZE, uc_entry->mac_addr); + printf("%04u | %01u | %s | ", uc_entry->idx, uc_entry->valid, mac_str); + printf("%04u | %u | %01u | ", + uc_entry->vlan_id, uc_entry->vmdq1, uc_entry->mac_en); + printf("%01u | %01u | %06x", + uc_entry->ingress_port, uc_entry->e_vport_type, uc_entry->e_vport); + printf("\n"); + } + } + + printf("Multicast MAC table[entry number=%u]:\n", mc_tbl->entry_size); + printf("index | mac_addr | func bitMap[255 <-- 0]\n"); + for (idx = 0; idx < mc_tbl->entry_size; idx++) { + mc_entry = &mc_tbl->entry[idx]; + if (mc_entry->idx < g_ppp_hw_res.max_key_mem_size || !is_key_mem) { + hikp_ether_format_addr(mac_str, + HIKP_NIC_ETH_ADDR_FMT_SIZE, mc_entry->mac_addr); + printf("%04u | %s | ", mc_entry->idx, mac_str); + printf("%08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x", + mc_entry->function_bitmap[7], mc_entry->function_bitmap[6], + mc_entry->function_bitmap[5], mc_entry->function_bitmap[4], + mc_entry->function_bitmap[3], mc_entry->function_bitmap[2], + mc_entry->function_bitmap[1], mc_entry->function_bitmap[0]); + printf("\n"); + } + } +} + +static void hikp_nic_ppp_show_func_uc_mac_addr(struct mac_vlan_uc_tbl *uc_tbl, + const struct bdf_t *bdf, uint16_t func_id) +{ + char mac_str[HIKP_NIC_ETH_ADDR_FMT_SIZE]; + struct mac_vlan_uc_entry *uc_entry; + uint8_t pf_id; + uint8_t vf_id; + uint8_t i; + + for (i = 0; i < uc_tbl->entry_size; i++) { + uc_entry = &uc_tbl->entry[i]; + if (uc_entry->idx >= g_ppp_hw_res.max_key_mem_size) + break; + + pf_id = hikp_get_field(uc_entry->e_vport, HIKP_NIC_PF_ID_MASK, HIKP_NIC_PF_ID_S); + vf_id = hikp_get_field(uc_entry->e_vport, HIKP_NIC_VF_ID_MASK, HIKP_NIC_VF_ID_S); + if (bdf->fun_id == pf_id && vf_id == func_id) { + hikp_ether_format_addr(mac_str, HIKP_NIC_ETH_ADDR_FMT_SIZE, + uc_entry->mac_addr); + printf("\t%s\n", mac_str); + } + } +} + +static void hikp_nic_ppp_show_func_mc_mac_addr(struct mac_vlan_mc_tbl *mc_tbl, + const struct bdf_t *bdf, uint16_t func_id) +{ + char mac_str[HIKP_NIC_ETH_ADDR_FMT_SIZE]; + struct mac_vlan_mc_entry *mc_entry; + uint16_t abs_func_id; + uint8_t offset; + uint8_t idx; + uint8_t i; + + abs_func_id = hikp_nic_ppp_get_abs_func_id(bdf, func_id); + idx = abs_func_id / HIKP_NIC_PPP_FUNC_BITMAP_SIZE; + offset = abs_func_id % HIKP_NIC_PPP_FUNC_BITMAP_SIZE; + + for (i = 0; i < mc_tbl->entry_size; i++) { + mc_entry = &mc_tbl->entry[i]; + if (mc_entry->idx >= g_ppp_hw_res.max_key_mem_size) + break; + + if (hikp_get_bit(mc_entry->function_bitmap[idx], offset) != 0) { + hikp_ether_format_addr(mac_str, HIKP_NIC_ETH_ADDR_FMT_SIZE, + mc_entry->mac_addr); + printf("\t%s\n", mac_str); + } + } +} + +static void hikp_nic_ppp_show_func_mac(struct nic_mac_tbl *tbl, + const struct nic_ppp_param *ppp_param) +{ + const struct bdf_t *bdf = &ppp_param->target.bdf; + char func_name[HIKP_NIC_FUNC_NAME_LEN]; + uint16_t abs_func_id; + + abs_func_id = hikp_nic_ppp_get_abs_func_id(bdf, ppp_param->func_id); + hikp_nic_ppp_get_func_name(func_name, sizeof(func_name), ppp_param->func_id); + printf("%s_abs_func_id=%u\n", func_name, abs_func_id); + printf("%s %s MAC addrs:\n", func_name, ppp_param->is_uc == 1 ? "unicast" : "multicast"); + if (ppp_param->is_uc == 1) { + hikp_nic_ppp_show_func_uc_mac_addr(&tbl->uc_tbl, bdf, ppp_param->func_id); + return; + } + + hikp_nic_ppp_show_func_mc_mac_addr(&tbl->mc_tbl, bdf, ppp_param->func_id); +} + +static void hikp_nic_ppp_show_mac_tbl(const void *data) +{ + struct nic_mac_tbl overflow_tbl = {0}; + struct mac_vlan_uc_entry *of_uc_entry; + struct mac_vlan_mc_entry *of_mc_entry; + + /* Display unicast or multicast MAC address in the specified function. */ + if (g_ppp_param.func_id != -1) { + hikp_nic_ppp_show_func_mac((struct nic_mac_tbl *)data, &g_ppp_param); + return; + } + + hikp_nic_ppp_show_key_mem((struct nic_mac_tbl *)data, true); + + of_uc_entry = (struct mac_vlan_uc_entry *)calloc(g_ppp_hw_res.overflow_cam_size, + sizeof(struct mac_vlan_uc_entry)); + if (of_uc_entry == NULL) { + HIKP_ERROR_PRINT("Failed to alloc memory for overflow uc table.\n"); + return; + } + + of_mc_entry = (struct mac_vlan_mc_entry *)calloc(g_ppp_hw_res.overflow_cam_size, + sizeof(struct mac_vlan_mc_entry)); + if (of_mc_entry == NULL) { + HIKP_ERROR_PRINT("Failed to alloc memory for overflow mc table.\n"); + free(of_uc_entry); + return; + } + + overflow_tbl.uc_tbl.entry = of_uc_entry; + overflow_tbl.mc_tbl.entry = of_mc_entry; + hikp_nic_ppp_get_overflow_mac(&overflow_tbl, (struct nic_mac_tbl *)data); + hikp_nic_ppp_show_key_mem(&overflow_tbl, false); + + free(of_uc_entry); + free(of_mc_entry); +} + +static void hikp_nic_ppp_show_port_vlan_info(const struct port_vlan_tbl *port_tbl, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + struct port_vlan_tbl_entry *port_entry; + uint32_t mac_id = hw_res->mac_id; + uint8_t vlan_cnt = 0; + uint32_t i; + + printf("mac_id=%u\n", hw_res->mac_id); + printf("total_func_num=%u\n", hw_res->total_func_num); + printf("abs_func_id_base=%u\n", hw_res->abs_func_id_base); + printf("port VLAN id:\n\t"); + for (i = 0; i < port_tbl->entry_size; i++) { + port_entry = &port_tbl->entry[i]; + if (hikp_get_bit(port_entry->port_bitmap, mac_id) != 0) { + printf("%4u ", port_entry->vlan_id); + vlan_cnt++; + if (vlan_cnt == HIKP_NIC_PPP_VLAN_ID_NUM_PER_LEN) { + printf("\n\t"); + vlan_cnt = 0; + } + } + } + printf("\n"); +} + +static void hikp_nic_ppp_show_vf_vlan_info(const struct vf_vlan_tbl *vf_tbl, uint16_t func_id, + const struct bdf_t *bdf, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + char func_name[HIKP_NIC_FUNC_NAME_LEN]; + struct vf_vlan_tbl_entry *vf_entry; + uint16_t abs_func_id; + uint8_t vlan_cnt = 0; + uint8_t offset; + uint8_t idx; + uint32_t i; + + abs_func_id = hikp_nic_ppp_get_abs_func_id(bdf, func_id); + idx = abs_func_id / HIKP_NIC_PPP_FUNC_BITMAP_SIZE; + offset = abs_func_id % HIKP_NIC_PPP_FUNC_BITMAP_SIZE; + hikp_nic_ppp_get_func_name(func_name, sizeof(func_name), func_id); + printf("%s_abs_func_id: %u\n", func_name, + (uint32_t)(g_ppp_hw_res.abs_func_id_base + func_id - 1)); + printf("%s VLAN id:\n\t", func_name); + for (i = 0; i < vf_tbl->entry_size; i++) { + vf_entry = &vf_tbl->entry[i]; + if (hikp_get_bit(vf_entry->func_bitmap[idx], offset) != 0) { + printf("%4u ", vf_entry->vlan_id); + vlan_cnt++; + if (vlan_cnt == HIKP_NIC_PPP_VLAN_ID_NUM_PER_LEN) { + printf("\n\t"); + vlan_cnt = 0; + } + } + } + printf("\n"); +} + +static void hikp_nic_ppp_show_func_vlan(const struct nic_vlan_tbl *vlan_tbl, + const struct nic_ppp_param *ppp_param) +{ + const struct port_vlan_tbl *port_tbl = &vlan_tbl->port_vlan_tbl; + const struct vf_vlan_tbl *vf_tbl = &vlan_tbl->vf_vlan_tbl; + const struct bdf_t *bdf = &ppp_param->target.bdf; + + /* VF VLAN filter table isn't configured by DPDK driver, + * so we have to get VLAN id by port VLAN table. + */ + if (ppp_param->func_id == 0) { + hikp_nic_ppp_show_port_vlan_info(port_tbl, &g_ppp_hw_res); + return; + } + + hikp_nic_ppp_show_vf_vlan_info(vf_tbl, ppp_param->func_id, bdf, &g_ppp_hw_res); +} + +static void hikp_nic_ppp_show_vlan_tbl(const void *data) +{ + struct nic_vlan_tbl *tbl = (struct nic_vlan_tbl *)data; + struct port_vlan_tbl *port_tbl = &tbl->port_vlan_tbl; + struct vf_vlan_tbl *vf_tbl = &tbl->vf_vlan_tbl; + uint32_t i; + + /* Display vlan information in the specified function. */ + if (g_ppp_param.func_id != -1) { + hikp_nic_ppp_show_func_vlan(tbl, &g_ppp_param); + return; + } + + printf("port_vlan_table_size=%u\n", g_ppp_hw_res.port_vlan_tbl_size); + printf("vf_vlan_table_size=%u\n", g_ppp_hw_res.vf_vlan_tbl_size); + printf("vlan_id | vf filter bitmap[func_255 <--- func_0]\n"); + for (i = 0; i < vf_tbl->entry_size; i++) { + printf(" %04u | %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n", + vf_tbl->entry[i].vlan_id, + vf_tbl->entry[i].func_bitmap[7], vf_tbl->entry[i].func_bitmap[6], + vf_tbl->entry[i].func_bitmap[5], vf_tbl->entry[i].func_bitmap[4], + vf_tbl->entry[i].func_bitmap[3], vf_tbl->entry[i].func_bitmap[2], + vf_tbl->entry[i].func_bitmap[1], vf_tbl->entry[i].func_bitmap[0]); + } + + printf("vlan_id | port filter bitmap(based on mac_id)\n"); + for (i = 0; i < port_tbl->entry_size; i++) + printf(" %04u | %02x\n", + port_tbl->entry[i].vlan_id, port_tbl->entry[i].port_bitmap); +} + +static void hikp_nic_ppp_show_manager_tbl(const void *data) +{ + struct nic_mng_tbl *tbl = (struct nic_mng_tbl *)data; + char mac_str[HIKP_NIC_ETH_ADDR_FMT_SIZE]; + struct manager_entry *entry; + uint32_t i; + + printf("manager_table_size=%u\n", g_ppp_hw_res.mng_tbl_size); + printf("entry | mac | mask | ether | mask | vlan | mask " + "| i_map | i_dir | e_type | pf_id | vf_id | q_id | drop\n"); + for (i = 0; i < tbl->entry_size; i++) { + entry = &tbl->entry[i]; + hikp_ether_format_addr(mac_str, HIKP_NIC_ETH_ADDR_FMT_SIZE, entry->mac_addr); + printf(" %02u | %s | %u ", entry->entry_no, mac_str, entry->mac_mask); + printf("| %04x | %u | %04u | %u ", + entry->ether_type, entry->ether_mask, entry->vlan_id, entry->vlan_mask); + printf("| %02x | %02x | %01u | %02u | %03u | %04u | %u", + entry->i_port_bitmap, entry->i_port_dir, entry->e_port_type, + entry->pf_id, entry->vf_id, entry->q_id, entry->drop); + } + printf("\n"); +} + +static void hikp_nic_ppp_show_promisc_tbl(const void *data) +{ + struct nic_promisc_tbl *tbl = (struct nic_promisc_tbl *)data; + char func_name[HIKP_NIC_FUNC_NAME_LEN]; + struct func_promisc_cfg *func; + uint16_t i; + + printf("func_id\t uc_en\t mc_en\t bc_en\n"); + for (i = 0; i < tbl->func_num; i++) { + func = &tbl->func[i]; + hikp_nic_ppp_get_func_name(func_name, HIKP_NIC_FUNC_NAME_LEN, func->func_id); + printf("%s\t %u\t %u\t %u\n", func_name, func->uc_en, func->mc_en, func->bc_en); + } +} + +static void hikp_nic_ppp_show_vlan_offload(const void *data) +{ + struct nic_vlan_offload_cfg *tbl = (struct nic_vlan_offload_cfg *)data; + const char * const state_str[] = { "off", "on" }; + char func_name[HIKP_NIC_FUNC_NAME_LEN]; + struct func_vlan_offload_cfg *func; + uint8_t ingress, egress; + uint16_t i; + + ingress = !!(tbl->port_vlan_fe & HIKP_FILTER_FE_NIC_INGRESS_B); + egress = !!(tbl->port_vlan_fe & HIKP_FILTER_FE_NIC_EGRESS_B); + printf("port VLAN filter configuration:\n"); + printf("ingress_port_vlan_filter: %s\n", state_str[ingress]); + printf("egress_port_vlan_filter: %s\n", state_str[egress]); + + printf("func VLAN filter configuration:\n"); + printf("func_id\t ingress_vlan_filter\t egress_vlan_filter\t port_vlan_filter_bypass\n"); + for (i = 0; i < tbl->func_num; i++) { + func = &tbl->func[i]; + ingress = !!(func->vlan_fe & HIKP_FILTER_FE_NIC_INGRESS_B); + egress = !!(func->vlan_fe & HIKP_FILTER_FE_NIC_EGRESS_B); + hikp_nic_ppp_get_func_name(func_name, HIKP_NIC_FUNC_NAME_LEN, i); + printf("%s\t %s\t\t\t %s\t\t\t %s\n", func_name, state_str[ingress], + state_str[egress], + func->port_vlan_bypass > 1 ? "NA" : state_str[func->port_vlan_bypass]); + } + + printf("func VLAN offload configuration:\n"); + printf("func_id\tpvid\taccept_tag1\taccept_tag2\taccept_untag1\taccept_untag2\t" + "insert_tag1\tinsert_tag2\tshift_tag\tstrip_tag1\tstrip_tag2\tdrop_tag1\t" + "drop_tag2\tpri_only_tag1\tpri_only_tag2\n"); + for (i = 0; i < tbl->func_num; i++) { + func = &tbl->func[i]; + hikp_nic_ppp_get_func_name(func_name, HIKP_NIC_FUNC_NAME_LEN, i); + printf("%s\t%u\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t" + "%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\n", func_name, + func->pvid, state_str[!!func->accept_tag1], state_str[!!func->accept_tag2], + state_str[!!func->accept_untag1], state_str[!!func->accept_untag2], + state_str[!!func->insert_tag1], state_str[!!func->insert_tag2], + state_str[!!func->shift_tag], state_str[!!func->strip_tag1], + state_str[!!func->strip_tag2], state_str[!!func->drop_tag1], + state_str[!!func->drop_tag2], state_str[!!func->pri_only_tag1], + state_str[!!func->pri_only_tag2]); + } +} + +static int hikp_nic_ppp_get_blk(struct hikp_cmd_header *req_header, + const struct nic_ppp_req_para *req_data, + void *buf, size_t buf_len, struct nic_ppp_rsp_head *rsp_head) +{ + struct hikp_cmd_ret *cmd_ret; + struct nic_ppp_rsp *rsp; + int ret = 0; + + cmd_ret = hikp_cmd_alloc(req_header, req_data, sizeof(*req_data)); + if (cmd_ret == NULL) + return -EIO; + + rsp = (struct nic_ppp_rsp *)cmd_ret->rsp_data; + if (rsp->rsp_head.cur_blk_size > buf_len) { + HIKP_ERROR_PRINT("nic_ppp block context copy size error, " + "buffer size=%u, data size=%u.\n", + buf_len, rsp->rsp_head.cur_blk_size); + ret = -EINVAL; + goto out; + } + memcpy(buf, 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; + rsp_head->next_entry_idx = rsp->rsp_head.next_entry_idx; + rsp_head->cur_blk_entry_cnt = rsp->rsp_head.cur_blk_entry_cnt; + +out: + free(cmd_ret); + return ret; +} + +static int hikp_nic_ppp_query_uc_mac_addr(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct mac_vlan_uc_tbl *uc_tbl, + uint16_t max_hw_entry_size) +{ + struct mac_vlan_uc_entry *uc_entry = uc_tbl->entry; + struct nic_ppp_rsp_head rsp_head = {0}; + uint32_t entry_size = 0; + size_t left_buf_len; + uint16_t idx = 0; + int ret = 0; + + while (idx < max_hw_entry_size) { + req_data->cur_entry_idx = idx; + req_data->is_unicast = 1; + left_buf_len = sizeof(struct mac_vlan_uc_entry) * (max_hw_entry_size - entry_size); + ret = hikp_nic_ppp_get_blk(req_header, req_data, + uc_entry + entry_size, left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get the uc entry after idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_size += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + } + uc_tbl->entry_size = entry_size; + + return ret; +} + +static int hikp_nic_ppp_query_mc_mac_addr(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct mac_vlan_mc_tbl *mc_tbl, + uint16_t max_hw_entry_size) +{ + struct mac_vlan_mc_entry *mc_entry = mc_tbl->entry; + struct nic_ppp_rsp_head rsp_head = {0}; + uint32_t entry_size = 0; + size_t left_buf_len; + uint16_t idx = 0; + int ret = 0; + + while (idx < max_hw_entry_size) { + req_data->cur_entry_idx = idx; + req_data->is_unicast = 0; + left_buf_len = sizeof(struct mac_vlan_mc_entry) * (max_hw_entry_size - entry_size); + ret = hikp_nic_ppp_get_blk(req_header, req_data, + mc_entry + entry_size, left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get the mc entry after idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_size += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + } + mc_tbl->entry_size = entry_size; + + return ret; +} + +static int hikp_nic_query_mac_tbl(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct nic_mac_tbl *mac_tbl) +{ + struct mac_vlan_uc_tbl *uc_tbl = &mac_tbl->uc_tbl; + struct mac_vlan_mc_tbl *mc_tbl = &mac_tbl->mc_tbl; + uint32_t max_hw_entry_size; + int ret = 0; + bool query; + + max_hw_entry_size = g_ppp_hw_res.max_key_mem_size + g_ppp_hw_res.overflow_cam_size; + query = g_ppp_param.is_uc != -1 ? (g_ppp_param.is_uc == 1) : true; + if (query) { + ret = hikp_nic_ppp_query_uc_mac_addr(req_header, req_data, + uc_tbl, max_hw_entry_size); + if (ret != 0) + return ret; + } + + query = g_ppp_param.is_uc != -1 ? (g_ppp_param.is_uc == 0) : true; + if (query) { + ret = hikp_nic_ppp_query_mc_mac_addr(req_header, req_data, + mc_tbl, max_hw_entry_size); + if (ret != 0) + return ret; + } + + return ret; +} + +static int hikp_nic_ppp_query_vf_vlan_tbl(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct vf_vlan_tbl *vlan_tbl, uint16_t hw_entry_size) +{ + struct vf_vlan_tbl_entry *vf_entry = vlan_tbl->entry; + struct nic_ppp_rsp_head rsp_head = {0}; + uint32_t entry_size = 0; + size_t left_buf_len; + uint32_t idx = 0; + int ret = 0; + + while (idx < hw_entry_size) { + req_data->cur_entry_idx = idx; + req_data->is_port_vlan = 0; + left_buf_len = sizeof(struct vf_vlan_tbl_entry) * (hw_entry_size - entry_size); + ret = hikp_nic_ppp_get_blk(req_header, req_data, + vf_entry + entry_size, left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get the vf vlan entry after idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_size += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + } + vlan_tbl->entry_size = entry_size; + + return ret; +} + +static int hikp_nic_ppp_query_port_vlan_tbl(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct port_vlan_tbl *vlan_tbl, uint16_t hw_entry_size) +{ + struct port_vlan_tbl_entry *port_entry = vlan_tbl->entry; + struct nic_ppp_rsp_head rsp_head = {0}; + uint32_t entry_size = 0; + size_t left_buf_len; + uint32_t idx = 0; + int ret = 0; + + while (idx < hw_entry_size) { + req_data->cur_entry_idx = idx; + req_data->is_port_vlan = 1; + left_buf_len = sizeof(struct port_vlan_tbl_entry) * (hw_entry_size - entry_size); + ret = hikp_nic_ppp_get_blk(req_header, req_data, + port_entry + entry_size, left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get the port vlan entry after idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_size += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + } + vlan_tbl->entry_size = entry_size; + + return ret; +} + +static int hikp_nic_query_vlan_tbl(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct nic_vlan_tbl *vlan_tbl) +{ + struct port_vlan_tbl *port_vlan_tbl = &vlan_tbl->port_vlan_tbl; + struct vf_vlan_tbl *vf_vlan_tbl = &vlan_tbl->vf_vlan_tbl; + int ret; + + ret = hikp_nic_ppp_query_vf_vlan_tbl(req_header, req_data, vf_vlan_tbl, + g_ppp_hw_res.vf_vlan_tbl_size); + if (ret != 0) + return ret; + + ret = hikp_nic_ppp_query_port_vlan_tbl(req_header, req_data, port_vlan_tbl, + g_ppp_hw_res.port_vlan_tbl_size); + if (ret != 0) + return ret; + + return ret; +} + +static int hikp_nic_query_mng_tbl(struct hikp_cmd_header *req_header, + struct nic_ppp_req_para *req_data, + struct nic_mng_tbl *mng_tbl) +{ + struct manager_entry *entry = mng_tbl->entry; + struct nic_ppp_rsp_head rsp_head = {0}; + uint32_t entry_size = 0; + size_t left_buf_len; + uint32_t idx = 0; + int ret = 0; + + while (idx < g_ppp_hw_res.mng_tbl_size) { + req_data->cur_entry_idx = idx; + left_buf_len = sizeof(struct manager_entry) * + (g_ppp_hw_res.mng_tbl_size - entry_size); + ret = hikp_nic_ppp_get_blk(req_header, req_data, + entry + entry_size, left_buf_len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get the mng entry after idx=%u, ret=%d.\n", + idx, ret); + return ret; + } + entry_size += rsp_head.cur_blk_entry_cnt; + idx = rsp_head.next_entry_idx; + } + mng_tbl->entry_size = entry_size; + + return ret; +} + +static int hikp_nic_query_ppp_by_entryid(struct hikp_cmd_header *req_header, + const struct bdf_t *bdf, + void *data, size_t len) +{ + const struct ppp_feature_cmd *ppp_cmd; + struct nic_ppp_req_para req_data = {0}; + + req_data.bdf = *bdf; + ppp_cmd = &g_ppp_feature_cmd[g_ppp_param.feature_idx]; + if (strcmp(ppp_cmd->feature_name, NIC_PPP_MAC_TBL_NAME) == 0) + return hikp_nic_query_mac_tbl(req_header, &req_data, (struct nic_mac_tbl *)data); + else if (strcmp(ppp_cmd->feature_name, NIC_PPP_VLAN_TBL_NAME) == 0) + return hikp_nic_query_vlan_tbl(req_header, &req_data, (struct nic_vlan_tbl *)data); + else + return hikp_nic_query_mng_tbl(req_header, &req_data, (struct nic_mng_tbl *)data); +} + +static int hikp_nic_query_ppp_by_blkid(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + void *data, size_t len) +{ + struct nic_ppp_rsp_head rsp_head = {0}; + struct nic_ppp_req_para req_data = {0}; + uint32_t total_blk_size; + uint8_t total_blk_num; + uint8_t blk_id = 0; + int ret = 0; + + req_data.bdf = *bdf; + req_data.block_id = blk_id; + ret = hikp_nic_ppp_get_blk(req_header, &req_data, data, len, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get block-%u context.\n", blk_id); + return ret; + } + total_blk_num = rsp_head.total_blk_num; + total_blk_size = rsp_head.cur_blk_size; + + /* Copy the remaining block content if total block number is greater than 1. */ + for (blk_id = 1; blk_id < total_blk_num; blk_id++) { + req_data.block_id = blk_id; + ret = hikp_nic_ppp_get_blk(req_header, &req_data, (uint8_t *)data + total_blk_size, + len - total_blk_size, &rsp_head); + if (ret != 0) { + HIKP_ERROR_PRINT("Fail to get block-%u context.\n", blk_id); + return ret; + } + total_blk_size += rsp_head.cur_blk_size; + } + + return ret; +} + +static int hikp_nic_ppp_get_hw_resources(const struct bdf_t *bdf, + struct hikp_nic_ppp_hw_resources *hw_res) +{ + struct hikp_cmd_header req_header = {0}; + + if (!g_ppp_feature_cmd[g_ppp_param.feature_idx].need_query_hw_res) + return 0; + + hikp_cmd_init(&req_header, NIC_MOD, GET_PPP_INFO_CMD, NIC_PPP_HW_RES_DUMP); + return hikp_nic_query_ppp_by_blkid(&req_header, bdf, hw_res, sizeof(*hw_res)); +} + +static int hikp_nic_ppp_alloc_mac_tbl_entry(struct nic_mac_tbl *mac_tbl, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + uint32_t max_entry_size; + + max_entry_size = hw_res->max_key_mem_size + hw_res->overflow_cam_size; + mac_tbl->uc_tbl.entry = (struct mac_vlan_uc_entry *)calloc(max_entry_size, + sizeof(struct mac_vlan_uc_entry)); + if (mac_tbl->uc_tbl.entry == NULL) { + HIKP_ERROR_PRINT("Fail to alloc uc_entry memory.\n"); + return -ENOMEM; + } + + mac_tbl->mc_tbl.entry = (struct mac_vlan_mc_entry *)calloc(max_entry_size, + sizeof(struct mac_vlan_mc_entry)); + if (mac_tbl->mc_tbl.entry == NULL) { + HIKP_ERROR_PRINT("Fail to alloc mc_entry memory.\n"); + free(mac_tbl->uc_tbl.entry); + return -ENOMEM; + } + + return 0; +} + +static int hikp_nic_ppp_alloc_vlan_tbl_entry(struct nic_vlan_tbl *vlan_tbl, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + vlan_tbl->port_vlan_tbl.entry = + (struct port_vlan_tbl_entry *)calloc(hw_res->port_vlan_tbl_size, + sizeof(struct port_vlan_tbl_entry)); + if (vlan_tbl->port_vlan_tbl.entry == NULL) { + HIKP_ERROR_PRINT("Fail to alloc port_vlan_tbl_entry memory.\n"); + return -ENOMEM; + } + + vlan_tbl->vf_vlan_tbl.entry = (struct vf_vlan_tbl_entry *)calloc(hw_res->vf_vlan_tbl_size, + sizeof(struct vf_vlan_tbl_entry)); + if (vlan_tbl->vf_vlan_tbl.entry == NULL) { + HIKP_ERROR_PRINT("Fail to alloc vf_vlan_tbl_entry memory.\n"); + free(vlan_tbl->port_vlan_tbl.entry); + return -ENOMEM; + } + + return 0; +} + +static int hikp_nic_ppp_alloc_mng_tbl_entry(struct nic_mng_tbl *mng_tbl, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + mng_tbl->entry = (struct manager_entry *)calloc(hw_res->mng_tbl_size, + sizeof(struct manager_entry)); + if (mng_tbl->entry == NULL) { + HIKP_ERROR_PRINT("fail to alloc manager_entry memory.\n"); + return -ENOMEM; + } + + return 0; +} + +static union nic_ppp_feature_info *hikp_nic_ppp_data_alloc(const struct ppp_feature_cmd *ppp_cmd, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + union nic_ppp_feature_info *ppp_data; + int ret = 0; + + ppp_data = (union nic_ppp_feature_info *)calloc(1, sizeof(union nic_ppp_feature_info)); + if (ppp_data == NULL) { + HIKP_ERROR_PRINT("Fail to allocate nic_ppp_feature_info memory.\n"); + return NULL; + } + + if (strcmp(ppp_cmd->feature_name, NIC_PPP_MAC_TBL_NAME) == 0) + ret = hikp_nic_ppp_alloc_mac_tbl_entry(&ppp_data->mac_tbl, hw_res); + else if (strcmp(ppp_cmd->feature_name, NIC_PPP_VLAN_TBL_NAME) == 0) + ret = hikp_nic_ppp_alloc_vlan_tbl_entry(&ppp_data->vlan_tbl, hw_res); + else if (strcmp(ppp_cmd->feature_name, NIC_PPP_MNG_TBL_NAME) == 0) + ret = hikp_nic_ppp_alloc_mng_tbl_entry(&ppp_data->mng_tbl, hw_res); + if (ret != 0) + goto out; + + return ppp_data; + +out: + free(ppp_data); + + return NULL; +} + +static void hikp_nic_ppp_data_free(union nic_ppp_feature_info *ppp_data) +{ + const struct ppp_feature_cmd *ppp_cmd; + struct nic_vlan_tbl *vlan_tbl; + struct nic_mac_tbl *mac_tbl; + struct nic_mng_tbl *mng_tbl; + + ppp_cmd = &g_ppp_feature_cmd[g_ppp_param.feature_idx]; + if (strcmp(ppp_cmd->feature_name, NIC_PPP_MAC_TBL_NAME) == 0) { + mac_tbl = &ppp_data->mac_tbl; + free(mac_tbl->uc_tbl.entry); + free(mac_tbl->mc_tbl.entry); + } else if (strcmp(ppp_cmd->feature_name, NIC_PPP_VLAN_TBL_NAME) == 0) { + vlan_tbl = &ppp_data->vlan_tbl; + free(vlan_tbl->vf_vlan_tbl.entry); + free(vlan_tbl->port_vlan_tbl.entry); + } else if (strcmp(ppp_cmd->feature_name, NIC_PPP_MNG_TBL_NAME) == 0) { + mng_tbl = &ppp_data->mng_tbl; + free(mng_tbl->entry); + } + free(ppp_data); +} + +static int hikp_nic_ppp_check_optional_param(struct major_cmd_ctrl *self, + const struct nic_ppp_param *ppp_param, + const struct ppp_feature_cmd *ppp_cmd) +{ + switch (ppp_cmd->sub_cmd_code) { + case NIC_MAC_TBL_DUMP: + if ((ppp_param->func_id != -1 && ppp_param->is_uc == -1) || + (ppp_param->func_id == -1 && ppp_param->is_uc != -1)) { + snprintf(self->err_str, sizeof(self->err_str), + "please input func_id and unicast value at the same time."); + self->err_no = -EINVAL; + return self->err_no; + } + break; + case NIC_VLAN_TBL_DUMP: + if (ppp_param->is_uc != -1) { + snprintf(self->err_str, sizeof(self->err_str), + "%s cmd no need '-uc/--unicast' parameter", + ppp_cmd->feature_name); + self->err_no = -EINVAL; + return self->err_no; + } + break; + case NIC_MNG_TBL_DUMP: + case NIC_PROMISCUOUS_TBL_DUMP: + case NIC_VLAN_OFFLOAD_DUMP: + if (ppp_param->func_id != -1 || ppp_param->is_uc != -1) { + snprintf(self->err_str, sizeof(self->err_str), + "%s cmd no need '-func/--func_id' and '-uc/--unicast' parameter", + ppp_cmd->feature_name); + self->err_no = -EINVAL; + return self->err_no; + } + break; + default: + break; + } + + return 0; +} + +static int hikp_nic_ppp_check_input_param(struct major_cmd_ctrl *self, + const struct nic_ppp_param *ppp_param) +{ + const struct bdf_t *bdf = &ppp_param->target.bdf; + const struct ppp_feature_cmd *ppp_cmd; + + if (bdf->dev_id != 0) { + snprintf(self->err_str, sizeof(self->err_str), "VF does not support query!"); + self->err_no = -EINVAL; + return self->err_no; + } + + if (ppp_param->feature_idx == -1) { + hikp_nic_ppp_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-du/--dump parameter error!"); + self->err_no = -EINVAL; + return self->err_no; + } + + ppp_cmd = &g_ppp_feature_cmd[g_ppp_param.feature_idx]; + return hikp_nic_ppp_check_optional_param(self, ppp_param, ppp_cmd); +} + +static int hikp_nic_check_func_id_valid(struct major_cmd_ctrl *self, + const struct ppp_feature_cmd *ppp_cmd, + const struct nic_ppp_param *ppp_param, + const struct hikp_nic_ppp_hw_resources *hw_res) +{ + if (ppp_param->func_id >= hw_res->total_func_num) { + snprintf(self->err_str, sizeof(self->err_str), + "-func/--func_id parameter is invalid, func_id should be less than %u.", + hw_res->total_func_num); + self->err_no = -EINVAL; + return self->err_no; + } + + return 0; +} + +static void hikp_nic_ppp_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_ppp_param.target.bdf; + const struct ppp_feature_cmd *ppp_cmd; + union nic_ppp_feature_info *ppp_data; + struct hikp_cmd_header req_header = {0}; + int ret; + + ret = hikp_nic_ppp_check_input_param(self, &g_ppp_param); + if (ret != 0) + return; + + ret = hikp_nic_ppp_get_hw_resources(bdf, &g_ppp_hw_res); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), + "fail to obtain ppp hardware resources."); + self->err_no = ret; + return; + } + + ppp_cmd = &g_ppp_feature_cmd[g_ppp_param.feature_idx]; + ret = hikp_nic_check_func_id_valid(self, ppp_cmd, &g_ppp_param, &g_ppp_hw_res); + if (ret != 0) + return; + + ppp_data = hikp_nic_ppp_data_alloc(ppp_cmd, &g_ppp_hw_res); + if (ppp_data == NULL) { + snprintf(self->err_str, sizeof(self->err_str), + "failed to allocate ppp_data memory!"); + self->err_no = -ENOMEM; + return; + } + + hikp_cmd_init(&req_header, NIC_MOD, GET_PPP_INFO_CMD, ppp_cmd->sub_cmd_code); + ret = ppp_cmd->query(&req_header, &g_ppp_param.target.bdf, ppp_data, + sizeof(union nic_ppp_feature_info)); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), + "failed to query %s info, ret = %d.", ppp_cmd->feature_name, ret); + self->err_no = ret; + goto out; + } + + printf("############## NIC PPP: %s info ############\n", ppp_cmd->feature_name); + ppp_cmd->show(ppp_data); + printf("#################### END #######################\n"); + +out: + hikp_nic_ppp_data_free(ppp_data); +} + +static int hikp_nic_cmd_get_ppp_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_ppp_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_cmd_ppp_feature_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t feat_size = HIKP_ARRAY_SIZE(g_ppp_feature_cmd); + size_t i; + + for (i = 0; i < feat_size; i++) { + if (strcmp(argv, g_ppp_feature_cmd[i].feature_name) == 0) { + g_ppp_param.feature_idx = i; + return 0; + } + } + + hikp_nic_ppp_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "please input valid subfunction."); + self->err_no = -EINVAL; + + return self->err_no; +} + +static int hikp_nic_cmd_ppp_parse_func_id(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t func_id; + + self->err_no = string_toui(argv, &func_id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "parse -func/--function parameter failed."); + return self->err_no; + } + + if (func_id >= HIKP_NIC_MAX_FUNC_NUM) { + snprintf(self->err_str, sizeof(self->err_str), + "maximum func_id should be less than %u.", HIKP_NIC_MAX_FUNC_NUM); + self->err_no = -EINVAL; + return self->err_no; + } + + g_ppp_param.func_id = (uint16_t)func_id; + + return 0; +} + +static int hikp_nic_cmd_ppp_parse_unicast(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + + self->err_no = string_toui(argv, &val); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "parse -un/--unicast parameter failed."); + return self->err_no; + } + + if (val != 0 && val != 1) { + snprintf(self->err_str, sizeof(self->err_str), + "please input 0 or 1 for -un/--unicast parameter."); + self->err_no = -EINVAL; + return self->err_no; + } + + g_ppp_param.is_uc = val; + + return 0; +} + +static void cmd_nic_get_ppp_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_ppp_param.func_id = -1; + g_ppp_param.is_uc = -1; + g_ppp_param.feature_idx = -1; + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_ppp_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_ppp_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_get_ppp_target); + cmd_option_register("-du", "--dump", true, hikp_nic_cmd_ppp_feature_select); + cmd_option_register("-func", "--func_id", true, hikp_nic_cmd_ppp_parse_func_id); + cmd_option_register("-uc", "--unicast", true, hikp_nic_cmd_ppp_parse_unicast); +} + +HIKP_CMD_DECLARE("nic_ppp", "dump ppp info of nic!", cmd_nic_get_ppp_init); diff --git a/net/nic/nic_ppp/hikp_nic_ppp.h b/net/nic/nic_ppp/hikp_nic_ppp.h new file mode 100644 index 0000000..033ca4d --- /dev/null +++ b/net/nic/nic_ppp/hikp_nic_ppp.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2022 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_NIC_PPP_H +#define HIKP_NIC_PPP_H + +#include "hikp_net_lib.h" + +enum nic_ppp_sub_cmd_type { + NIC_PPP_HW_RES_DUMP = 0, + NIC_MAC_TBL_DUMP, + NIC_VLAN_TBL_DUMP, + NIC_MNG_TBL_DUMP, + NIC_PROMISCUOUS_TBL_DUMP, + NIC_VLAN_OFFLOAD_DUMP, +}; + +#define HIKP_NIC_ENTRY_FUNC_BITMAP_CNT 8 + +struct hikp_nic_ppp_hw_resources { + uint32_t max_key_mem_size; + uint32_t overflow_cam_size; + uint32_t mng_tbl_size; + uint16_t port_vlan_tbl_size; + uint16_t vf_vlan_tbl_size; + /* port information */ + uint16_t total_func_num; /* contain PF and VF. */ + uint16_t abs_func_id_base; /* The absolute func_id of the first VF in this port. */ + uint32_t mac_id; + uint32_t rsv1[10]; +}; + +/* struct mac_vlan_uc_entry::e_vport field defination: + * bit[0-2]: pf_id + * bit[3-10]: vf_id + */ +#define HIKP_NIC_PF_ID_MASK 0x7 +#define HIKP_NIC_PF_ID_S 0 +#define HIKP_NIC_VF_ID_MASK 0x7f8 +#define HIKP_NIC_VF_ID_S 3 + +struct mac_vlan_uc_entry { + uint32_t idx; + uint8_t mac_addr[HIKP_NIC_ETH_MAC_ADDR_LEN]; + uint16_t valid; + uint16_t ingress_port; + uint16_t vlan_id; + uint16_t mac_en; + uint16_t vmdq1; + uint16_t u_m; + uint16_t e_vport_type; + uint16_t e_vport; + uint16_t rsv; +}; + +struct mac_vlan_mc_entry { + uint32_t idx; + uint8_t mac_addr[HIKP_NIC_ETH_MAC_ADDR_LEN]; + uint16_t rsv; + uint32_t function_bitmap[HIKP_NIC_ENTRY_FUNC_BITMAP_CNT]; +}; + +/* Data from firmware is unicast MAC table entry, entry_size is accumulated on tool side. */ +struct mac_vlan_uc_tbl { + uint32_t entry_size; + struct mac_vlan_uc_entry *entry; +}; + +/* Data from firmware is multicast MAC table entry, entry_size is accumulated on tool side. */ +struct mac_vlan_mc_tbl { + uint32_t entry_size; + struct mac_vlan_mc_entry *entry; +}; + +struct nic_mac_tbl { + struct mac_vlan_uc_tbl uc_tbl; + struct mac_vlan_mc_tbl mc_tbl; +}; + +struct port_vlan_tbl_entry { + uint16_t vlan_id; + uint8_t port_bitmap; + uint8_t rsv; +}; + +/* Data from firmware is port vlan table entry, entry_size is accumulated on tool side. */ +struct port_vlan_tbl { + uint32_t entry_size; + struct port_vlan_tbl_entry *entry; +}; + +struct vf_vlan_tbl_entry { + uint16_t vlan_id; + uint16_t rsv; + uint32_t func_bitmap[HIKP_NIC_ENTRY_FUNC_BITMAP_CNT]; /* 256bits */ +}; + +/* Data from firmware is vf vlan table entry, entry_size is accumulated on tool side. */ +struct vf_vlan_tbl { + uint32_t entry_size; + struct vf_vlan_tbl_entry *entry; +}; + +struct nic_vlan_tbl { + struct vf_vlan_tbl vf_vlan_tbl; + struct port_vlan_tbl port_vlan_tbl; +}; + +struct manager_entry { + uint32_t entry_no; + uint8_t mac_addr[HIKP_NIC_ETH_MAC_ADDR_LEN]; + uint8_t mac_mask; + uint8_t ether_mask; + uint16_t ether_type; + uint16_t vlan_id; + uint8_t vlan_mask; + uint8_t i_port_bitmap; + uint8_t i_port_dir; + /* 1: Drop the packet when match, 0: Forward the packet to E_vport/queue_id when match. */ + uint8_t drop; + /* port type value + * 1: Network port(corresponding to MAC, the one facing the external switch), + * 0: RX egress port + */ + uint8_t e_port_type; + uint8_t pf_id; + uint16_t vf_id; + uint16_t q_id; + uint16_t rsv; +}; + +/* Data from firmware is manager entry, entry_size is accumulated on tool side. */ +struct nic_mng_tbl { + uint32_t entry_size; + struct manager_entry *entry; +}; + +struct func_vlan_offload_cfg { + uint16_t vlan_fe; + uint16_t pvid; + uint8_t port_vlan_bypass; /* 0: off, 1: on, 2: unsupport port vlan */ + uint8_t accept_tag1; + uint8_t accept_tag2; + uint8_t accept_untag1; + uint8_t accept_untag2; + uint8_t insert_tag1; + uint8_t insert_tag2; + uint8_t shift_tag; + uint8_t strip_tag1; + uint8_t strip_tag2; + uint8_t drop_tag1; + uint8_t drop_tag2; + uint8_t pri_only_tag1; + uint8_t pri_only_tag2; + uint8_t rsv[2]; +}; + +#define HIKP_FILTER_FE_NIC_INGRESS_B HI_BIT(0) +#define HIKP_FILTER_FE_NIC_EGRESS_B HI_BIT(1) +struct nic_vlan_offload_cfg { + uint8_t port_vlan_fe; + uint8_t rsv; + uint16_t func_num; /* contain PF and VFs */ + struct func_vlan_offload_cfg func[HIKP_NIC_MAX_FUNC_NUM]; +}; + +struct func_promisc_cfg { + uint8_t func_id; + uint8_t uc_en; + uint8_t mc_en; + uint8_t bc_en; +}; + +struct nic_promisc_tbl { + uint16_t func_num; + uint16_t rsv; + struct func_promisc_cfg func[HIKP_NIC_MAX_FUNC_NUM]; +}; + +union nic_ppp_feature_info { + struct nic_mac_tbl mac_tbl; + struct nic_vlan_tbl vlan_tbl; + struct nic_mng_tbl mng_tbl; + struct nic_promisc_tbl promisc_tbl; + struct nic_vlan_offload_cfg vlan_offload; +}; + +struct nic_ppp_rsp_head { + uint8_t total_blk_num; + uint8_t cur_blk_size; /* real data size, not contain head size. */ + uint16_t rsv; + /* firmware must set following fields when query MAC/VLAN/MNG table. */ + uint32_t next_entry_idx; + uint32_t cur_blk_entry_cnt; +}; + +#define NIC_PPP_MAX_RSP_DATA 57 +struct nic_ppp_rsp { + struct nic_ppp_rsp_head rsp_head; /* 12 Byte */ + uint32_t rsp_data[NIC_PPP_MAX_RSP_DATA]; +}; + +struct nic_ppp_req_para { + struct bdf_t bdf; + uint8_t block_id; + union { + uint8_t is_unicast; /* 1: uc MAC, 0: mc MAC. */ + uint8_t is_port_vlan; /* 1: port vlan table, 0: vf vlan table. */ + uint8_t rsv; /* firmware ignores it if isn't used to query MAC/VLAN table. */ + }; + uint8_t rsv1[2]; + uint32_t cur_entry_idx; /* firmware queries MAC/VLAN/MNG table from the valuue. */ +}; + +struct nic_ppp_param { + struct tool_target target; + int feature_idx; + /* 'func_id' is used to control whether to + * query all entries or the entry of a specified function. + * It will be used when query MAC or VLAN table. Value range: + * -1: query all entries + * 0: means PF + * > 0: means VF + */ + int func_id; + int is_uc; /* Must be specified when query one function entry for mac or vlan cmd. */ +}; + +#define HIKP_PPP_MAX_FEATURE_NAME_LEN 20 +struct ppp_feature_cmd { + const char feature_name[HIKP_PPP_MAX_FEATURE_NAME_LEN]; + uint32_t sub_cmd_code; + bool need_query_hw_res; + int (*query)(struct hikp_cmd_header *req_header, + const struct bdf_t *bdf, void *data, size_t len); + void (*show)(const void *data); +}; + +#endif /* HIKP_NIC_PPP_H */ diff --git a/net/nic/nic_qos/hikp_nic_qos.c b/net/nic/nic_qos/hikp_nic_qos.c new file mode 100644 index 0000000..2d55e45 --- /dev/null +++ b/net/nic/nic_qos/hikp_nic_qos.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_qos.h" + +static struct nic_qos_param g_qos_param = { 0 }; + +static void hikp_nic_qos_show_pkt_buf(const void *data); +static void hikp_nic_qos_show_dcb_info(const void *data); +static void hikp_nic_qos_show_pause_info(const void *data); + +static const struct qos_feature_cmd g_qos_feature_cmd[] = { + {"pkt_buf", NIC_PACKET_BUFFER_DUMP, hikp_nic_qos_show_pkt_buf}, + {"dcb", NIC_DCB_DUMP, hikp_nic_qos_show_dcb_info}, + {"pause", NIC_PAUSE_DUMP, hikp_nic_qos_show_pause_info}, +}; + +static int hikp_nic_qos_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + printf(" %s\n", + "[-g/--get ]\n" + " pkt_buf : get nic packet buffer.\n" + " dcb : get dcb information.\n" + " pause : get pause information\n"); + + return 0; +} + +static void hikp_nic_qos_show_pkt_buf(const void *data) +{ + struct nic_pkt_buf_info *pkt_buf = (struct nic_pkt_buf_info *)data; + struct nic_shared_buf *share_buf = &pkt_buf->share_buf; + struct nic_priv_buf *priv_buf = pkt_buf->priv_buf; + uint16_t tc_no; + + printf("Rx Shared packet buffer configuration\n"); + printf(" > buffer size: 0x%x\n", share_buf->buf_size); + printf(" > common waterline high: 0x%x low: 0x%x\n", + share_buf->comm_wl.high, share_buf->comm_wl.low); + printf(" > common threshold: 0x%x low: 0x%x\n", + share_buf->comm_wl.high, share_buf->comm_wl.low); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) { + printf(" - tc%u high: 0x%x low: 0x%x\n", tc_no, share_buf->tc_thrd[tc_no].high, + share_buf->tc_thrd[tc_no].low); + } + + printf("\nRx Privated buffer waterline\n"); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) + printf(" > tc%u high: 0x%x low: 0x%x\n", tc_no, priv_buf[tc_no].wl.high, + priv_buf[tc_no].wl.low); + + printf("\nRx Privated packet buffer configuration\n"); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) + printf(" > tc%u Rx buffer size: 0x%x\n", tc_no, priv_buf[tc_no].rx_buf_size); + + printf("\nTx Privated packet buffer configuration\n"); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) + printf(" > tc%u Tx buffer size: 0x%x\n", tc_no, priv_buf[tc_no].tx_buf_size); +} + +static void hikp_nic_qos_show_dcb_info(const void *data) +{ + struct nic_dcb_info *dcb = (struct nic_dcb_info *)data; + struct nic_pfc_info *pfc = &dcb->pfc; + struct nic_ets_info *ets = &dcb->ets; + uint16_t up; + uint16_t tc_no; + + printf("PFC configuration\n"); + printf(" PFC enable:"); + for (up = 0; up < HIKP_NIC_MAX_USER_PRIO_NUM; up++) + printf(" %d", HI_BIT(up) & pfc->pfc_en ? 1 : 0); + + printf("\n"); + printf(" TC enable:"); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) + printf(" %d", HI_BIT(tc_no) & pfc->hw_tc_map ? 1 : 0); + + printf("\n"); + printf("ETS configuration\n"); + printf(" max_tc_cap: %u\n", ets->max_tc); + printf(" up2tc:"); + for (up = 0; up < HIKP_NIC_MAX_USER_PRIO_NUM; up++) + printf(" %u:%u", up, ets->prio_tc[up]); + + printf("\n"); + printf(" tc_bw:"); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) + printf(" %u:%u%%", tc_no, ets->tc_bw[tc_no]); + + printf("\n"); + printf(" tsa_map:"); + for (tc_no = 0; tc_no < HIKP_NIC_MAX_TC_NUM; tc_no++) + printf(" %u:%s", tc_no, ets->sch_mode[tc_no] == 0 ? "strict" : "ets"); + printf("\n"); +} + +static void hikp_nic_qos_show_pause_info(const void *data) +{ + struct nic_pause_info *pause = (struct nic_pause_info *)data; + + printf("PAUSE Information\n"); + if (pause->type == HIKP_NONE_PAUSE) + printf("pause type: none\n"); + else if (pause->type == HIKP_MAC_PAUSE) + printf("pause type: MAC pause\n"); + else if (pause->type == HIKP_PFC) + printf("pause type: PFC\n"); + printf(" pause_rx: %s\n", pause->pause_rx ? "On" : "Off"); + printf(" pause_tx: %s\n", pause->pause_tx ? "On" : "Off"); + + printf("pause time: 0x%x\n", pause->pause_time); + printf("pause gap: 0x%x\n", pause->pause_gap); +} + +static int hikp_nic_qos_get_blk(struct hikp_cmd_header *req_header, + const struct nic_qos_req_para *req_data, + void *buf, size_t buf_len, struct nic_qos_rsp_head *rsp_head) +{ + struct hikp_cmd_ret *cmd_ret; + struct nic_qos_rsp *rsp; + int ret = 0; + + cmd_ret = hikp_cmd_alloc(req_header, req_data, sizeof(*req_data)); + if (cmd_ret == NULL) { + HIKP_ERROR_PRINT("failed to get block-%u context.\n", req_data->block_id); + return -EIO; + } + + rsp = (struct nic_qos_rsp *)cmd_ret->rsp_data; + if (rsp->rsp_head.cur_blk_size > buf_len) { + HIKP_ERROR_PRINT("nic_qos block-%u copy size error, " + "buffer size=%u, data size=%u.\n", + req_data->block_id, buf_len, rsp->rsp_head.cur_blk_size); + ret = -EINVAL; + goto out; + } + memcpy(buf, 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: + free(cmd_ret); + return ret; +} + +static int hikp_nic_query_qos_feature(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + union nic_qos_feature_info *data) +{ + struct nic_qos_rsp_head rsp_head = {0}; + struct nic_qos_req_para req_data; + size_t buf_len = sizeof(*data); + uint32_t total_blk_size; + uint8_t total_blk_num; + uint8_t blk_num = 0; + uint8_t blk_id = 0; + int ret; + + req_data.bdf = *bdf; + + req_data.block_id = blk_id; + ret = hikp_nic_qos_get_blk(req_header, &req_data, data, buf_len, &rsp_head); + if (ret != 0) + return ret; + + total_blk_num = rsp_head.total_blk_num; + total_blk_size = rsp_head.cur_blk_size; + + /* Copy the remaining block content if total block number is greater than 1. */ + for (blk_id = 1; blk_id < total_blk_num; blk_id++) { + req_data.block_id = blk_id; + ret = hikp_nic_qos_get_blk(req_header, &req_data, + (uint8_t *)data + total_blk_size, + buf_len - total_blk_size, &rsp_head); + if (ret != 0) + return ret; + total_blk_size += rsp_head.cur_blk_size; + } + + return ret; +} + +static void hikp_nic_qos_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_qos_param.target.bdf; + union nic_qos_feature_info qos_data = {0}; + const struct qos_feature_cmd *qos_cmd; + struct hikp_cmd_header req_header = {0}; + int ret; + + if (bdf->dev_id != 0) { + snprintf(self->err_str, sizeof(self->err_str), "VF does not support query!"); + self->err_no = -EINVAL; + return; + } + + if (g_qos_param.feature_idx == -1) { + hikp_nic_qos_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-g/--get param error!"); + self->err_no = -EINVAL; + return; + } + + qos_cmd = &g_qos_feature_cmd[g_qos_param.feature_idx]; + hikp_cmd_init(&req_header, NIC_MOD, GET_QOS_INFO_CMD, qos_cmd->sub_cmd_code); + ret = hikp_nic_query_qos_feature(&req_header, &g_qos_param.target.bdf, &qos_data); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "failed to query %s, ret = %d.", + qos_cmd->feature_name, ret); + self->err_no = ret; + return; + } + + printf("############## NIC QOS: %s info ############\n", qos_cmd->feature_name); + qos_cmd->show(&qos_data); + printf("#################### END #######################\n"); +} + +static int hikp_nic_cmd_get_qos_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_qos_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_cmd_qos_feature_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t feat_size = HIKP_ARRAY_SIZE(g_qos_feature_cmd); + size_t i; + + for (i = 0; i < feat_size; i++) { + if (strcmp(argv, g_qos_feature_cmd[i].feature_name) == 0) { + g_qos_param.feature_idx = i; + return 0; + } + } + + hikp_nic_qos_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 void cmd_nic_get_qos_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_qos_param.feature_idx = -1; + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_qos_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_qos_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_get_qos_target); + cmd_option_register("-g", "--get", true, hikp_nic_cmd_qos_feature_select); +} + +HIKP_CMD_DECLARE("nic_qos", "show qos info of nic!", cmd_nic_get_qos_init); diff --git a/net/nic/nic_qos/hikp_nic_qos.h b/net/nic/nic_qos/hikp_nic_qos.h new file mode 100644 index 0000000..b5481f5 --- /dev/null +++ b/net/nic/nic_qos/hikp_nic_qos.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2022 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_NIC_QOS_H +#define HIKP_NIC_QOS_H + +#include "hikp_net_lib.h" + +enum nic_qos_sub_cmd_type { + NIC_PACKET_BUFFER_DUMP = 0, + NIC_DCB_DUMP, + NIC_PAUSE_DUMP, +}; + +struct nic_buf_waterline { + uint32_t low; + uint32_t high; +}; + +struct nic_shared_buf { + struct nic_buf_waterline tc_thrd[HIKP_NIC_MAX_TC_NUM]; + struct nic_buf_waterline comm_wl; + uint32_t buf_size; /* share packet buffer size. */ +}; + +struct nic_priv_buf { + struct nic_buf_waterline wl; /* high and low waterline for the TC Rx private buffer. */ + uint32_t rx_buf_size; /* TC Rx private buffer size. */ + uint32_t tx_buf_size; /* TC Tx private buffer size. */ +}; + +struct nic_pkt_buf_info { + struct nic_priv_buf priv_buf[HIKP_NIC_MAX_TC_NUM]; + struct nic_shared_buf share_buf; +}; + +struct nic_pfc_info { + uint8_t hw_tc_map; /* enabled TC map in hardware */ + uint8_t pfc_en; /* enable pfc bitmap for UP */ + uint8_t rsv[2]; +}; + +struct nic_ets_info { + uint8_t prio_tc[HIKP_NIC_MAX_USER_PRIO_NUM]; + uint8_t tc_bw[HIKP_NIC_MAX_TC_NUM]; + uint8_t sch_mode[HIKP_NIC_MAX_TC_NUM]; /* 0: sp 1: dwrr */ + uint8_t max_tc; /* supported max TC number */ + uint8_t rsv[3]; +}; + +struct nic_dcb_info { + struct nic_pfc_info pfc; + struct nic_ets_info ets; +}; + +enum hikp_pause_type { + HIKP_NONE_PAUSE = 0x0, + HIKP_MAC_PAUSE, + HIKP_PFC, +}; + +struct nic_pause_info { + uint8_t type; + uint8_t pause_rx; /* 1: enable 0: disable */ + uint8_t pause_tx; /* 1: enable 0: disable */ + uint8_t pause_gap; + uint16_t pause_time; + uint16_t rsv; +}; + +union nic_qos_feature_info { + struct nic_pkt_buf_info pkt_buf; + struct nic_dcb_info dcb; + struct nic_pause_info pause; +}; + +struct nic_qos_rsp_head { + uint8_t total_blk_num; + uint8_t cur_blk_size; /* real data size, not contain head size. */ + uint16_t rsv; +}; + +#define NIC_QOS_MAX_RSP_DATA 59 +struct nic_qos_rsp { + struct nic_qos_rsp_head rsp_head; /* 4 Byte */ + uint32_t rsp_data[NIC_QOS_MAX_RSP_DATA]; +}; + +struct nic_qos_req_para { + struct bdf_t bdf; + uint8_t block_id; +}; + +struct nic_qos_param { + struct tool_target target; + int feature_idx; +}; + +#define HIKP_QOS_MAX_FEATURE_NAME_LEN 20 +struct qos_feature_cmd { + const char feature_name[HIKP_QOS_MAX_FEATURE_NAME_LEN]; + uint32_t sub_cmd_code; + void (*show)(const void *data); +}; + +#endif /* HIKP_NIC_QOS_H */ diff --git a/net/nic/nic_queue/hikp_nic_queue.c b/net/nic/nic_queue/hikp_nic_queue.c new file mode 100644 index 0000000..37460c0 --- /dev/null +++ b/net/nic/nic_queue/hikp_nic_queue.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_queue.h" + +static struct nic_queue_param g_queue_param = { 0 }; + +static void hikp_nic_queue_show_basic_info(const void *data); +static void hikp_nic_queue_show_enable_info(const void *data); +static void hikp_nic_queue_show_intr_map(const void *data); +static void hikp_nic_queue_show_func_map(const void *data); + +static const struct queue_feature_cmd g_queue_feature_cmd[] = { + {"basic_info", QUEUE_BASIC_INFO, hikp_nic_queue_show_basic_info}, + {"queue_en", QUEUE_EN_INFO, hikp_nic_queue_show_enable_info}, + {"intr_map", QUEUE_INTR_MAP, hikp_nic_queue_show_intr_map}, + {"func_map", QUEUE_FUNC_MAP, hikp_nic_queue_show_func_map}, +}; + +static int hikp_nic_queue_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + printf("%s\n", + " [-du/--dump basic_info -d/--dir -q/--qid ]\n" + " dump a Rx/Tx queue basic info.\n" + " [-du/--dump queue_en -a/--all ]\n" + " dump Rx & Tx queue enable info\n" + " [-du/--dump intr_map -d/--dir -a/--all ]\n" + " dump all Rx/Tx queue intr map.\n" + " [-du/--dump func_map]\n" + " display the queue mapping between the function and " + "the global queue on the port.\n"); + printf("%s\n", + " Note: '-a/--all' means if display all queues including disabled or unused, " + "defaultly only display\n enabled and used queues.\n"); + + return 0; +} + +#define HIKP_NIC_GET_DESC_NUM(num) (((num) + 1) * 8) + +#define HIKP_NIC_BD_SIZE_512_TYPE 0 +#define HIKP_NIC_BD_SIZE_1024_TYPE 1 +#define HIKP_NIC_BD_SIZE_2048_TYPE 2 +#define HIKP_NIC_BD_SIZE_4096_TYPE 3 + +#define HIKP_NIC_BUF_LEN_512B 512 +#define HIKP_NIC_BUF_LEN_1024B 1024 +#define HIKP_NIC_BUF_LEN_2048B 2048 +#define HIKP_NIC_BUF_LEN_4096B 4096 +static uint32_t hikp_nic_buf_type_to_buf_len(uint32_t type) +{ + uint32_t rx_buf_len; + + switch (type) { + case HIKP_NIC_BD_SIZE_512_TYPE: + rx_buf_len = HIKP_NIC_BUF_LEN_512B; + break; + case HIKP_NIC_BD_SIZE_1024_TYPE: + rx_buf_len = HIKP_NIC_BUF_LEN_1024B; + break; + case HIKP_NIC_BD_SIZE_2048_TYPE: + rx_buf_len = HIKP_NIC_BUF_LEN_2048B; + break; + case HIKP_NIC_BD_SIZE_4096_TYPE: + rx_buf_len = HIKP_NIC_BUF_LEN_4096B; + break; + default: + rx_buf_len = 0; + break; + } + + return rx_buf_len; +} + +static void hikp_nic_queue_show_basic_info(const void *data) +{ + union nic_queue_info *q_info = (union nic_queue_info *)data; + struct rx_queue_info *rxq; + struct tx_queue_info *txq; + + printf("%s queue id-%d basic info:\n", + g_queue_param.dir == NIC_RX_QUEUE ? "Rx" : "Tx", g_queue_param.qid); + if (g_queue_param.dir == NIC_RX_QUEUE) { + rxq = &q_info->rxq; + printf(" nb_desc = %u\n", HIKP_NIC_GET_DESC_NUM(rxq->rx_nb_desc)); + printf(" tail = %u\n", rxq->rx_tail); + printf(" head = %u\n", rxq->rx_head); + printf(" fbd_num = %u\n", rxq->rx_fbd_num); + printf(" ring_offset = %u\n", rxq->rx_ring_offset); + printf(" fbd_offset = %u\n", rxq->rx_fbd_offset); + printf(" rx_buf_len = %u\n", hikp_nic_buf_type_to_buf_len(rxq->rx_buf_len)); + printf(" ring_tcid = %u\n", rxq->rx_ring_tcid); + printf(" merge_en = %s\n", rxq->rx_merge_en ? "enable" : "disable"); + printf(" bd_err = %u\n", rxq->rx_bd_err); + printf(" rx_stash_lpid = 0x%x\n", rxq->rx_stash_lpid); + return; + } + + txq = &q_info->txq; + printf(" nb_desc = %u\n", HIKP_NIC_GET_DESC_NUM(txq->tx_nb_desc)); + printf(" tail = %u\n", txq->tx_tail); + printf(" head = %u\n", txq->tx_head); + printf(" fbd_num = %u\n", txq->tx_fbd_num); + printf(" ring_offset = %u\n", txq->tx_ring_offset); + printf(" ebd_num = %u\n", txq->tx_ebd_num); + printf(" ebd_offset = %u\n", txq->tx_ring_ebd_offset); + printf(" tx_ring_pri = %u\n", txq->tx_ring_pri); + printf(" tx_ring_tc = %u\n", txq->tx_ring_tc); + printf(" merge_en = %s\n", txq->tx_merge_en ? "enable" : "disable"); + printf(" bd_err = %u\n", txq->tx_ring_bd_err); + printf(" ring_fbd_prf_num = 0x%x\n", txq->tx_ring_fbd_prf_num); +} + +static void hikp_nic_queue_show_enable_info(const void *data) +{ + struct nic_queue_en_cfg_info *q_en_info = (struct nic_queue_en_cfg_info *)data; + struct nic_queue_en_cfg *q_en_cfg; + uint16_t qid; + bool rx_en; + bool tx_en; + + printf("Rx & Tx Queue enable info[tqp_num=%u display_all=%s]:\n", q_en_info->tqp_num, + g_queue_param.is_display_all ? "On" : "Off"); + for (qid = 0; qid < q_en_info->tqp_num; qid++) { + if (qid >= HIKP_NIC_MAX_QUEUE_NUM) { + HIKP_ERROR_PRINT("The cmd data is truncated.\n"); + break; + } + q_en_cfg = &q_en_info->q_en_cfg[qid]; + rx_en = q_en_cfg->rcb_en && q_en_cfg->rcb_rx_en; + tx_en = q_en_cfg->rcb_en && q_en_cfg->rcb_tx_en; + if (rx_en || tx_en || g_queue_param.is_display_all) { + printf(" qid-%u: tqp_en:%u rcb_rx_en:%u rcb_tx_en:%u Rx:%s Tx:%s\n", + qid, q_en_cfg->rcb_en, q_en_cfg->rcb_rx_en, q_en_cfg->rcb_tx_en, + rx_en ? "enable" : "disable", tx_en ? "enable" : "disable"); + } + } +} + +static void hikp_nic_queue_show_intr_map(const void *data) +{ + struct nic_queue_intr_map *map = (struct nic_queue_intr_map *)data; + struct rcb_intr_ctl_cfg *rcb_intr; + struct queue_intr_cfg *intr_cfg; + bool intr_en; + uint16_t qid; + + printf("%s queue intr mapping info[tqp_num=%u display_all=%s]:\n", + g_queue_param.dir == NIC_RX_QUEUE ? "Rx" : "Tx", + map->tqp_num, g_queue_param.is_display_all ? "On" : "Off"); + for (qid = 0; qid < map->tqp_num; qid++) { + if (qid >= HIKP_NIC_MAX_QUEUE_NUM) { + HIKP_ERROR_PRINT("The cmd data is truncated.\n"); + break; + } + intr_cfg = &map->intr_cfg[qid]; + rcb_intr = &intr_cfg->rcb_intr; + intr_en = intr_cfg->tqp_intr_en && rcb_intr->intr_dis == 0; + if (intr_en || g_queue_param.is_display_all) { + printf(" qid-%u: vec_id=%u gl_cfg=%u intr_dis:%s " + "intr_coal:%s que_intr:%s\n", qid, rcb_intr->intr_vector_id, + rcb_intr->int_gl_idx, rcb_intr->intr_dis ? "disable" : "enable", + intr_cfg->tqp_intr_en ? "enable" : "disable", + intr_en ? "enable" : "disable"); + } + } +} + +static void hikp_nic_queue_show_func_map(const void *data) +{ + struct nic_queue_func_map *q_func_map = (struct nic_queue_func_map *)data; + struct tqp_func_map *map; + uint16_t qid; + + printf("TQP function mapping info:\n"); + printf(" local_qid | global_qid\n"); + for (qid = 0; qid < q_func_map->tqp_num; qid++) { + if (qid >= HIKP_NIC_MAX_QUEUE_NUM) { + HIKP_ERROR_PRINT("The cmd data is truncated.\n"); + break; + } + + map = &q_func_map->map[qid]; + printf(" %4u | %4u\n", map->q_id, map->abs_q_id); + } +} + +static void hikp_nic_queue_req_para_init(struct nic_queue_req_para *req_data, + const struct bdf_t *bdf, + const struct nic_queue_param *queue_param) +{ + const struct queue_feature_cmd *queue_cmd = &g_queue_feature_cmd[queue_param->feature_idx]; + + req_data->bdf = *bdf; + + switch (queue_cmd->sub_cmd_code) { + case QUEUE_BASIC_INFO: + req_data->is_rx = queue_param->dir == NIC_RX_QUEUE ? 1 : 0; + req_data->q_id = (uint16_t)queue_param->qid; + break; + case QUEUE_EN_INFO: + break; + case QUEUE_INTR_MAP: + req_data->is_rx = queue_param->dir == NIC_RX_QUEUE ? 1 : 0; + break; + case QUEUE_FUNC_MAP: + default: + break; + } +} + +static int hikp_nic_queue_get_blk(struct hikp_cmd_header *req_header, + const struct nic_queue_req_para *req_data, + void *buf, size_t buf_len, struct nic_queue_rsp_head *rsp_head) +{ + struct hikp_cmd_ret *cmd_ret; + struct nic_queue_rsp *rsp; + int ret = 0; + + cmd_ret = hikp_cmd_alloc(req_header, req_data, sizeof(*req_data)); + if (cmd_ret == NULL) { + HIKP_ERROR_PRINT("failed to get block-%u context.\n", req_data->block_id); + return -EIO; + } + + rsp = (struct nic_queue_rsp *)cmd_ret->rsp_data; + if (rsp->rsp_head.cur_blk_size > buf_len) { + HIKP_ERROR_PRINT("nic_queue block-%u copy size error, " + "buffer size=%u, data size=%u.\n", + req_data->block_id, buf_len, rsp->rsp_head.cur_blk_size); + ret = -EINVAL; + goto out; + } + memcpy(buf, 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: + free(cmd_ret); + return ret; +} + +static int hikp_nic_query_queue_feature(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + union nic_queue_feature_info *data) +{ + struct nic_queue_rsp_head rsp_head = {0}; + struct nic_queue_req_para req_data; + size_t buf_len = sizeof(*data); + uint32_t total_blk_size; + uint8_t total_blk_num; + uint8_t blk_id = 0; + int ret; + + hikp_nic_queue_req_para_init(&req_data, bdf, &g_queue_param); + + req_data.block_id = blk_id; + ret = hikp_nic_queue_get_blk(req_header, &req_data, data, buf_len, &rsp_head); + if (ret != 0) + return ret; + + total_blk_num = rsp_head.total_blk_num; + total_blk_size = rsp_head.cur_blk_size; + + /* Copy the remaining block content if total block number is greater than 1. */ + for (blk_id = 1; blk_id < total_blk_num; blk_id++) { + req_data.block_id = blk_id; + ret = hikp_nic_queue_get_blk(req_header, &req_data, + (uint8_t *)data + total_blk_size, + buf_len - total_blk_size, &rsp_head); + if (ret != 0) + return ret; + total_blk_size += rsp_head.cur_blk_size; + } + + return ret; +} + +static bool hikp_nic_queue_check_feature_para_vaild(const struct queue_feature_cmd *cmd) +{ + bool valid = true; + + switch (cmd->sub_cmd_code) { + case QUEUE_BASIC_INFO: + if (g_queue_param.qid == -1 || + g_queue_param.dir == NIC_QUEUE_DIR_UNKNOWN) { + HIKP_ERROR_PRINT("please select rx or tx and qid " + "by '-d/--dir' and '-q/--qid'.\n"); + valid = false; + } + break; + case QUEUE_EN_INFO: + case QUEUE_FUNC_MAP: + if (g_queue_param.qid != -1 || + g_queue_param.dir != NIC_QUEUE_DIR_UNKNOWN) { + HIKP_ERROR_PRINT("%s sub cmd no need '-q/--qid' and '-d/--dir'.\n", + cmd->feature_name); + valid = false; + } + break; + case QUEUE_INTR_MAP: + if (g_queue_param.dir == NIC_QUEUE_DIR_UNKNOWN) { + HIKP_ERROR_PRINT("please select rx or tx by '-d/--dir'.\n"); + valid = false; + } + if (g_queue_param.qid != -1) { + HIKP_ERROR_PRINT("%s sub cmd no need -q/--qid.\n", cmd->feature_name); + valid = false; + } + break; + default: + HIKP_ERROR_PRINT("unknown feature parameter.\n"); + valid = false; + break; + } + + return valid; +} + +static void hikp_nic_queue_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_queue_param.target.bdf; + const struct queue_feature_cmd *queue_cmd; + union nic_queue_feature_info *queue_data; + struct hikp_cmd_header req_header = {0}; + int ret; + + if (g_queue_param.feature_idx == -1) { + hikp_nic_queue_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-du/--dump param error!"); + self->err_no = -EINVAL; + return; + } + + queue_cmd = &g_queue_feature_cmd[g_queue_param.feature_idx]; + if (!hikp_nic_queue_check_feature_para_vaild(queue_cmd)) { + hikp_nic_queue_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "option parameters error!"); + self->err_no = -EINVAL; + return; + } + + queue_data = (union nic_queue_feature_info *)calloc(1, + sizeof(union nic_queue_feature_info)); + if (queue_data == NULL) { + snprintf(self->err_str, sizeof(self->err_str), + "failed to allocate queue_data memory!"); + self->err_no = -ENOMEM; + return; + } + hikp_cmd_init(&req_header, NIC_MOD, GET_QUEUE_INFO_CMD, queue_cmd->sub_cmd_code); + ret = hikp_nic_query_queue_feature(&req_header, &g_queue_param.target.bdf, queue_data); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "failed to query %s, ret = %d.", + queue_cmd->feature_name, ret); + self->err_no = ret; + goto out; + } + + printf("############## NIC Queue: %s info ############\n", queue_cmd->feature_name); + queue_cmd->show(queue_data); + printf("#################### END #######################\n"); + +out: + free(queue_data); +} + +static int hikp_nic_cmd_get_queue_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_queue_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_cmd_queue_select_dir(struct major_cmd_ctrl *self, const char *argv) +{ + if (strcmp(argv, "rx") == 0) { + g_queue_param.dir = NIC_RX_QUEUE; + return 0; + } else if (strcmp(argv, "tx") == 0) { + g_queue_param.dir = NIC_TX_QUEUE; + return 0; + } + + snprintf(self->err_str, sizeof(self->err_str), "--d/--dir option is incorrect."); + self->err_no = -EINVAL; + + return self->err_no; +} + +static int hikp_nic_cmd_queue_get_qid(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t qid; + + self->err_no = string_toui(argv, &qid); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "parse qid failed."); + return self->err_no; + } + + if (qid >= HIKP_NIC_MAX_QUEUE_NUM) { + snprintf(self->err_str, sizeof(self->err_str), "the qid should be less than %u.", + HIKP_NIC_MAX_QUEUE_NUM); + self->err_no = -EINVAL; + return self->err_no; + } + + g_queue_param.qid = (uint16_t)qid; + + return 0; +} + +static int hikp_nic_cmd_queue_get_all_switch(struct major_cmd_ctrl *self, const char *argv) +{ + if (strcmp(argv, "on") == 0) { + g_queue_param.is_display_all = true; + return 0; + } else if (strcmp(argv, "off") == 0) { + g_queue_param.is_display_all = false; + return 0; + } + + snprintf(self->err_str, sizeof(self->err_str), "parse -a/--all option failed."); + self->err_no = -EINVAL; + + return self->err_no; +} + +static int hikp_nic_cmd_queue_feature_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t feat_size = HIKP_ARRAY_SIZE(g_queue_feature_cmd); + size_t i; + + for (i = 0; i < feat_size; i++) { + if (strcmp(argv, g_queue_feature_cmd[i].feature_name) == 0) { + g_queue_param.feature_idx = i; + return 0; + } + } + + hikp_nic_queue_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), + "please specify the subfunction to be queried."); + self->err_no = -EINVAL; + + return self->err_no; +} + +static void cmd_nic_get_queue_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_queue_param.feature_idx = -1; + g_queue_param.qid = -1; + g_queue_param.dir = NIC_QUEUE_DIR_UNKNOWN; + g_queue_param.is_display_all = false; + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_queue_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_queue_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_get_queue_target); + cmd_option_register("-du", "--dump", true, hikp_nic_cmd_queue_feature_select); + cmd_option_register("-d", "--dir", true, hikp_nic_cmd_queue_select_dir); + cmd_option_register("-q", "--qid", true, hikp_nic_cmd_queue_get_qid); + cmd_option_register("-a", "--all", true, hikp_nic_cmd_queue_get_all_switch); +} + +HIKP_CMD_DECLARE("nic_queue", "dump queue info of nic!", cmd_nic_get_queue_init); diff --git a/net/nic/nic_queue/hikp_nic_queue.h b/net/nic/nic_queue/hikp_nic_queue.h new file mode 100644 index 0000000..fac39a0 --- /dev/null +++ b/net/nic/nic_queue/hikp_nic_queue.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2022 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_NIC_QUEUE_H +#define HIKP_NIC_QUEUE_H + +#include "hikp_net_lib.h" + +enum nic_queue_sub_cmd_type { + QUEUE_BASIC_INFO = 0, + QUEUE_EN_INFO, + QUEUE_INTR_MAP, + QUEUE_FUNC_MAP, +}; + +enum nic_queue_dir { + NIC_TX_QUEUE = 0, + NIC_RX_QUEUE, + NIC_QUEUE_DIR_UNKNOWN, +}; + +#define HIKP_NIC_MAX_QUEUE_NUM 2048 + +struct rx_queue_info { + uint32_t rx_nb_desc; + uint32_t rx_buf_len; + uint32_t rx_ring_tcid; + uint32_t rx_merge_en; + uint32_t rx_tail; + uint32_t rx_head; + uint32_t rx_fbd_num; + uint32_t rx_ring_offset; + uint32_t rx_fbd_offset; + uint32_t rx_bd_err; + uint32_t rx_stash_lpid; +}; + +struct tx_queue_info { + uint32_t tx_nb_desc; + uint32_t tx_ring_pri; /* 0-low prioritym, 1-high priority */ + uint32_t tx_ring_tc; + uint32_t tx_merge_en; + uint32_t tx_tail; + uint32_t tx_head; + uint32_t tx_fbd_num; + uint32_t tx_ring_offset; + uint32_t tx_ebd_num; + uint32_t tx_ring_ebd_offset; + uint32_t tx_ring_bd_err; + uint32_t tx_ring_fbd_prf_num; +}; + +union nic_queue_info { + struct rx_queue_info rxq; + struct tx_queue_info txq; +}; + +struct nic_queue_en_cfg { + uint8_t rcb_en; /* common switch, 0-disable, 1-enable */ + uint8_t rcb_rx_en; /* 0-disable, 1-enable */ + uint8_t rcb_tx_en; /* 0-disable, 1-enable */ + uint8_t rsv; +}; + +struct nic_queue_en_cfg_info { + uint16_t tqp_num; /* max queue number in the function */ + uint16_t rsv; + struct nic_queue_en_cfg q_en_cfg[HIKP_NIC_MAX_QUEUE_NUM]; +}; + +struct rcb_intr_ctl_cfg { + uint8_t intr_dis; /* 1-disable, 0-enable */ + uint8_t int_gl_idx; + uint16_t intr_vector_id; +}; + +struct queue_intr_cfg { + uint8_t tqp_intr_en; /* intr enable in func common. */ + uint8_t rsv[3]; + struct rcb_intr_ctl_cfg rcb_intr; +}; + +/* Rx/Tx queue intr map */ +struct nic_queue_intr_map { + uint16_t tqp_num; + uint16_t rsv; + struct queue_intr_cfg intr_cfg[HIKP_NIC_MAX_QUEUE_NUM]; +}; + +struct tqp_func_map { + uint16_t q_id; /* relative queue id in the func */ + uint16_t abs_q_id; /* absolute queue id relative to PF */ +}; + +struct nic_queue_func_map { + uint16_t tqp_num; + uint16_t rsv; + struct tqp_func_map map[HIKP_NIC_MAX_QUEUE_NUM]; +}; + +union nic_queue_feature_info { + union nic_queue_info q_info; /* one Rx/Tx queue info */ + struct nic_queue_en_cfg_info q_en_info; + struct nic_queue_intr_map q_intr_map; + struct nic_queue_func_map q_func_map; +}; + +struct nic_queue_rsp_head { + uint8_t total_blk_num; + uint8_t cur_blk_size; /* real data size, not contain head size. */ + uint16_t rsv; +}; + +#define NIC_QUEUE_MAX_RSP_DATA 59 +struct nic_queue_rsp { + struct nic_queue_rsp_head rsp_head; /* 4 Byte */ + uint32_t rsp_data[NIC_QUEUE_MAX_RSP_DATA]; +}; + +struct nic_queue_req_para { + struct bdf_t bdf; + uint8_t block_id; + uint8_t is_rx; /* 1: Rx queue, 0: Tx queue */ + uint16_t q_id; +}; + +struct nic_queue_param { + struct tool_target target; + int feature_idx; + enum nic_queue_dir dir; + int qid; + + /* Control if display all queues including disabled or unused, defaulty + * only display enabled and used queues. + */ + bool is_display_all; +}; + +#define HIKP_QUEUE_FEATURE_MAX_NAME_LEN 20 +struct queue_feature_cmd { + const char feature_name[HIKP_QUEUE_FEATURE_MAX_NAME_LEN]; + uint32_t sub_cmd_code; + void (*show)(const void *data); +}; +#endif /* HIKP_NIC_QUEUE_H */ diff --git a/net/nic/nic_rss/hikp_nic_rss.c b/net/nic/nic_rss/hikp_nic_rss.c new file mode 100644 index 0000000..b785ba4 --- /dev/null +++ b/net/nic/nic_rss/hikp_nic_rss.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2022 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 "hikp_nic_rss.h" + +static struct nic_rss_param g_rss_param = { 0 }; + +/* ipv4-tcp */ +#define HIKP_RSS_NONFRAG_IPV4_TCP_EN_TCP_D HI_BIT(0) +#define HIKP_RSS_NONFRAG_IPV4_TCP_EN_TCP_S HI_BIT(1) +#define HIKP_RSS_NONFRAG_IPV4_TCP_EN_IP_D HI_BIT(2) +#define HIKP_RSS_NONFRAG_IPV4_TCP_EN_IP_S HI_BIT(3) + +/* ipv4-udp */ +#define HIKP_RSS_NONFRAG_IPV4_UDP_EN_UDP_D HI_BIT(4) +#define HIKP_RSS_NONFRAG_IPV4_UDP_EN_UDP_S HI_BIT(5) +#define HIKP_RSS_NONFRAG_IPV4_UDP_EN_IP_D HI_BIT(6) +#define HIKP_RSS_NONFRAG_IPV4_UDP_EN_IP_S HI_BIT(7) + +/* ipv4-sctp */ +#define HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_D HI_BIT(8) +#define HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_S HI_BIT(9) +#define HIKP_RSS_NONFRAG_IPV4_SCTP_EN_IP_D HI_BIT(10) +#define HIKP_RSS_NONFRAG_IPV4_SCTP_EN_IP_S HI_BIT(11) +#define HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_VTAG HI_BIT(12) + +/* ipv4-other */ +#define HIKP_RSS_NONFRAG_IPV4_OTHER_EN_IP_D HI_BIT(13) +#define HIKP_RSS_NONFRAG_IPV4_OTHER_EN_IP_S HI_BIT(14) + +/* ipv4-frag */ +#define HIKP_RSS_FRAG_IPV4_EN_IP_D HI_BIT(15) +#define HIKP_RSS_FRAG_IPV4_EN_IP_S HI_BIT(16) + +/* ipv6-tcp */ +#define HIKP_RSS_NONFRAG_IPV6_TCP_EN_TCP_D HI_BIT(0) +#define HIKP_RSS_NONFRAG_IPV6_TCP_EN_TCP_S HI_BIT(1) +#define HIKP_RSS_NONFRAG_IPV6_TCP_EN_IP_D HI_BIT(2) +#define HIKP_RSS_NONFRAG_IPV6_TCP_EN_IP_S HI_BIT(3) + +/* ipv6-udp */ +#define HIKP_RSS_NONFRAG_IPV6_UDP_EN_UDP_D HI_BIT(4) +#define HIKP_RSS_NONFRAG_IPV6_UDP_EN_UDP_S HI_BIT(5) +#define HIKP_RSS_NONFRAG_IPV6_UDP_EN_IP_D HI_BIT(6) +#define HIKP_RSS_NONFRAG_IPV6_UDP_EN_IP_S HI_BIT(7) + +/* ipv6-sctp */ +#define HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_D HI_BIT(8) +#define HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_S HI_BIT(9) +#define HIKP_RSS_NONFRAG_IPV6_SCTP_EN_IP_D HI_BIT(10) +#define HIKP_RSS_NONFRAG_IPV6_SCTP_EN_IP_S HI_BIT(11) +#define HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_VTAG HI_BIT(12) + +/* ipv6-other */ +#define HIKP_RSS_NONFRAG_IPV6_OTHER_EN_IP_D HI_BIT(13) +#define HIKP_RSS_NONFRAG_IPV6_OTHER_EN_IP_S HI_BIT(14) + +/* ipv6-frag */ +#define HIKP_RSS_FRAG_IPV6_EN_IP_D HI_BIT(15) +#define HIKP_RSS_FRAG_IPV6_EN_IP_S HI_BIT(16) + +#define HIKP_RSS_FRAG_IPV4_MASK \ + (HIKP_RSS_FRAG_IPV4_EN_IP_D | HIKP_RSS_FRAG_IPV4_EN_IP_S) +#define HIKP_RSS_NONFRAG_IPV4_OTHER_MASK \ + (HIKP_RSS_NONFRAG_IPV4_OTHER_EN_IP_D | HIKP_RSS_NONFRAG_IPV4_OTHER_EN_IP_S) +#define HIKP_RSS_NONFRAG_IPV4_TCP_MASK \ + (HIKP_RSS_NONFRAG_IPV4_TCP_EN_TCP_D | HIKP_RSS_NONFRAG_IPV4_TCP_EN_TCP_S | \ + HIKP_RSS_NONFRAG_IPV4_TCP_EN_IP_D | HIKP_RSS_NONFRAG_IPV4_TCP_EN_IP_S) +#define HIKP_RSS_NONFRAG_IPV4_UDP_MASK \ + (HIKP_RSS_NONFRAG_IPV4_UDP_EN_UDP_D | HIKP_RSS_NONFRAG_IPV4_UDP_EN_UDP_S | \ + HIKP_RSS_NONFRAG_IPV4_UDP_EN_IP_D | HIKP_RSS_NONFRAG_IPV4_UDP_EN_IP_S) +#define HIKP_RSS_NONFRAG_IPV4_SCTP_MASK \ + (HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_D | HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_S | \ + HIKP_RSS_NONFRAG_IPV4_SCTP_EN_IP_D | HIKP_RSS_NONFRAG_IPV4_SCTP_EN_IP_S | \ + HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_VTAG) + +#define HIKP_RSS_FRAG_IPV6_MASK \ + ((uint64_t)(HIKP_RSS_FRAG_IPV6_EN_IP_D | HIKP_RSS_FRAG_IPV6_EN_IP_S) << 32) +#define HIKP_RSS_NONFRAG_IPV6_OTHER_MASK \ + ((uint64_t)(HIKP_RSS_NONFRAG_IPV6_OTHER_EN_IP_D | \ + HIKP_RSS_NONFRAG_IPV6_OTHER_EN_IP_S) << 32) +#define HIKP_RSS_NONFRAG_IPV6_TCP_MASK \ + ((uint64_t)(HIKP_RSS_NONFRAG_IPV6_TCP_EN_TCP_D | HIKP_RSS_NONFRAG_IPV6_TCP_EN_TCP_S | \ + HIKP_RSS_NONFRAG_IPV6_TCP_EN_IP_D | HIKP_RSS_NONFRAG_IPV6_TCP_EN_IP_S) << 32) +#define HIKP_RSS_NONFRAG_IPV6_UDP_MASK \ + ((uint64_t)(HIKP_RSS_NONFRAG_IPV6_UDP_EN_UDP_D | HIKP_RSS_NONFRAG_IPV6_UDP_EN_UDP_S | \ + HIKP_RSS_NONFRAG_IPV6_UDP_EN_IP_D | HIKP_RSS_NONFRAG_IPV6_UDP_EN_IP_S) << 32) +#define HIKP_RSS_NONFRAG_IPV6_SCTP_MASK \ + ((uint64_t)(HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_D | HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_S | \ + HIKP_RSS_NONFRAG_IPV6_SCTP_EN_IP_D | HIKP_RSS_NONFRAG_IPV6_SCTP_EN_IP_S | \ + HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_VTAG) << 32) + +enum hikp_nic_rss_pkt_type { + IPV4_FRAG = 0, + IPV4_TCP, + IPV4_UDP, + IPV4_SCTP, + IPV4_OTHER, + IPV6_FRAG, + IPV6_TCP, + IPV6_UDP, + IPV6_SCTP, + IPV6_OTHER, +}; + +static void hikp_nic_rss_show_algo(const void *data); +static void hikp_nic_rss_show_hash_key(const void *data); +static void hikp_nic_rss_show_tuple(const void *data); +static void hikp_nic_rss_show_reta_table(const void *data); +static void hikp_nic_rss_show_tc_mode(const void *data); + +static const struct rss_feature_cmd g_rss_feature_cmd[] = { + {"algo", RSS_ALGO_DUMP, hikp_nic_rss_show_algo}, + {"key", RSS_KEY_DUMP, hikp_nic_rss_show_hash_key}, + {"tuple", RSS_TUPLE_DUMP, hikp_nic_rss_show_tuple}, + {"reta", RSS_RETA_DUMP, hikp_nic_rss_show_reta_table}, + {"tc_mode", RSS_TC_MODE_DUMP, hikp_nic_rss_show_tc_mode}, +}; + +static int hikp_nic_rss_cmd_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + printf(" %s\n", + "[-g/--get ]\n" + " algo : get hash algorithm.\n" + " key : get hash key.\n" + " tuple : get configuration of tuple\n" + " reta : get reta table.\n" + " tc_mode : get rss tc mode.\n"); + + return 0; +} + +static void hikp_nic_rss_show_algo(const void *data) +{ + uint8_t hash_algo = *(uint8_t *)data; + + switch (hash_algo) { + case HIKP_RSS_HASH_TOEPLITZ: + printf("RSS hash algo: Toeplitz.\n"); + break; + case HIKP_RSS_HASH_SIMPLE_XOR: + printf("RSS hash algo: Simple-XOR.\n"); + break; + case HIKP_RSS_HASH_SYMMETRIC_TOEPLITZ: + printf("RSS hash algo: Symmetric Toeplitz.\n"); + break; + default: + printf("hash_algo=0x%x\n", hash_algo); + break; + } +} + +static void hikp_nic_rss_show_hash_key(const void *data) +{ + struct rss_hash_key *rss_key = (struct rss_hash_key *)data; + uint16_t i; + + printf("key len: %u\n", rss_key->key_len); + printf("KEY: "); + for (i = 0; i < rss_key->key_len; i++) { + if (i >= HIKP_RSS_HASH_KEY_LEN_MAX) { + HIKP_ERROR_PRINT("The cmd data is truncated.\n"); + break; + } + printf("%02X", rss_key->key[i]); + } + printf("\n"); +} + +static void hikp_nic_rss_get_ipv4_tuples_name(enum hikp_nic_rss_pkt_type pkt_type, + uint64_t rss_type, char *tuples_name, uint8_t len) +{ + switch (pkt_type) { + case IPV4_FRAG: + snprintf(tuples_name, len, "%s %s", + (rss_type & HIKP_RSS_FRAG_IPV4_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_FRAG_IPV4_EN_IP_D) ? "IP_D" : ""); + break; + case IPV4_TCP: + snprintf(tuples_name, len, "%s %s %s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV4_TCP_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_TCP_EN_IP_D) ? "IP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_TCP_EN_TCP_S) ? "TCP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_TCP_EN_TCP_D) ? "TCP_D" : ""); + break; + case IPV4_UDP: + snprintf(tuples_name, len, "%s %s %s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV4_UDP_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_UDP_EN_IP_D) ? "IP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_UDP_EN_UDP_S) ? "UDP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_UDP_EN_UDP_D) ? "UDP_D" : ""); + break; + case IPV4_SCTP: + snprintf(tuples_name, len, "%s %s %s %s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV4_SCTP_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_SCTP_EN_IP_D) ? "IP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_S) ? "SCTP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_D) ? "SCTP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_SCTP_EN_SCTP_VTAG) ? "SCTP_VTAG" : ""); + break; + case IPV4_OTHER: + snprintf(tuples_name, len, "%s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV4_OTHER_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV4_OTHER_EN_IP_D) ? "IP_D" : ""); + break; + default: + break; + } +} + +static void hikp_nic_rss_get_ipv6_tuples_name(enum hikp_nic_rss_pkt_type pkt_type, + uint64_t rss_type, char *tuples_name, uint8_t len) +{ + switch (pkt_type) { + case IPV6_FRAG: + snprintf(tuples_name, len, "%s %s", + (rss_type & HIKP_RSS_FRAG_IPV6_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_FRAG_IPV6_EN_IP_D) ? "IP_D" : ""); + break; + case IPV6_TCP: + snprintf(tuples_name, len, "%s %s %s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV6_TCP_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_TCP_EN_IP_D) ? "IP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_TCP_EN_TCP_S) ? "TCP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_TCP_EN_TCP_D) ? "TCP_D" : ""); + break; + case IPV6_UDP: + snprintf(tuples_name, len, "%s %s %s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV6_UDP_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_UDP_EN_IP_D) ? "IP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_UDP_EN_UDP_S) ? "UDP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_UDP_EN_UDP_D) ? "UDP_D" : ""); + break; + case IPV6_SCTP: + snprintf(tuples_name, len, "%s %s %s %s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV6_SCTP_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_SCTP_EN_IP_D) ? "IP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_S) ? "SCTP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_D) ? "SCTP_D" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_SCTP_EN_SCTP_VTAG) ? "SCTP_VTAG" : ""); + break; + case IPV6_OTHER: + snprintf(tuples_name, len, "%s %s", + (rss_type & HIKP_RSS_NONFRAG_IPV6_OTHER_EN_IP_S) ? "IP_S" : "", + (rss_type & HIKP_RSS_NONFRAG_IPV6_OTHER_EN_IP_D) ? "IP_D" : ""); + break; + default: + break; + } +} + +static void hikp_nic_rss_get_tuples_name(enum hikp_nic_rss_pkt_type pkt_type, uint64_t rss_type, + char *tuples_name, uint8_t len) +{ + hikp_nic_rss_get_ipv4_tuples_name(pkt_type, rss_type, tuples_name, len); + hikp_nic_rss_get_ipv6_tuples_name(pkt_type, rss_type, tuples_name, len); + if (tuples_name[0] == '\0') + HIKP_WARN_PRINT("Invalid packet type.\n"); +} + +static void hikp_nic_rss_show_tuple(const void *data) +{ +#define RSS_MAX_TUPLES_NAME_LEN 64 + + const struct { + const char *str; /* Type name. */ + enum hikp_nic_rss_pkt_type pkt_type; + uint64_t rss_type; /* Type value. */ + } rss_type_table[] = { + { "ipv4-frag", IPV4_FRAG, HIKP_RSS_FRAG_IPV4_MASK }, + { "ipv4-tcp", IPV4_TCP, HIKP_RSS_NONFRAG_IPV4_TCP_MASK }, + { "ipv4-udp", IPV4_UDP, HIKP_RSS_NONFRAG_IPV4_UDP_MASK }, + { "ipv4-sctp", IPV4_SCTP, HIKP_RSS_NONFRAG_IPV4_SCTP_MASK }, + { "ipv4-other", IPV4_OTHER, HIKP_RSS_NONFRAG_IPV4_OTHER_MASK }, + { "ipv6-frag", IPV6_FRAG, HIKP_RSS_FRAG_IPV6_MASK }, + { "ipv6-tcp", IPV6_TCP, HIKP_RSS_NONFRAG_IPV4_TCP_MASK }, + { "ipv6-udp", IPV6_UDP, HIKP_RSS_NONFRAG_IPV6_UDP_MASK }, + { "ipv6-sctp", IPV6_SCTP, HIKP_RSS_NONFRAG_IPV6_SCTP_MASK }, + { "ipv6-other", IPV6_OTHER, HIKP_RSS_NONFRAG_IPV6_OTHER_MASK }, + }; + struct rss_tuple_fields *tuple_info = (struct rss_tuple_fields *)data; + size_t type_size = HIKP_ARRAY_SIZE(rss_type_table); + size_t i; + + for (i = 0; i < type_size; i++) { + if (tuple_info->tuple_field == 0) { + printf("RSS disable"); + break; + } + + char tuples_name[RSS_MAX_TUPLES_NAME_LEN] = {0}; + + if (tuple_info->tuple_field & rss_type_table[i].rss_type) { + hikp_nic_rss_get_tuples_name(rss_type_table[i].pkt_type, + tuple_info->tuple_field, + tuples_name, RSS_MAX_TUPLES_NAME_LEN); + printf("%s enable field: %s\n", rss_type_table[i].str, tuples_name); + } + } + printf("\n"); +} + +static void hikp_nic_rss_show_reta_table(const void *data) +{ + struct rss_reta_info *reta_info = (struct rss_reta_info *)data; + uint16_t i; + + for (i = 0; i < reta_info->reta_size; i++) { + if (i >= HIKP_RSS_RETA_SIZE_MAX) { + HIKP_ERROR_PRINT("The cmd data is truncated.\n"); + break; + } + printf("RSS RETA configuration: hash index=%u, queue=%u\n", i, reta_info->reta[i]); + } +} + +static void hikp_nic_rss_show_tc_mode(const void *data) +{ + struct rss_tc_mode_entry *tc_mode_entry = (struct rss_tc_mode_entry *)data; + uint16_t tc; + + printf("tc_num | tc_valid | tc_offset | tc_size\n"); + for (tc = 0; tc < HIKP_NIC_MAX_TC_NUM; tc++) { + printf("%u | %u | %04u | %u\n", + tc, tc_mode_entry[tc].tc_valid, + tc_mode_entry[tc].tc_offset, tc_mode_entry[tc].tc_size); + } +} + +static int hikp_nic_rss_get_blk(struct hikp_cmd_header *req_header, + const struct nic_rss_req_para *req_data, + void *buf, size_t buf_len, struct nic_rss_rsp_head *rsp_head) +{ + struct hikp_cmd_ret *cmd_ret; + struct nic_rss_rsp *rsp; + int ret = 0; + + cmd_ret = hikp_cmd_alloc(req_header, req_data, sizeof(*req_data)); + if (cmd_ret == NULL) { + HIKP_ERROR_PRINT("failed to get block-%u context.\n", req_data->block_id); + return -EIO; + } + + rsp = (struct nic_rss_rsp *)cmd_ret->rsp_data; + if (rsp->rsp_head.cur_blk_size > buf_len) { + HIKP_ERROR_PRINT("nic_rss block-%u copy size error, " + "buffer size=%u, data size=%u.\n", + req_data->block_id, buf_len, rsp->rsp_head.cur_blk_size); + ret = -EINVAL; + goto out; + } + memcpy(buf, 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: + free(cmd_ret); + return ret; +} + +static int hikp_nic_query_rss_feature(struct hikp_cmd_header *req_header, const struct bdf_t *bdf, + union nic_rss_feature_info *data) +{ + struct nic_rss_rsp_head rsp_head = {0}; + struct nic_rss_req_para req_data; + size_t buf_len = sizeof(*data); + uint32_t total_blk_size; + uint8_t total_blk_num; + uint8_t blk_num = 0; + uint8_t blk_id = 0; + int ret; + + req_data.bdf = *bdf; + + req_data.block_id = blk_id; + ret = hikp_nic_rss_get_blk(req_header, &req_data, data, buf_len, &rsp_head); + if (ret != 0) + return ret; + + total_blk_num = rsp_head.total_blk_num; + total_blk_size = rsp_head.cur_blk_size; + + /* Copy the remaining block content if total block number is greater than 1. */ + for (blk_id = 1; blk_id < total_blk_num; blk_id++) { + req_data.block_id = blk_id; + ret = hikp_nic_rss_get_blk(req_header, &req_data, + (uint8_t *)data + total_blk_size, + buf_len - total_blk_size, &rsp_head); + if (ret != 0) + return ret; + total_blk_size += rsp_head.cur_blk_size; + } + + return ret; +} + +static void hikp_nic_rss_cmd_execute(struct major_cmd_ctrl *self) +{ + union nic_rss_feature_info rss_data = {0}; + const struct rss_feature_cmd *rss_cmd; + struct hikp_cmd_header req_header = {0}; + int ret; + + if (g_rss_param.feature_idx == -1) { + hikp_nic_rss_cmd_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), "-g/--get param error!"); + self->err_no = -EINVAL; + return; + } + + rss_cmd = &g_rss_feature_cmd[g_rss_param.feature_idx]; + hikp_cmd_init(&req_header, NIC_MOD, GET_RSS_INFO_CMD, rss_cmd->sub_cmd_code); + ret = hikp_nic_query_rss_feature(&req_header, &g_rss_param.target.bdf, &rss_data); + if (ret != 0) { + snprintf(self->err_str, sizeof(self->err_str), "failed to query %s, ret = %d.", + rss_cmd->feature_name, ret); + self->err_no = ret; + return; + } + + printf("################### RSS %s ###################\n", rss_cmd->feature_name); + rss_cmd->show(&rss_data); + printf("#################### END #######################\n"); +} + +static int hikp_nic_cmd_get_rss_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_rss_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "unknown device!"); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_cmd_rss_feature_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t feat_size = HIKP_ARRAY_SIZE(g_rss_feature_cmd); + size_t i; + + for (i = 0; i < feat_size; i++) { + if (strcmp(argv, g_rss_feature_cmd[i].feature_name) == 0) { + g_rss_param.feature_idx = i; + return 0; + } + } + + hikp_nic_rss_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 void cmd_nic_get_rss_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + g_rss_param.feature_idx = -1; + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_rss_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_rss_cmd_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_get_rss_target); + cmd_option_register("-g", "--get", true, hikp_nic_cmd_rss_feature_select); +} + +HIKP_CMD_DECLARE("nic_rss", "show rss info of nic!", cmd_nic_get_rss_init); diff --git a/net/nic/nic_rss/hikp_nic_rss.h b/net/nic/nic_rss/hikp_nic_rss.h new file mode 100644 index 0000000..39b3300 --- /dev/null +++ b/net/nic/nic_rss/hikp_nic_rss.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 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_NIC_RSS_H +#define HIKP_NIC_RSS_H + +#include "hikp_net_lib.h" + +enum nic_rss_sub_cmd_type { + RSS_ALGO_DUMP = 0, + RSS_KEY_DUMP, + RSS_TUPLE_DUMP, + RSS_RETA_DUMP, + RSS_TC_MODE_DUMP, +}; + +#define HIKP_RSS_RETA_SIZE_MAX 2048 +struct rss_reta_info { + uint16_t reta_size; + uint16_t rsv; + uint16_t reta[HIKP_RSS_RETA_SIZE_MAX]; +}; + +#define HIKP_RSS_HASH_KEY_LEN_MAX 128 +struct rss_hash_key { + uint16_t key_len; + uint16_t rsv; + uint8_t key[HIKP_RSS_HASH_KEY_LEN_MAX]; +}; + +struct rss_tc_mode_entry { + uint16_t tc_offset; + uint16_t tc_size; + uint8_t tc_valid; + uint8_t rsv[3]; +}; + +struct rss_tuple_fields { + uint64_t tuple_field; /* IPV4: LOW 32BIT, IPV6: HIGH 32BIT */ + uint64_t rsv; +}; + +#define HIKP_RSS_HASH_TOEPLITZ 0 +#define HIKP_RSS_HASH_SIMPLE_XOR 1 +#define HIKP_RSS_HASH_SYMMETRIC_TOEPLITZ 2 + +union nic_rss_feature_info { + uint8_t hash_algo; + struct rss_hash_key hash_key; + struct rss_tuple_fields tuples; + struct rss_reta_info reta_info; + struct rss_tc_mode_entry tc_mode_entry[HIKP_NIC_MAX_TC_NUM]; +}; + +struct nic_rss_rsp_head { + uint8_t total_blk_num; + uint8_t cur_blk_size; /* real data size, not contain head size. */ + uint16_t rsv; +}; + +#define NIC_RSS_MAX_RSP_DATA 59 +struct nic_rss_rsp { + struct nic_rss_rsp_head rsp_head; /* 4 Byte */ + uint32_t rsp_data[NIC_RSS_MAX_RSP_DATA]; +}; + +struct nic_rss_req_para { + struct bdf_t bdf; + uint8_t block_id; +}; + +struct nic_rss_param { + struct tool_target target; + int feature_idx; +}; + +#define HIKP_RSS_MAX_FEATURE_NAME_LEN 20 +struct rss_feature_cmd { + const char feature_name[HIKP_RSS_MAX_FEATURE_NAME_LEN]; + uint32_t sub_cmd_code; + void (*show)(const void *data); +}; + +#endif /* HIKP_NIC_RSS_H */ -- Gitee From d3d1fc4942a9fa2ee810627beb68bb7cc4d87a52 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:24:32 +0800 Subject: [PATCH 08/14] support querying SATA module information queries information about the SATA module, including the global and port dfx registers. Signed-off-by: nifujia (cherry picked from commit 7b285cff9eec1b19837ba17f22718ed01cd745f4) --- CMakeLists.txt | 1 + sata/sata_func/sata_common.h | 31 +++++ sata/sata_func/sata_dump_reg.c | 77 +++++++++++ sata/sata_func/sata_dump_reg.h | 27 ++++ sata/user_cmd/cmd_code/sata_cmd_dump.c | 138 ++++++++++++++++++++ sata/user_cmd/cmd_code/sata_tools_include.h | 29 ++++ 6 files changed, 303 insertions(+) create mode 100644 sata/sata_func/sata_common.h create mode 100644 sata/sata_func/sata_dump_reg.c create mode 100644 sata/sata_func/sata_dump_reg.h create mode 100644 sata/user_cmd/cmd_code/sata_cmd_dump.c create mode 100644 sata/user_cmd/cmd_code/sata_tools_include.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b38417f..7a51ba3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ file(GLOB_RECURSE HIKPTOOL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/net/*.c ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/sata/*.c ${CMAKE_CURRENT_SOURCE_DIR}/serdes/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c ${CMAKE_CURRENT_SOURCE_DIR}/hikp_init_main.c diff --git a/sata/sata_func/sata_common.h b/sata/sata_func/sata_common.h new file mode 100644 index 0000000..82e39c0 --- /dev/null +++ b/sata/sata_func/sata_common.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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 __SATA_COMMON_H_ +#define __SATA_COMMON_H_ + +#define SATA_MAX_PORT_NUM 1 +#define RESP_MAX_NUM 60 + +/* SATA command code */ +enum sata_cmd_type { + SATA_DUMP = 0, +}; + +enum sata_dump_cmd_type { + DUMP_UNKNOWN = 0, + DUMP_GLOBAL, + DUMP_PORTX, +}; + +#endif diff --git a/sata/sata_func/sata_dump_reg.c b/sata/sata_func/sata_dump_reg.c new file mode 100644 index 0000000..86f6760 --- /dev/null +++ b/sata/sata_func/sata_dump_reg.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 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 "hikptdev_plug.h" +#include "sata_common.h" +#include "sata_dump_reg.h" + +static int sata_get_reg(const struct tool_sata_cmd *cmd, uint32_t *reg_save, uint32_t *reg_num) +{ + uint32_t i; + struct hikp_cmd_ret *cmd_ret; + struct hikp_cmd_header req_header = { 0 }; + struct sata_dump_req_para req_data = { 0 }; + + req_data.die_id = cmd->die_id; + req_data.phy_id = cmd->phy_id; + req_data.chip_id = cmd->chip_id; + + hikp_cmd_init(&req_header, SATA_MOD, SATA_DUMP, cmd->sata_cmd_type); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL) { + printf("hikp_data_proc err\n"); + return -1; + } + *reg_num = cmd_ret->rsp_data_num; + for (i = 0; i < *reg_num; i++) + reg_save[i] = cmd_ret->rsp_data[i]; + + free(cmd_ret); + return 0; +} + +static void sata_print_reg(uint32_t cmd_type, const uint32_t *reg_save, uint32_t reg_num) +{ + uint32_t i; + + if (reg_num == 0) { + printf("SATA dump is failed\n"); + return; + } + printf(" sata reg dump list:\n"); + for (i = 0; i < reg_num; i++) + printf(" 0x%08x\n", reg_save[i]); +} + +int sata_reg_dump(struct tool_sata_cmd *cmd) +{ + int ret; + uint32_t sata_reg_num = 0; + uint32_t sata_reg_save[RESP_MAX_NUM] = { 0 }; + + if (cmd == NULL) + return -ENOSPC; + + ret = sata_get_reg(cmd, sata_reg_save, &sata_reg_num); + if (ret) + return ret; + + sata_print_reg(cmd->sata_cmd_type, sata_reg_save, sata_reg_num); + + return 0; +} diff --git a/sata/sata_func/sata_dump_reg.h b/sata/sata_func/sata_dump_reg.h new file mode 100644 index 0000000..972ab71 --- /dev/null +++ b/sata/sata_func/sata_dump_reg.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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 __SATA_DUMP_REG_H_ +#define __SATA_DUMP_REG_H_ + +#include "sata_tools_include.h" + +struct sata_dump_req_para { + uint32_t chip_id; + uint32_t die_id; + uint32_t phy_id; +}; + +int sata_reg_dump(struct tool_sata_cmd *cmd); + +#endif diff --git a/sata/user_cmd/cmd_code/sata_cmd_dump.c b/sata/user_cmd/cmd_code/sata_cmd_dump.c new file mode 100644 index 0000000..d38ff1c --- /dev/null +++ b/sata/user_cmd/cmd_code/sata_cmd_dump.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022 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 "tool_cmd.h" +#include "sata_tools_include.h" +#include "sata_common.h" +#include "sata_dump_reg.h" + +struct tool_sata_cmd g_sata_dump_cmd = { + .sata_cmd_type = DUMP_UNKNOWN, + .phy_id = (uint32_t)(-1), + .chip_id = (uint32_t)(-1), + .die_id = (uint32_t)(-1), +}; + +static int sata_dump_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-c", "--chipid", "please input chip id[x] first\n"); + printf(" %s, %-25s %s\n", "-d", "--dieid", "please input die id[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-p", "--portx", "set port num(0-1) to dump reg\n"); + printf(" %s, %-25s %s\n", "-g", "--global", "dump global dfx reg\n"); + printf("\n"); + + return 0; +} + +static int sata_set_id(struct major_cmd_ctrl *self, const char *argv, uint32_t *id) +{ + int ret; + uint32_t val = 0; + + ret = string_toui(argv, &val); + if (ret) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid id."); + self->err_no = ret; + return ret; + } + *id = val; + return ret; +} + +static int sata_set_chip_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sata_set_id(self, argv, &g_sata_dump_cmd.chip_id); +} + +static int sata_set_die_id(struct major_cmd_ctrl *self, const char *argv) +{ + return sata_set_id(self, argv, &g_sata_dump_cmd.die_id); +} + +static int sata_dump_global(struct major_cmd_ctrl *self, const char *argv) +{ + g_sata_dump_cmd.sata_cmd_type = DUMP_GLOBAL; + return 0; +} + +static int sata_dump_portx(struct major_cmd_ctrl *self, const char *argv) +{ + int ret; + uint32_t val = 0; + + g_sata_dump_cmd.sata_cmd_type = DUMP_PORTX; + ret = string_toui(argv, &val); + if (ret || val > SATA_MAX_PORT_NUM) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid portid."); + self->err_no = ret; + return -EINVAL; + } + g_sata_dump_cmd.phy_id = val; + + return 0; +} + +static int sata_dump_excute_funs_call(uint32_t cmd_type) +{ + if (cmd_type != DUMP_UNKNOWN) + return sata_reg_dump(&g_sata_dump_cmd); + + return -1; +} + +static void sata_dump_execute(struct major_cmd_ctrl *self) +{ + int ret; + const char *suc_msg[] = { + "", + "sata_dump_global success.", + "sata_dump_port success.", + "sata_dump_axi success." + }; + const char *err_msg[] = { + "sata_dump failed, unknown cmd type", + "sata_dump_global error.", + "sata_dump_port error.", + "sata_dump_axi error." + }; + + ret = sata_dump_excute_funs_call(g_sata_dump_cmd.sata_cmd_type); + if (ret == 0) { + printf("%s\n", suc_msg[g_sata_dump_cmd.sata_cmd_type]); + } else { + snprintf(self->err_str, sizeof(self->err_str), "%s\n", + err_msg[g_sata_dump_cmd.sata_cmd_type]); + self->err_no = ret; + } +} + +static void cmd_sata_dump_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = sata_dump_execute; + + cmd_option_register("-c", "--chipid", true, sata_set_chip_id); + cmd_option_register("-d", "--dieid", true, sata_set_die_id); + cmd_option_register("-h", "--help", false, sata_dump_help); + cmd_option_register("-g", "--global", false, sata_dump_global); + cmd_option_register("-p", "--portx", true, sata_dump_portx); +} + +HIKP_CMD_DECLARE("sata_dump", "sata reg dump", cmd_sata_dump_init); diff --git a/sata/user_cmd/cmd_code/sata_tools_include.h b/sata/user_cmd/cmd_code/sata_tools_include.h new file mode 100644 index 0000000..a9671a9 --- /dev/null +++ b/sata/user_cmd/cmd_code/sata_tools_include.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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 __SATA_TOOLS_INCLUDE_H_ +#define __SATA_TOOLS_INCLUDE_H_ + +#include "hikptdev_plug.h" +#include "tool_lib.h" + +#define MAX_PARA_LENTH 10 + +struct tool_sata_cmd { + uint32_t sata_cmd_type; + uint32_t phy_id; + uint32_t chip_id; + uint32_t die_id; +}; + +#endif -- Gitee From 19cc7fb84164a16a7991e672a297874d3eba4d58 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:26:01 +0800 Subject: [PATCH 09/14] support querying the RoH module information querying information about the RoH module, including the MAC mode, packet sending and receiving, L/C, protocol header information, and entries. Signed-off-by: zhangwenkai (cherry picked from commit 99d48570419c71ca5de56bf1a0ce81f84f82ab75) --- net/roh/hikp_roh_cmd.h | 38 ++++ net/roh/hikp_roh_mac.c | 419 ++++++++++++++++++++++++++++++++++++ net/roh/hikp_roh_mac.h | 107 +++++++++ net/roh/hikp_roh_show_bp.c | 135 ++++++++++++ net/roh/hikp_roh_show_bp.h | 50 +++++ net/roh/hikp_roh_show_mib.c | 272 +++++++++++++++++++++++ net/roh/hikp_roh_show_mib.h | 86 ++++++++ 7 files changed, 1107 insertions(+) create mode 100644 net/roh/hikp_roh_cmd.h create mode 100644 net/roh/hikp_roh_mac.c create mode 100644 net/roh/hikp_roh_mac.h create mode 100644 net/roh/hikp_roh_show_bp.c create mode 100644 net/roh/hikp_roh_show_bp.h create mode 100644 net/roh/hikp_roh_show_mib.c create mode 100644 net/roh/hikp_roh_show_mib.h diff --git a/net/roh/hikp_roh_cmd.h b/net/roh/hikp_roh_cmd.h new file mode 100644 index 0000000..5aea6ac --- /dev/null +++ b/net/roh/hikp_roh_cmd.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 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_ROH_CMD_H__ +#define __HIKP_ROH_CMD_H__ + +#include "hikp_net_lib.h" + +#define RESPONSE_DATA_NUMBER_MAX 60 + +enum roh_subcmd { + CMD_SHOW_MAC_TYPE = 0, + CMD_SHOW_CAM = 1, + CMD_SHOW_CREDIT = 2, + CMD_GET_CAM_REG_NUM = 3, + CMD_BUILD_CAM_TABLE = 4, +}; + +enum roh_show_mib_subcmd { + CMD_SHOW_MIB_FILL_CNT = 0, +}; + +enum roh_show_bp_subcmd { + CMD_SHOW_BP = 0, +}; + +int hikp_roh_get_mac_type(struct major_cmd_ctrl *self, struct bdf_t bdf); +#endif /* __HIKP_ROH_CMD_H__ */ diff --git a/net/roh/hikp_roh_mac.c b/net/roh/hikp_roh_mac.c new file mode 100644 index 0000000..90708b1 --- /dev/null +++ b/net/roh/hikp_roh_mac.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2022 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 "hikp_roh_mac.h" +#include "hikp_roh_cmd.h" + +static struct roh_mac_param g_roh_mac_param = { 0 }; + +static int hikp_roh_mac_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, + "-i -s \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-s", "--show=", + "show cam table mapping or mac_type or credit_cnt"); + printf("\n"); + return 0; +} + +static int hikp_roh_mac_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roh_mac_param.target)); + if (self->err_no != 0) + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + + return self->err_no; +} + +static int cmd_show_mac_type_parse(void) +{ + g_roh_mac_param.flag |= CMD_SHOW_MAC_TYPE_FLAG; + return 0; +} + +static int cmd_show_cam_parse(void) +{ + g_roh_mac_param.flag |= CMD_SHOW_CAM_FLAG; + return 0; +} + +static int cmd_show_credit_parse(void) +{ + g_roh_mac_param.flag |= CMD_SHOW_CREDIT_CNT; + return 0; +} + +static int hikp_roh_mac_show_parse(struct major_cmd_ctrl *self, const char *argv) +{ + int ret; + + if (strncmp(argv, "cam", sizeof("cam")) == 0) { + ret = cmd_show_cam_parse(); + } else if (strncmp(argv, "mac_type", sizeof("mac_type")) == 0) { + ret = cmd_show_mac_type_parse(); + } else if (strncmp(argv, "credit", sizeof("credit")) == 0) { + ret = cmd_show_credit_parse(); + } else { + hikp_roh_mac_help(self, NULL); + snprintf(self->err_str, sizeof(self->err_str), + "-s/--show param should be cam/mac_type/credit"); + self->err_no = -EINVAL; + return -EINVAL; + } + return ret; +} + +int hikp_roh_get_mac_type(struct major_cmd_ctrl *self, struct bdf_t bdf) +{ + struct roh_mac_req_para req_data = { 0 }; + struct roh_mac_get_type *mac_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + uint8_t is_roh; + + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_MAC, CMD_SHOW_MAC_TYPE); + req_data.bdf = bdf; + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("failed to get roh info, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + self->err_no = -EIO; + free(cmd_ret); + return -EIO; + } + mac_rsp = (struct roh_mac_get_type *)(cmd_ret->rsp_data); + is_roh = mac_rsp->mac_type; + free(cmd_ret); + cmd_ret = NULL; + return is_roh; +} + +static void hikp_roh_show_mac_type(struct major_cmd_ctrl *self, int mac_type) +{ + if (mac_type) + printf("MAC_TYPE: ROH\n"); + else + printf("MAC_TYPE: ETH\n"); +} + +static void hikp_roh_print_cam(unsigned int cam_convert_enable, unsigned int convert_enable, + const struct cam_table_entry_t *cam_table) +{ + printf("**************CAM TABLE INFO*************\n"); + if (cam_convert_enable & DMAC_CONVERT_ENABLE_MASK) + printf("CAM TABLE DMAC convert : Enable\n"); + else + printf("CAM TABLE DMAC convert : Disable\n"); + + if (cam_convert_enable & SMAC_CONVERT_ENABLE_MASK) + printf("CAM TABLE SMAC convert : Enable\n"); + else + printf("CAM TABLE SMAC convert : Disable\n"); + + printf("%3s%8s%16s%8s\n", "ID", "EID", "MAC", "Status"); + for (int camid = 0; camid < MAX_CAM_SIZE; camid++) { + printf("%3d %06x %012lx", camid, cam_table[camid].eid, cam_table[camid].mac); + if (convert_enable & (1UL << camid)) + printf("%8s\n", "Enable"); + else + printf("%8s\n", "Disable"); + } + printf("*****************************************\n"); +} + +static int hikp_roh_get_cam_reg_num(struct major_cmd_ctrl *self) +{ + struct roh_mac_cam_reg_num *mac_rsp = NULL; + struct roh_mac_req_para req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + + req_data.bdf = g_roh_mac_param.target.bdf; + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_MAC, CMD_GET_CAM_REG_NUM); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("fail to get cam reg num, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + self->err_no = -EIO; + free(cmd_ret); + return -EIO; + } + mac_rsp = (struct roh_mac_cam_reg_num *)(cmd_ret->rsp_data); + return mac_rsp->cam_reg_num; +} + +static int hikp_roh_build_cam(struct major_cmd_ctrl *self, struct cam_table_entry_t *cam_table) +{ + struct roh_mac_req_para req_data = { 0 }; + struct roh_mac_cam_table *mac_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int block_num; + int reg_num; + int addtion; + int index; + + reg_num = hikp_roh_get_cam_reg_num(self); + if (reg_num < 0) + return -EIO; + + addtion = reg_num % RESPONSE_DATA_NUMBER_MAX ? 1 : 0; + block_num = reg_num / RESPONSE_DATA_NUMBER_MAX + addtion; + + for (int i = 0; i < block_num; i++) { + req_data.bdf = g_roh_mac_param.target.bdf; + req_data.cam_block_index = i; + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_MAC, CMD_BUILD_CAM_TABLE); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("fail to get cam table info, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + self->err_no = -EIO; + free(cmd_ret); + return -EIO; + } + mac_rsp = (struct roh_mac_cam_table *)(cmd_ret->rsp_data); + for (int j = 0; j < BLOCK_SIZE; j++) { + index = i * BLOCK_SIZE + j; + if (index >= MAX_CAM_SIZE) + break; + + cam_table[index].eid = (mac_rsp->cam_eid[j]) & 0xffffff; + cam_table[index].mac = 0xffffffffUL & + (unsigned long)(mac_rsp->cam_mac_low32[j]); + cam_table[index].mac |= ((0xffffUL & + (unsigned long)(mac_rsp->cam_mac_high16[j])) << + ROH_MAC_CAM_OFFSET); + } + free(cmd_ret); + cmd_ret = NULL; + } + return 0; +} + +static void hikp_roh_show_cam(struct major_cmd_ctrl *self) +{ + struct cam_table_entry_t cam_table[MAX_CAM_SIZE] = { 0 }; + struct roh_mac_req_para req_data = { 0 }; + struct roh_mac_cam_caps *mac_rsp = NULL; + unsigned int cam_convert_enable; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + unsigned int convert_enable; + int ret; + + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_MAC, CMD_SHOW_CAM); + req_data.bdf = g_roh_mac_param.target.bdf; + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("fail to get cam info, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + self->err_no = -EIO; + free(cmd_ret); + return; + } + mac_rsp = (struct roh_mac_cam_caps *)cmd_ret->rsp_data; + convert_enable = mac_rsp->convert_enable; + cam_convert_enable = mac_rsp->cam_convert_enable; + free(cmd_ret); + cmd_ret = NULL; + + ret = hikp_roh_build_cam(self, cam_table); + if (ret != 0) + return; + + hikp_roh_print_cam(cam_convert_enable, convert_enable, cam_table); +} + +static int hikp_roh_query_crd(uint8_t crd_type, uint32_t num_rows, char const *crds[][2]) +{ + struct roh_mac_credit_data *mac_rsp = NULL; + struct roh_mac_req_para req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_MAC, CMD_SHOW_CREDIT); + req_data.bdf = g_roh_mac_param.target.bdf; + req_data.crd_type = crd_type; + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) { + free(cmd_ret); + cmd_ret = NULL; + return ret; + } + mac_rsp = (struct roh_mac_credit_data *)(cmd_ret->rsp_data); + for (int i = 0; i < num_rows; i++) { + union cut_reg reg; + + reg.value = (mac_rsp->cut_reg_value)[i]; + if ((strcmp(crds[i][0], "NULL") != 0) && (reg.cut[0] != 0)) + printf("%-28s : %#x\n", crds[i][0], (reg.cut)[0]); + + if ((strcmp(crds[i][1], "NULL") != 0) && (reg.cut)[1] != 0) + printf("%-28s : %#x\n", crds[i][1], (reg.cut)[1]); + } + free(cmd_ret); + cmd_ret = NULL; + return 0; +} + +static int hikp_roh_print_holding_crd(void) +{ + int ret; + + char const *holding_crds[][2] = { + {"MAC0_TX_ICRD_VNA", "NULL"}, {"MAC0_TX_ICRD_VN_TC0", "MAC0_TX_ICRD_VN_TC1"}, + {"MAC0_TX_ICRD_VN_TC2", "MAC0_TX_ICRD_VN_TC3"}, + {"MAC0_TX_ICRD_VN_TC4", "MAC0_TX_ICRD_VN_TC5"}, + {"MAC0_TX_ICRD_VN_TC6", "MAC0_TX_ICRD_VN_TC7"}, {"MAC2_TX_ICRD_VNA", "NULL"}, + {"MAC2_TX_ICRD_VN_TC0", "MAC2_TX_ICRD_VN_TC1"}, + {"MAC2_TX_ICRD_VN_TC2", "MAC2_TX_ICRD_VN_TC3"}, + {"MAC2_TX_ICRD_VN_TC4", "MAC2_TX_ICRD_VN_TC5"}, + {"MAC2_TX_ICRD_VN_TC6", "MAC2_TX_ICRD_VN_TC7"} }; + + ret = hikp_roh_query_crd(HOLDING_CRD, NUM_ROWS_HOLDING_CRDS, holding_crds); + return ret; +} + +static int hikp_roh_print_init_crd(void) +{ + int ret; + + char const *init_crds[][2] = { + {"MAC0_RX_CFG_REMOTE_ICRD", "NULL"}, + {"MAC0_RX_CFG_REMOTE_CRD_VL6", "MAC0_RX_CFG_REMOTE_CRD_VL7"}, + {"MAC0_RX_CFG_REMOTE_CRD_VL4", "MAC0_RX_CFG_REMOTE_CRD_VL5"}, + {"MAC0_RX_CFG_REMOTE_CRD_VL2", "MAC0_RX_CFG_REMOTE_CRD_VL3"}, + {"MAC0_RX_CFG_REMOTE_CRD_VL0", "MAC0_RX_CFG_REMOTE_CRD_VL1"}, + {"MAC0_RX_CFG_REMOTE_CRD_VL8", "NULL"}, {"MAC2_RX_CFG_REMOTE_ICRD", "NULL"}, + {"MAC2_RX_CFG_REMOTE_CRD_VL6", "MAC2_RX_CFG_REMOTE_CRD_VL7"}, + {"MAC2_RX_CFG_REMOTE_CRD_VL4", "MAC2_RX_CFG_REMOTE_CRD_VL5"}, + {"MAC2_RX_CFG_REMOTE_CRD_VL2", "MAC2_RX_CFG_REMOTE_CRD_VL3"}, + {"MAC2_RX_CFG_REMOTE_CRD_VL0", "MAC2_RX_CFG_REMOTE_CRD_VL1"}, + {"MAC2_RX_CFG_REMOTE_CRD_VL8", "NULL"} }; + + ret = hikp_roh_query_crd(INIT_CRD, NUM_ROWS_INIT_CRDS, init_crds); + return ret; +} + +static int hikp_roh_print_temp_crd(void) +{ + int ret; + + char const *temp_crds[][2] = { + {"MAC0_TX_LCRD_VNA_EXIST_NUM", "NULL"}, {"MAC0_TX_ICRD_VNA_EXIST_NUM", "NULL"}, + {"MAC0_TX_CRD_VN0_EXIST_NUM", "NULL"}, {"MAC0_TX_CRD_VN1_EXIST_NUM", "NULL"}, + {"MAC0_TX_CRD_VN2_EXIST_NUM", "NULL"}, {"MAC0_TX_CRD_VN3_EXIST_NUM", "NULL"}, + {"MAC0_TX_CRD_VN4_EXIST_NUM", "NULL"}, {"MAC0_TX_CRD_VN5_EXIST_NUM", "NULL"}, + {"MAC0_TX_CRD_VN6_EXIST_NUM", "NULL"}, {"MAC0_TX_CRD_VN7_EXIST_NUM", "NULL"}, + {"MAC2_TX_LCRD_VNA_EXIST_NUM", "NULL"}, {"MAC2_TX_ICRD_VNA_EXIST_NUM", "NULL"}, + {"MAC2_TX_CRD_VN0_EXIST_NUM", "NULL"}, {"MAC2_TX_CRD_VN1_EXIST_NUM", "NULL"}, + {"MAC2_TX_CRD_VN2_EXIST_NUM", "NULL"}, {"MAC2_TX_CRD_VN3_EXIST_NUM", "NULL"}, + {"MAC2_TX_CRD_VN4_EXIST_NUM", "NULL"}, {"MAC2_TX_CRD_VN5_EXIST_NUM", "NULL"}, + {"MAC2_TX_CRD_VN6_EXIST_NUM", "NULL"}, {"MAC2_TX_CRD_VN7_EXIST_NUM", "NULL"} }; + + ret = hikp_roh_query_crd(TEMP_CRD, NUM_ROWS_TEMP_CRDS, temp_crds); + return ret; +} + +static void hikp_roh_mac_show_credit(struct major_cmd_ctrl *self) +{ + int ret; + + printf("******************** CREDIT CNT START ********************\n"); + printf("------------------- HOLDING CREDIT START-----------------\n"); + ret = hikp_roh_print_holding_crd(); + if (ret != 0) { + HIKP_ERROR_PRINT("failed to get holding crd, retcode: %d\n", ret); + self->err_no = ret; + return; + } + printf("------------------- HOLDING CREDIT END -----------------\n"); + printf("------------------- INIT CREDIT START -----------------\n"); + ret = hikp_roh_print_init_crd(); + if (ret != 0) { + HIKP_ERROR_PRINT("failed to get init crd, retcode: %d\n", ret); + self->err_no = ret; + return; + } + printf("------------------- INIT CREDIT END --------------------\n"); + printf("------------------- TEMP CREDIT START ------------------\n"); + ret = hikp_roh_print_temp_crd(); + if (ret != 0) { + HIKP_ERROR_PRINT("failed to get temp crd, retcode: %d\n", ret); + self->err_no = ret; + return; + } + printf("------------------- TEMP CREDIT END --------------------\n"); + printf("********************* CREDIT CNT END *********************\n"); +} + +static int hikp_roh_is_roh(struct major_cmd_ctrl *self) +{ + int mac_type = hikp_roh_get_mac_type(self, g_roh_mac_param.target.bdf); + + if (mac_type == -EIO) { + HIKP_ERROR_PRINT("Failed get current mac type\n"); + } else if (mac_type == 0) { + HIKP_ERROR_PRINT("Current mac is not roh type, don't support\n"); + self->err_no = -EINVAL; + } + return mac_type; +} + +static void hikp_roh_mac_execute_entry(struct major_cmd_ctrl *self) +{ + int mac_type; + + switch (g_roh_mac_param.flag) { + case (CMD_SHOW_MAC_TYPE_FLAG): + mac_type = hikp_roh_get_mac_type(self, g_roh_mac_param.target.bdf); + if (mac_type == -EIO) { + HIKP_ERROR_PRINT("Failed get current mac type\n"); + return; + } + hikp_roh_show_mac_type(self, mac_type); + break; + case (CMD_SHOW_CAM_FLAG): + if (hikp_roh_is_roh(self) > 0) + hikp_roh_show_cam(self); + break; + case (CMD_SHOW_CREDIT_CNT): + if (hikp_roh_is_roh(self) > 0) + hikp_roh_mac_show_credit(self); + break; + default: + printf("roh_mac param format error\n"); + self->err_no = -EINVAL; + } +} + +static void cmd_roh_mac_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roh_mac_execute_entry; + + cmd_option_register("-h", "--help", false, hikp_roh_mac_help); + cmd_option_register("-i", "--interface", true, hikp_roh_mac_target); + cmd_option_register("-s", "--show", true, hikp_roh_mac_show_parse); +} + +HIKP_CMD_DECLARE("roh_mac", "get roh mac information", cmd_roh_mac_init); diff --git a/net/roh/hikp_roh_mac.h b/net/roh/hikp_roh_mac.h new file mode 100644 index 0000000..88115cf --- /dev/null +++ b/net/roh/hikp_roh_mac.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 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_ROH_MAC_H__ +#define __HIKP_ROH_MAC_H__ + +#include "tool_lib.h" +#include "hikp_net_lib.h" + +#define MAX_CRD_SIZE 20 + +#define ROH_MAC_ROH_PORT_ID_OFFSET 4 +#define ROH_MAC_DIR_OFFSET 5 +#define ROH_MAC_CAM_OFFSET 32 +#define ROH_MAC_LRH_LB_OFFSET 16 +#define ROH_MAC_LRH_VNI_0_OFFSET 24 +#define ROH_MAC_LRH_VNI_1_OFFSET 8 +#define ROH_MAC_LRH_SEID_OFFSET 8 +#define ROH_MAC_LRH_TTL_OFFSET 24 +#define ROH_MAC_LRH_SL_OFFSET 28 +#define ROH_MAC_LRH_FECN_OFFSET 1 +#define ROH_MAC_LRH_RM_OFFSET 3 +#define ROH_MAC_LRH_PLENGTH_OFFSET 5 +#define ROH_MAC_LRH_NLP_OFFSET 19 +#define ROH_MAC_LRH_CFG_OFFSET 24 +#define ROH_MAC_LRH_VL_OFFSET 29 +#define ROH_MAC_LRH_REG_MATCH_1 0 +#define ROH_MAC_LRH_REG_MATCH_2 1 +#define ROH_MAC_LRH_REG_MATCH_3 2 +#define ROH_MAC_LRH_REG_MATCH_4 3 +#define NUM_ROWS_HOLDING_CRDS 10 +#define NUM_ROWS_INIT_CRDS 12 +#define NUM_ROWS_TEMP_CRDS 20 +#define NUM_REGS 4 + +#define MAX_CAM_SIZE 32 +#define CMD_SHOW_MAC_TYPE_FLAG HI_BIT(31) +#define CMD_SHOW_CAM_FLAG HI_BIT(30) +#define CMD_SHOW_CREDIT_CNT HI_BIT(29) +#define COMMANDER_ERR_MAX_STRING 128 +#define ROH_LINK_0 0 +#define ROH_LINK_1 1 +#define BLOCK_SIZE 20 +#define DMAC_CONVERT_ENABLE_MASK 0x1 +#define SMAC_CONVERT_ENABLE_MASK 0x10 + +enum print_crd { + HOLDING_CRD = 0, + INIT_CRD = 1, + TEMP_CRD = 2, +}; + +struct roh_mac_param { + struct tool_target target; + uint32_t flag; +}; + +struct roh_mac_req_para { + struct bdf_t bdf; + uint8_t crd_type; + uint32_t cam_block_index; +}; + +struct cam_table_entry_t { + unsigned int eid; + unsigned long mac; +}; + +union cut_reg { + uint32_t value; + uint16_t cut[2]; +}; + +struct roh_mac_get_type { + uint8_t mac_type; +}; + +struct roh_mac_cam_caps { + uint32_t convert_enable; + uint32_t cam_convert_enable; +}; + +struct roh_mac_cam_reg_num { + uint32_t cam_reg_num; +}; + +struct roh_mac_cam_table { + uint32_t cam_eid[20]; + uint32_t cam_mac_low32[20]; + uint32_t cam_mac_high16[20]; +}; + +struct roh_mac_credit_data { + uint32_t cut_reg_value[MAX_CRD_SIZE]; +}; + +#endif /* __HIKP_ROH_MAC_H__ */ diff --git a/net/roh/hikp_roh_show_bp.c b/net/roh/hikp_roh_show_bp.c new file mode 100644 index 0000000..c89e98b --- /dev/null +++ b/net/roh/hikp_roh_show_bp.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2022 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 "hikp_roh_show_bp.h" +#include "hikp_roh_cmd.h" + +static struct cmd_roh_show_bp_param g_roh_show_bp_param = { 0 }; + +static int hikp_roh_show_bp_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i -s\n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-s", "--show", "show backpressure"); + printf("\n"); + return 0; +} + +static int hikp_roh_show_bp_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roh_show_bp_param.target)); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + return 0; +} + +static int hikp_roh_show_bp(struct major_cmd_ctrl *self) +{ + uint8_t pfc[8] = { 0 }; + uint8_t egu_tx_bp; + union bp_val res; + uint8_t flit_bp; + int mac_id; + int ret; + + struct hikp_cmd_ret *cmd_ret = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct roh_show_bp_req_paras req_data = { 0 }; + struct roh_show_bp_rsp_t *bp_rsp = NULL; + + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_SHOW_BP, CMD_SHOW_BP); + req_data.bdf = g_roh_show_bp_param.target.bdf; + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (cmd_ret == NULL || cmd_ret->status != 0) { + HIKP_ERROR_PRINT("fail to get bp info, retcode: %u\n", + cmd_ret ? cmd_ret->status : EIO); + self->err_no = -EIO; + ret = -EIO; + goto out; + } + bp_rsp = (struct roh_show_bp_rsp_t *)(cmd_ret->rsp_data); + res.val = bp_rsp->bp_val; + mac_id = bp_rsp->mac_id; + if (mac_id % VERIFY_MAC_ID != 0) { + HIKP_ERROR_PRINT("Invalid mac id\n"); + self->err_no = -EINVAL; + ret = -EINVAL; + goto out; + } + + for (int i = 0; i < BP_SIZE; i++) { + if (mac_id == 0) + pfc[i] = ((res._val.st_ssu_pfc_mac0)>>i) & 0x1; + else + pfc[i] = ((res._val.st_ssu_pfc_mac1)>>i) & 0x1; + + printf("MAC%d_pfc_%d : 0x%x\n", mac_id, i, pfc[i]); + } + egu_tx_bp = mac_id == 0 ? res._val.st_roh_egu_tx_bp_mac0 : res._val.st_roh_egu_tx_bp_mac1; + flit_bp = mac_id == 0 ? res._val.st_hllc_roh_flit_bp_mac0 : + res._val.st_hllc_roh_flit_bp_mac1; + printf("MAC%d_egu_tx_bp : 0x%x\n", mac_id, egu_tx_bp); + printf("MAC%d_flit_bp : 0x%x\n", mac_id, flit_bp); + +out: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static void hikp_roh_show_bp_execute(struct major_cmd_ctrl *self) +{ + int mac_type = hikp_roh_get_mac_type(self, g_roh_show_bp_param.target.bdf); + + if (g_roh_show_bp_param.flag & ROH_CMD_SHOW_BP) { + if (mac_type == -EIO) { + self->err_no = -EIO; + return; + } + + if (mac_type == 0) { + HIKP_ERROR_PRINT("Current mac is not roh type, don't support\n"); + self->err_no = -EINVAL; + return; + } + + hikp_roh_show_bp(self); + } else { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Invalid operation\n"); + } +} + +static int hikp_roh_show_bp_parse(struct major_cmd_ctrl *self, const char *argv) +{ + g_roh_show_bp_param.flag |= ROH_CMD_SHOW_BP; + return 0; +} + +static void cmd_roh_show_bp_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roh_show_bp_execute; + + cmd_option_register("-h", "--help", false, hikp_roh_show_bp_help); + cmd_option_register("-i", "--interface", true, hikp_roh_show_bp_target); + cmd_option_register("-s", "--show", false, hikp_roh_show_bp_parse); +} + +HIKP_CMD_DECLARE("roh_show_bp", "get roh bp information", cmd_roh_show_bp_init); diff --git a/net/roh/hikp_roh_show_bp.h b/net/roh/hikp_roh_show_bp.h new file mode 100644 index 0000000..e7a3894 --- /dev/null +++ b/net/roh/hikp_roh_show_bp.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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_ROH_SHOW_BP_H__ +#define __HIKP_ROH_SHOW_BP_H__ + +#include "hikp_net_lib.h" + +struct cmd_roh_show_bp_param { + struct tool_target target; + uint8_t flag; +}; + +struct roh_show_bp_req_paras { + struct bdf_t bdf; +}; + +union bp_val { + uint32_t val; + struct { + uint32_t st_ssu_pfc_mac0 : 8; + uint32_t st_ssu_pfc_mac1 : 8; + uint32_t st_roh_egu_tx_bp_mac0 : 1; + uint32_t st_roh_egu_tx_bp_mac1 : 1; + uint32_t st_hllc_roh_flit_bp_mac0 : 1; + uint32_t st_hllc_roh_flit_bp_mac1 : 1; + uint32_t rsv : 12; + } _val; +}; + +struct roh_show_bp_rsp_t { + uint8_t mac_id; + uint32_t bp_val; +}; + +#define ROH_CMD_SHOW_BP 1 +#define VERIFY_MAC_ID 2 +#define BP_SIZE 8 + +#endif /* __HIKP_ROH_SHOW_BP_H__ */ diff --git a/net/roh/hikp_roh_show_mib.c b/net/roh/hikp_roh_show_mib.c new file mode 100644 index 0000000..425a0e6 --- /dev/null +++ b/net/roh/hikp_roh_show_mib.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2022 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 "hikp_roh_show_mib.h" +#include "hikp_roh_cmd.h" + +static struct cmd_roh_show_mib_param roh_show_mib_param = { 0 }; + +static char g_roh_mac_mib_name[MIB_EVENT_COUNT][ROH_NAME_MAX] = { + "TX_FROM_SSU_UDM", + "TX_FROM_SSU_MIN_64", + "TX_FROM_SSU_65_127", + "TX_FROM_SSU_128_255", + "TX_FROM_SSU_256_511", + "TX_FROM_SSU_512_1023", + "TX_FROM_SSU_1024_1518", + "TX_FROM_SSU_1519_2047", + "TX_FROM_SSU_2048_4095", + "TX_FROM_SSU_4096_MAX", + "TX_FROM_SSU_LARGER_THAN_MAX", + "TX_FROM_SSU_RDMA_PKT", + "TX_FROM_SSU_RDMA_INC_PKT", + "TX_FROM_SSU_IP_PKT", + "TX_FROM_SSU_HNMP_EID_PKT", + "TX_FROM_SSU_HNMP_DR_PKT", + "TX_FROM_SSU_ERR_PKT", + "TX_FROM_SSU_TC0", + "TX_FROM_SSU_TC1", + "TX_FROM_SSU_TC2", + "TX_FROM_SSU_TC3", + "TX_FROM_SSU_TC4", + "TX_FROM_SSU_TC5", + "TX_FROM_SSU_TC6", + "TX_FROM_SSU_TC7", + "TX_SENDBY_ROH_MAC_BLOCK", + "TX_SENDBY_ROH_MAC_PKT", + "RX_TO_SSU_UDM", + "RX_TO_SSU_MIN_64", + "RX_TO_SSU_65_127", + "RX_TO_SSU_128_255", + "RX_TO_SSU_256_511", + "RX_TO_SSU_512_1023", + "RX_TO_SSU_1024_1518", + "RX_TO_SSU_1519_2047", + "RX_TO_SSU_2048_4095", + "RX_TO_SSU_4096_MAX", + "RX_TO_SSU_LARGER_THAN_MAX", + "RX_TO_SSU_RDMA_PKT", + "RX_TO_SSU_RDMA_INC_PKT", + "RX_TO_SSU_IP_PKT", + "RX_TO_SSU_HNMP_EID_PKT", + "RX_TO_SSU_HNMP_DR_PKT", + "RX_TO_SSU_ERR_PKT", + "RX_TO_SSU_TC0", + "RX_TO_SSU_TC1", + "RX_TO_SSU_TC2", + "RX_TO_SSU_TC3", + "RX_TO_SSU_TC4", + "RX_TO_SSU_TC5", + "RX_TO_SSU_TC6", + "RX_TO_SSU_TC7", + "RX_RECVBY_ROH_MAC_BLOCK", + "RX_RECVBY_ROH_MAC_PKT", + + "TX_FROM_SSU_HNMP_UAAP_PKT", + "RX_FROM_SSU_HNMP_UAAP_PKT", + + // ========== 56 ================ + "NA", "NA", "NA", "NA", "NA", "NA", + // ========== 62 ================ + "TX_FROM_SSU_HNMP_UAAP_BYTE", + "RX_FROM_SSU_HNMP_UAAP_BYTE", + "TX_SENDBY_ROH_MAC_FLIT", + "RX_RECVBY_ROH_MAC_FLIT", + // ========== 66 ================ + "TX_FROM_SSU_RDMA_BYTE", + "TX_FROM_SSU_RDMA_INC_BYTE", + "TX_FROM_SSU_IP_BYTE", + "TX_FROM_SSU_HNMP_EID_BYTE", + "TX_FROM_SSU_HNMP_DR_BYTE", + "TX_FROM_SSU_TC0_BYTE", + "TX_FROM_SSU_TC1_BYTE", + "TX_FROM_SSU_TC2_BYTE", + "TX_FROM_SSU_TC3_BYTE", + "TX_FROM_SSU_TC4_BYTE", + "TX_FROM_SSU_TC5_BYTE", + "TX_FROM_SSU_TC6_BYTE", + "TX_FROM_SSU_TC7_BYTE", + "RX_TO_SSU_RDMA_BYTE", + "RX_TO_SSU_RDMA_INC_BYTE", + "RX_TO_SSU_IP_BYTE", + "RX_TO_SSU_HNMP_EID_BYTE", + "RX_TO_SSU_HNMP_DR_BYTE", + "RX_TO_SSU_TC0_BYTE", + "RX_TO_SSU_TC1_BYTE", + "RX_TO_SSU_TC2_BYTE", + "RX_TO_SSU_TC3_BYTE", + "RX_TO_SSU_TC4_BYTE", + "RX_TO_SSU_TC5_BYTE", + "RX_TO_SSU_TC6_BYTE", + "RX_TO_SSU_TC7_BYTE", + // ========== 92 ================ + "TX_ICRD_VNA_USE", + "TX_ICRD_VN_USE_TC0", + "TX_ICRD_VN_USE_TC1", + "TX_ICRD_VN_USE_TC2", + "TX_ICRD_VN_USE_TC3", + "TX_ICRD_VN_USE_TC4", + "TX_ICRD_VN_USE_TC5", + "TX_ICRD_VN_USE_TC6", + "TX_ICRD_VN_USE_TC7", + "TX_ICRD_VNA_RELEASE", + "TX_ICRD_VN_RELEASE_TC0", + "TX_ICRD_VN_RELEASE_TC1", + "TX_ICRD_VN_RELEASE_TC2", + "TX_ICRD_VN_RELEASE_TC3", + "TX_ICRD_VN_RELEASE_TC4", + "TX_ICRD_VN_RELEASE_TC5", + "TX_ICRD_VN_RELEASE_TC6", + "TX_ICRD_VN_RELEASE_TC7", + + "RX_ICRD_VNA_RECV", + "RX_ICRD_VN_RECV_TC0", + "RX_ICRD_VN_RECV_TC1", + "RX_ICRD_VN_RECV_TC2", + "RX_ICRD_VN_RECV_TC3", + "RX_ICRD_VN_RECV_TC4", + "RX_ICRD_VN_RECV_TC5", + "RX_ICRD_VN_RECV_TC6", + "RX_ICRD_VN_RECV_TC7", + "RX_ICRD_VNA_RELEASE_TO_SSU", + "RX_ICRD_VN_RELEASE_TO_SSU_TC0", + "RX_ICRD_VN_RELEASE_TO_SSU_TC1", + "RX_ICRD_VN_RELEASE_TO_SSU_TC2", + "RX_ICRD_VN_RELEASE_TO_SSU_TC3", + "RX_ICRD_VN_RELEASE_TO_SSU_TC4", + "RX_ICRD_VN_RELEASE_TO_SSU_TC5", + "RX_ICRD_VN_RELEASE_TO_SSU_TC6", + "RX_ICRD_VN_RELEASE_TO_SSU_TC7" +}; + +static int hikp_roh_show_mib_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i -s\n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth1"); + printf(" %s, %-25s %s\n", "-s", "--show", "show non-zero mib"); + printf("\n"); + return 0; +} + +static int hikp_roh_show_mib_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(roh_show_mib_param.target)); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + return 0; +} + +static int hikp_roh_fill_pmu_cnt(int round) +{ + struct roh_show_mib_req_paras req_data = { 0 }; + struct roh_show_mib_rsp_t *mib_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + uint64_t mac0_pmu_cnt; + uint64_t mac2_pmu_cnt; + int index; + int ret; + + hikp_cmd_init(&req_header, ROH_MOD, HIKP_ROH_SHOW_MIB, CMD_SHOW_MIB_FILL_CNT); + req_data.bdf = roh_show_mib_param.target.bdf; + req_data.round = round; + + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) { + free(cmd_ret); + cmd_ret = NULL; + return ret; + } + mib_rsp = (struct roh_show_mib_rsp_t *)(cmd_ret->rsp_data); + for (int i = 0; i < BLOCK_SIZE; i++) { + index = round * BLOCK_SIZE + i; + if (index >= MIB_EVENT_COUNT) + break; + + mac0_pmu_cnt = mib_rsp->reg_data[i][0]; + mac2_pmu_cnt = mib_rsp->reg_data[i][1]; + if (mac0_pmu_cnt) + printf("MAC0_%-28s : 0x%lx\n", g_roh_mac_mib_name[index], mac0_pmu_cnt); + + if (mac2_pmu_cnt) + printf("MAC2_%-28s : 0x%lx\n", g_roh_mac_mib_name[index], mac2_pmu_cnt); + } + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static void hikp_roh_show_mib_in_multi_rounds(struct major_cmd_ctrl *self) +{ + int mac_type = hikp_roh_get_mac_type(self, roh_show_mib_param.target.bdf); + int total_round; + int addition; + int ret; + + addition = MIB_EVENT_COUNT % RESPONSE_MIB_NUMBER_MAX ? 1 : 0; + total_round = MIB_EVENT_COUNT / RESPONSE_MIB_NUMBER_MAX + addition; + + if (mac_type == -EIO) { + self->err_no = -EIO; + return; + } + if (mac_type == 0) { + HIKP_ERROR_PRINT("Current mac is not roh type, don't support\n"); + self->err_no = -EINVAL; + return; + } + + for (int i = 0; i < total_round; i++) { + ret = hikp_roh_fill_pmu_cnt(i); + if (ret != 0) { + printf("Failed to get mib info in %dth round!\n", i); + return; + } + } +} + +static void hikp_roh_show_mib_execute(struct major_cmd_ctrl *self) +{ + if (roh_show_mib_param.flag & ROH_CMD_SHOW_MIB) { + hikp_roh_show_mib_in_multi_rounds(self); + } else { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Invalid operation\n"); + } +} + +static int hikp_roh_show_mib_parse(struct major_cmd_ctrl *self, const char *argv) +{ + roh_show_mib_param.flag |= ROH_CMD_SHOW_MIB; + return 0; +} + +static void cmd_roh_show_mib_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roh_show_mib_execute; + + cmd_option_register("-h", "--help", false, hikp_roh_show_mib_help); + cmd_option_register("-i", "--interface", true, hikp_roh_show_mib_target); + cmd_option_register("-s", "--show", false, hikp_roh_show_mib_parse); +} + +HIKP_CMD_DECLARE("roh_show_mib", "get roh mac mib information", cmd_roh_show_mib_init); diff --git a/net/roh/hikp_roh_show_mib.h b/net/roh/hikp_roh_show_mib.h new file mode 100644 index 0000000..fc7c308 --- /dev/null +++ b/net/roh/hikp_roh_show_mib.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022 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_ROH_SHOW_MIB_H__ +#define __HIKP_ROH_SHOW_MIB_H__ + +#include "hikp_net_lib.h" + +#define ROH_NAME_MAX 50 +#define ROH_CMD_MAX 15 +#define FLAG_ROH_MAC_PMU_RC 1 +#define FIRST_PMU_CUT 0 +#define SECOND_PMU_CUT 1 +#define THIRD_PMU_CUT 2 +#define FOURTH_PMU_CUT 3 +#define PMU_OFFSET 32 +#define MIB_EVENT_COUNT 128 +#define BLOCK_SIZE 15 + +struct cmd_roh_show_mib_param { + struct tool_target target; + uint8_t flag; +}; +union cfg_pmu_val { + uint32_t val; + struct { + uint32_t cfg_pmu_en : 1; + uint32_t resv1 : 3; + uint32_t cfg_pmu_clr : 1; + uint32_t resv2 : 3; + uint32_t cfg_pmu_rd_en : 1; + uint32_t resv3 : 3; + uint32_t cfg_pmu_rd_num : 7; + uint32_t resv4 : 1; + uint32_t cfg_pmu_mem : 1; + uint32_t resv5 : 3; + uint32_t mem_init_done : 1; + uint32_t resv6 : 7; + } _val; +}; +union st_pmu_4 { + uint32_t val; + struct { + uint32_t pmu_cnt_rd_vld_0 : 1; + uint32_t resv1 : 3; + uint32_t pmu_cnt_rd_vld_1 : 1; + uint32_t resv2 : 27; + } _val; +}; +struct roh_show_mib_req_paras { + struct bdf_t bdf; + uint32_t round; +}; +struct roh_show_mib_rsp_t { + uint64_t reg_data[BLOCK_SIZE][2]; +}; + +struct roh_show_mib_reg_num { + uint32_t reg_num; +}; + +enum target_addr { + CFG_PMU0 = 0, + CFG_PMU1 = 1, + ICG_EN = 2, + ST_PMU0 = 3, + ST_PMU1 = 4, + ST_PMU2 = 5, + ST_PMU3 = 6, + MAC_TYPE = 7, +}; + +#define ROH_CMD_SHOW_MIB (1 << 0) +#define RESPONSE_MIB_NUMBER_MAX 15 + +#endif /* __HIKP_ROH_SHOW_MIB_H__ */ -- Gitee From 118ea596f830d6710589c8f935e5c14338b57d7c Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:27:24 +0800 Subject: [PATCH 10/14] support querying RoCE module information querying information including flow control algorithm parameters, packet sending and receiving, and internal sub-module status. Signed-off-by: shushengming (cherry picked from commit 392c269be165f687f5fbeb14279aece562152f56) --- net/roce/roce_caep/hikp_roce_caep.c | 103 +++++++++ net/roce/roce_caep/hikp_roce_caep.h | 40 ++++ net/roce/roce_gmv/hikp_roce_gmv.c | 118 ++++++++++ net/roce/roce_gmv/hikp_roce_gmv.h | 41 ++++ net/roce/roce_mdb/hikp_roce_mdb.c | 122 ++++++++++ net/roce/roce_mdb/hikp_roce_mdb.h | 41 ++++ net/roce/roce_pkt/hikp_roce_pkt.c | 107 +++++++++ net/roce/roce_pkt/hikp_roce_pkt.h | 42 ++++ net/roce/roce_qmm/hikp_roce_qmm.c | 179 +++++++++++++++ net/roce/roce_qmm/hikp_roce_qmm.h | 43 ++++ net/roce/roce_scc/hikp_roce_scc.c | 285 ++++++++++++++++++++++++ net/roce/roce_scc/hikp_roce_scc.h | 69 ++++++ net/roce/roce_timer/hikp_roce_timer.c | 174 +++++++++++++++ net/roce/roce_timer/hikp_roce_timer.h | 43 ++++ net/roce/roce_trp/hikp_roce_trp.c | 308 ++++++++++++++++++++++++++ net/roce/roce_trp/hikp_roce_trp.h | 73 ++++++ net/roce/roce_tsp/hikp_roce_tsp.c | 205 +++++++++++++++++ net/roce/roce_tsp/hikp_roce_tsp.h | 64 ++++++ 18 files changed, 2057 insertions(+) create mode 100644 net/roce/roce_caep/hikp_roce_caep.c create mode 100644 net/roce/roce_caep/hikp_roce_caep.h create mode 100644 net/roce/roce_gmv/hikp_roce_gmv.c create mode 100644 net/roce/roce_gmv/hikp_roce_gmv.h create mode 100644 net/roce/roce_mdb/hikp_roce_mdb.c create mode 100644 net/roce/roce_mdb/hikp_roce_mdb.h create mode 100644 net/roce/roce_pkt/hikp_roce_pkt.c create mode 100644 net/roce/roce_pkt/hikp_roce_pkt.h create mode 100644 net/roce/roce_qmm/hikp_roce_qmm.c create mode 100644 net/roce/roce_qmm/hikp_roce_qmm.h create mode 100644 net/roce/roce_scc/hikp_roce_scc.c create mode 100644 net/roce/roce_scc/hikp_roce_scc.h create mode 100644 net/roce/roce_timer/hikp_roce_timer.c create mode 100644 net/roce/roce_timer/hikp_roce_timer.h create mode 100644 net/roce/roce_trp/hikp_roce_trp.c create mode 100644 net/roce/roce_trp/hikp_roce_trp.h create mode 100644 net/roce/roce_tsp/hikp_roce_tsp.c create mode 100644 net/roce/roce_tsp/hikp_roce_tsp.h diff --git a/net/roce/roce_caep/hikp_roce_caep.c b/net/roce/roce_caep/hikp_roce_caep.c new file mode 100644 index 0000000..69a4742 --- /dev/null +++ b/net/roce/roce_caep/hikp_roce_caep.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_caep.h" + +static struct cmd_roce_caep_param_t g_roce_caep_param_t = { 0 }; + +static int hikp_roce_caep_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf("\n"); + + return 0; +} + +static int hikp_roce_caep_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_caep_param_t.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_caep_get_data(struct hikp_cmd_ret **cmd_ret, + struct roce_caep_req_param req_data) +{ + struct hikp_cmd_header req_header = { 0 }; + + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_CAEP_CMD, 0); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (*cmd_ret == NULL) { + printf("hikptool roce_caep cmd_ret malloc failed\n"); + return -EIO; + } + + return 0; +} + +static void hikp_roce_caep_print(uint32_t total_block_num, + const uint32_t *offset, const uint32_t *data) +{ + uint32_t i; + + printf("**************CAEP INFO*************\n"); + for (i = 0; i < total_block_num; i++) + printf("[0x%08X] : 0x%08X\n", offset[i], data[i]); + printf("************************************\n"); +} + +static void hikp_roce_caep_execute(struct major_cmd_ctrl *self) +{ + struct roce_caep_res_param *roce_caep_res; + struct roce_caep_req_param req_data; + struct hikp_cmd_ret *cmd_ret; + int ret; + + req_data.bdf = g_roce_caep_param_t.target.bdf; + ret = hikp_roce_caep_get_data(&cmd_ret, req_data); + if (ret < 0) { + self->err_no = ret; + return; + } else if (cmd_ret->status != 0) { + printf("hikptool roce_caep read data failed\n"); + goto exec_error; + } + roce_caep_res = (struct roce_caep_res_param *)cmd_ret->rsp_data; + hikp_roce_caep_print(roce_caep_res->total_block_num, + roce_caep_res->reg_data.offset, roce_caep_res->reg_data.data); + +exec_error: + free(cmd_ret); + cmd_ret = NULL; +} + +static void cmd_roce_caep_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_caep_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_caep_help); + cmd_option_register("-i", "--interface", true, hikp_roce_caep_target); +} + +HIKP_CMD_DECLARE("roce_caep", "get roce_caep registers information", cmd_roce_caep_init); diff --git a/net/roce/roce_caep/hikp_roce_caep.h b/net/roce/roce_caep/hikp_roce_caep.h new file mode 100644 index 0000000..3c494b1 --- /dev/null +++ b/net/roce/roce_caep/hikp_roce_caep.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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_ROCE_CAEP_H__ +#define __HIKP_ROCE_CAEP_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_CAEP_REG_NUM 29 +#define PER_REG_NUM 2 + +struct cmd_roce_caep_param_t { + struct tool_target target; +}; + +struct roce_caep_req_param { + struct bdf_t bdf; +}; + +struct roce_caep_res { + uint32_t offset[ROCE_HIKP_CAEP_REG_NUM]; + uint32_t data[ROCE_HIKP_CAEP_REG_NUM]; +}; + +struct roce_caep_res_param { + uint32_t total_block_num; + struct roce_caep_res reg_data; +}; + +#endif /* __HIKP_ROCE_CAEP_H__ */ diff --git a/net/roce/roce_gmv/hikp_roce_gmv.c b/net/roce/roce_gmv/hikp_roce_gmv.c new file mode 100644 index 0000000..d65dc82 --- /dev/null +++ b/net/roce/roce_gmv/hikp_roce_gmv.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_gmv.h" + +static struct cmd_roce_gmv_param g_roce_gmv_param = { 0 }; + +static int hikp_roce_gmv_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-x", "--gmv_index", + "[option]set which gid to read. (default 0)"); + printf("\n"); + + return 0; +} + +static int hikp_roce_gmv_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_gmv_param.target)); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_gmv_idxget(struct major_cmd_ctrl *self, const char *argv) +{ + char *endptr = NULL; + int index; + + index = strtol(argv, &endptr, 0); + if ((endptr <= argv) || (*endptr != '\0') || + (index < 0) || (index >= ROCE_MAX_HIKPTOOL_GMV)) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid gmv_index."); + self->err_no = -EINVAL; + return -EINVAL; + } + g_roce_gmv_param.gmv_index = index; + + return 0; +} + +static void hikp_roce_gmv_print(uint32_t reg_num, struct roce_gmv_rsp_data *gmv_rsp) +{ + uint32_t i; + + printf("*******************GMV INFO****************\n"); + printf("addr_offset : reg_data\n"); + for (i = 0; i < reg_num; i++) + printf("0x%08X : 0x%08X\n", gmv_rsp->reg_offset[i], gmv_rsp->reg_data[i]); + printf("*******************************************\n"); +} + +static void hikp_roce_gmv_execute(struct major_cmd_ctrl *self) +{ + struct roce_gmv_req_para req_data = { 0 }; + struct roce_gmv_rsp_data *gmv_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + uint32_t reg_num; + int ret; + + req_data.bdf = g_roce_gmv_param.target.bdf; + req_data.gmv_index = g_roce_gmv_param.gmv_index; + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_GMV_CMD, GMV_SHOW); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto exec_error; + + if (cmd_ret->rsp_data_num == 0) { + printf("roce show gmv single-port info cmd param mem read failed\n"); + goto exec_error; + } + reg_num = cmd_ret->rsp_data_num / ROCE_HIKP_GMV_REG_SWICTH; + if (reg_num != ROCE_HIKP_GMV_REG_NUM) { + printf("version might not match\n"); + goto exec_error; + } + + gmv_rsp = (struct roce_gmv_rsp_data *)(cmd_ret->rsp_data); + hikp_roce_gmv_print(reg_num, gmv_rsp); +exec_error: + free(cmd_ret); + cmd_ret = NULL; +} + +static void cmd_roce_gmv_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_gmv_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_gmv_help); + cmd_option_register("-i", "--interface", true, hikp_roce_gmv_target); + cmd_option_register("-x", "--gmv_index", true, hikp_roce_gmv_idxget); +} + +HIKP_CMD_DECLARE("roce_gmv", "get roce_gmv registers information", cmd_roce_gmv_init); diff --git a/net/roce/roce_gmv/hikp_roce_gmv.h b/net/roce/roce_gmv/hikp_roce_gmv.h new file mode 100644 index 0000000..30f37fb --- /dev/null +++ b/net/roce/roce_gmv/hikp_roce_gmv.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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_ROCE_GMV_H__ +#define __HIKP_ROCE_GMV_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_GMV_REG_NUM 7 +#define ROCE_HIKP_GMV_REG_SWICTH 2 +#define ROCE_MAX_HIKPTOOL_GMV 128 +struct cmd_roce_gmv_param { + struct tool_target target; + uint32_t gmv_index; +}; + +struct roce_gmv_req_para { + struct bdf_t bdf; + uint32_t gmv_index; +}; + +struct roce_gmv_rsp_data { + uint32_t reg_offset[ROCE_HIKP_GMV_REG_NUM]; + uint32_t reg_data[ROCE_HIKP_GMV_REG_NUM]; +}; + +enum roce_gmv_cmd_type { + GMV_SHOW = 0x0, +}; + +#endif /* __HIKP_ROCE_GMV_H__ */ diff --git a/net/roce/roce_mdb/hikp_roce_mdb.c b/net/roce/roce_mdb/hikp_roce_mdb.c new file mode 100644 index 0000000..9cc07a1 --- /dev/null +++ b/net/roce/roce_mdb/hikp_roce_mdb.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_mdb.h" + +#define ROCE_MDB_CMD_CLEAR HI_BIT(0) +static struct cmd_roce_mdb_param g_roce_mdb_param = { 0 }; + +static int hikp_roce_mdb_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-c", "--clear=", "clear mdb registers"); + printf("\n"); + + return 0; +} + +static int hikp_roce_mdb_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_mdb_param.target)); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_mdb_clear_set(struct major_cmd_ctrl *self, const char *argv) +{ + g_roce_mdb_param.reset_flag = ROCE_MDB_CMD_CLEAR; + return 0; +} + +static void hikp_roce_mdb_print(uint32_t reg_num, struct roce_mdb_rsp_data *mdb_rsp) +{ + uint32_t i; + + printf("**************MDB INFO*************\n"); + printf("addr_offset : reg_data\n"); + for (i = 0; i < reg_num; i++) + printf("0x%08X : 0x%08X\n", mdb_rsp->reg_offset[i], mdb_rsp->reg_data[i]); + printf("***********************************\n"); +} + +static int hikp_roce_mdb_show(struct major_cmd_ctrl *self) +{ + struct roce_mdb_req_para req_data = { 0 }; + struct roce_mdb_rsp_data *mdb_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + uint32_t reg_num; + int ret; + + req_data.bdf = g_roce_mdb_param.target.bdf; + if (g_roce_mdb_param.reset_flag) + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_MDB_CMD, MDB_CLEAR); + else + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_MDB_CMD, MDB_SHOW); + + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto exec_error; + + reg_num = cmd_ret->rsp_data_num / ROCE_HIKP_REG_SWICTH; + if (reg_num != ROCE_HIKP_MDB_REG_NUM) { + printf("version might not match.\n"); + ret = -1; + goto exec_error; + } + + mdb_rsp = (struct roce_mdb_rsp_data *)(cmd_ret->rsp_data); + hikp_roce_mdb_print(reg_num, mdb_rsp); + ret = 0; + +exec_error: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static void hikp_roce_mdb_execute(struct major_cmd_ctrl *self) +{ + self->err_no = hikp_roce_mdb_show(self); + if (self->err_no) + return; + + if (g_roce_mdb_param.reset_flag) + printf("clear roce_mdb reg success.\n"); + else + printf("show roce_mdb reg success.\n"); +} + +static void cmd_roce_mdb_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_mdb_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_mdb_help); + cmd_option_register("-i", "--interface", true, hikp_roce_mdb_target); + cmd_option_register("-c", "--clear", false, hikp_roce_mdb_clear_set); +} + +HIKP_CMD_DECLARE("roce_mdb", "get or clear roce_mdb registers information", cmd_roce_mdb_init); diff --git a/net/roce/roce_mdb/hikp_roce_mdb.h b/net/roce/roce_mdb/hikp_roce_mdb.h new file mode 100644 index 0000000..8e7da03 --- /dev/null +++ b/net/roce/roce_mdb/hikp_roce_mdb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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_ROCE_MDB_H__ +#define __HIKP_ROCE_MDB_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_MDB_REG_NUM 22 +#define ROCE_HIKP_REG_SWICTH 2 + +struct cmd_roce_mdb_param { + struct tool_target target; + int reset_flag; +}; + +struct roce_mdb_req_para { + struct bdf_t bdf; +}; + +struct roce_mdb_rsp_data { + uint32_t reg_offset[ROCE_HIKP_MDB_REG_NUM]; + uint32_t reg_data[ROCE_HIKP_MDB_REG_NUM]; +}; + +enum roce_mdb_cmd_type { + MDB_SHOW = 0x0, + MDB_CLEAR, +}; + +#endif /* __HIKP_ROCE_MDB_H__ */ diff --git a/net/roce/roce_pkt/hikp_roce_pkt.c b/net/roce/roce_pkt/hikp_roce_pkt.c new file mode 100644 index 0000000..abfc526 --- /dev/null +++ b/net/roce/roce_pkt/hikp_roce_pkt.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_pkt.h" + +static struct cmd_roce_pkt_param_t g_roce_pkt_param_t = { 0 }; + +static int hikp_roce_pkt_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-c", "--clear=", "clear param count registers"); + printf("\n"); + + return 0; +} + +static int hikp_roce_pkt_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_pkt_param_t.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_pkt_clear_set(struct major_cmd_ctrl *self, const char *argv) +{ + g_roce_pkt_param_t.reset_flag = 1; + return 0; +} + +static int hikp_roce_pkt_get_data(struct hikp_cmd_ret **cmd_ret, struct roce_pkt_req_param req_data) +{ + struct hikp_cmd_header req_header = { 0 }; + + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_PKT_CMD, 0); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (*cmd_ret == NULL) { + printf("hikptool roce_pkt cmd_ret malloc failed\n"); + return -EIO; + } + + return 0; +} + +static void hikp_roce_pkt_print(uint32_t total_block_num, + const uint32_t *offset, const uint32_t *data) +{ + uint32_t i; + + printf("**************PKT INFO*************\n"); + for (i = 0; i < total_block_num; i++) + printf("[0x%08X] : 0x%08X\n", offset[i], data[i]); + printf("***********************************\n"); +} + +static void hikp_roce_pkt_execute(struct major_cmd_ctrl *self) +{ + struct roce_pkt_req_param req_data = { 0 }; + struct roce_pkt_res_param *roce_pkt_res; + struct hikp_cmd_ret *cmd_ret; + int ret; + + req_data.bdf = g_roce_pkt_param_t.target.bdf; + req_data.reset_flag = g_roce_pkt_param_t.reset_flag; + ret = hikp_roce_pkt_get_data(&cmd_ret, req_data); + if (ret < 0) { + self->err_no = ret; + return; + } + roce_pkt_res = (struct roce_pkt_res_param *)cmd_ret->rsp_data; + hikp_roce_pkt_print(roce_pkt_res->total_block_num, + roce_pkt_res->reg_data.offset, roce_pkt_res->reg_data.data); + + free(cmd_ret); + cmd_ret = NULL; +} + +static void cmd_roce_pkt_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_pkt_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_pkt_help); + cmd_option_register("-i", "--interface", true, hikp_roce_pkt_target); + cmd_option_register("-c", "--clear", false, hikp_roce_pkt_clear_set); +} + +HIKP_CMD_DECLARE("roce_pkt", "get or clear roce_pkt registers information", cmd_roce_pkt_init); diff --git a/net/roce/roce_pkt/hikp_roce_pkt.h b/net/roce/roce_pkt/hikp_roce_pkt.h new file mode 100644 index 0000000..5f438b7 --- /dev/null +++ b/net/roce/roce_pkt/hikp_roce_pkt.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 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_ROCE_PKT_H__ +#define __HIKP_ROCE_PKT_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_PKT_REG_NUM 29 +#define PKT_PER_REG_NUM 2 + +struct cmd_roce_pkt_param_t { + uint8_t reset_flag; + struct tool_target target; +}; + +struct roce_pkt_req_param { + struct bdf_t bdf; + uint8_t reset_flag; +}; + +struct roce_pkt_res { + uint32_t offset[ROCE_HIKP_PKT_REG_NUM]; + uint32_t data[ROCE_HIKP_PKT_REG_NUM]; +}; + +struct roce_pkt_res_param { + uint32_t total_block_num; + struct roce_pkt_res reg_data; +}; + +#endif /* __HIKP_ROCE_PKT_H__ */ diff --git a/net/roce/roce_qmm/hikp_roce_qmm.c b/net/roce/roce_qmm/hikp_roce_qmm.c new file mode 100644 index 0000000..c7e0ca4 --- /dev/null +++ b/net/roce/roce_qmm/hikp_roce_qmm.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_qmm.h" + +static struct cmd_roce_qmm_param_t g_roce_qmm_param = { 0 }; + +static int hikp_roce_qmm_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-b", "--bank=", + "[option]bank number, e.g. 0~7. (default 0)"); + printf("\n"); + + return 0; +} + +static int hikp_roce_qmm_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_qmm_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_qmm_bank_get(struct major_cmd_ctrl *self, const char *argv) +{ + char *endptr = NULL; + int bank_num; + + bank_num = strtol(argv, &endptr, 0); + if ((endptr <= argv) || (*endptr != '\0') || bank_num > QMM_BANK_NUM || bank_num < 0) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid bank number!\n"); + self->err_no = -EINVAL; + return -EINVAL; + } + + g_roce_qmm_param.bank_id = bank_num; + return 0; +} + +static void hikp_roce_qmm_print(struct roce_qmm_rsp_data *qmm_rsp) +{ + int index = 0; + + while (index < qmm_rsp->reg_num) { + printf("0x%08X : 0x%08X\n", qmm_rsp->qmm_content[index][0], + qmm_rsp->qmm_content[index][1]); + index++; + } + printf("***************************************\n"); +} + +static int hikp_roce_qmm_show_cqc(struct major_cmd_ctrl *self) +{ + struct roce_qmm_req_para req_data = { 0 }; + struct roce_qmm_rsp_data *qmm_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + req_data.bdf = g_roce_qmm_param.target.bdf; + + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_QMM_CMD, QMM_SHOW_CQC); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto out; + + qmm_rsp = (struct roce_qmm_rsp_data *)(cmd_ret->rsp_data); + printf("**************QMM CQC INFO*************\n"); + hikp_roce_qmm_print(qmm_rsp); +out: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static int hikp_roce_qmm_show_qpc(struct major_cmd_ctrl *self) +{ + struct roce_qmm_req_para req_data = { 0 }; + struct roce_qmm_rsp_data *qmm_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + req_data.bdf = g_roce_qmm_param.target.bdf; + req_data.bank_id = g_roce_qmm_param.bank_id; + + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_QMM_CMD, QMM_SHOW_QPC); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto out; + + qmm_rsp = (struct roce_qmm_rsp_data *)(cmd_ret->rsp_data); + printf("**************QMM QPC INFO*************\n"); + hikp_roce_qmm_print(qmm_rsp); +out: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static int hikp_roce_qmm_show_top(struct major_cmd_ctrl *self) +{ + struct roce_qmm_req_para req_data = { 0 }; + struct roce_qmm_rsp_data *qmm_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + req_data.bdf = g_roce_qmm_param.target.bdf; + + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_QMM_CMD, QMM_SHOW_TOP); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto out; + + qmm_rsp = (struct roce_qmm_rsp_data *)(cmd_ret->rsp_data); + printf("**************QMM TOP INFO*************\n"); + hikp_roce_qmm_print(qmm_rsp); +out: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static void hikp_roce_qmm_execute(struct major_cmd_ctrl *self) +{ + int (*func[])(struct major_cmd_ctrl *self) = { + hikp_roce_qmm_show_cqc, hikp_roce_qmm_show_qpc, hikp_roce_qmm_show_top + }; + char *function[] = {"show cqc", "show qpc", "show top"}; + int ret; + + for (int i = 0; i < HIKP_ARRAY_SIZE(func); i++) { + ret = func[i](self); + if (ret != 0) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "roce_qmm %s function failed\n", function[i]); + break; + } + } +} + +static void cmd_roce_qmm_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_qmm_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_qmm_help); + cmd_option_register("-i", "--interface", true, hikp_roce_qmm_target); + cmd_option_register("-b", "--bank", true, hikp_roce_qmm_bank_get); +} + +HIKP_CMD_DECLARE("roce_qmm", "get roce_qmm registers information", cmd_roce_qmm_init); diff --git a/net/roce/roce_qmm/hikp_roce_qmm.h b/net/roce/roce_qmm/hikp_roce_qmm.h new file mode 100644 index 0000000..08cb5d2 --- /dev/null +++ b/net/roce/roce_qmm/hikp_roce_qmm.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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_ROCE_QMM_H__ +#define __HIKP_ROCE_QMM_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_QMM_REG_NUM 36 +#define QMM_BANK_NUM 0x7 + +struct cmd_roce_qmm_param_t { + struct tool_target target; + uint32_t bank_id; +}; + +struct roce_qmm_rsp_data { + uint32_t reg_num; + uint32_t qmm_content[ROCE_HIKP_QMM_REG_NUM][2]; +}; + +struct roce_qmm_req_para { + struct bdf_t bdf; + uint32_t bank_id; +}; + +enum roce_qmm_cmd_type { + QMM_SHOW_CQC = 0x1, + QMM_SHOW_QPC = 0x2, + QMM_SHOW_TOP = 0x3, +}; + +#endif /* __HIKP_ROCE_QMM_H__ */ diff --git a/net/roce/roce_scc/hikp_roce_scc.c b/net/roce/roce_scc/hikp_roce_scc.c new file mode 100644 index 0000000..1011814 --- /dev/null +++ b/net/roce/roce_scc/hikp_roce_scc.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_scc.h" + +struct cmd_roce_scc_param_t g_roce_scc_param_t = { 0 }; +struct roce_scc_module g_roce_scc_module[] = { + ROCE_SCC_HANDLE(COMMON), + ROCE_SCC_HANDLE(DCQCN), + ROCE_SCC_HANDLE(DIP), + ROCE_SCC_HANDLE(HC3), + ROCE_SCC_HANDLE(LDCP), + ROCE_SCC_HANDLE(CFG), +}; + +static int hikp_roce_scc_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-m", "--module=", "this is necessary param " + "COMMON/DCQCN/DIP/HC3/LDCP/CFG"); + printf(" %s, %-25s %s\n", "-c", "--clear=", + "[Only Work for COMMON]clear param count registers"); + printf("\n"); + + return 0; +} + +static int hikp_roce_scc_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_scc_param_t.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_scc_module_select(struct major_cmd_ctrl *self, const char *argv) +{ + bool is_found; + uint32_t i; + + for (i = 0; i < HIKP_ARRAY_SIZE(g_roce_scc_module); i++) { + is_found = strncmp(argv, (const char *)g_roce_scc_module[i].module_name, + sizeof(g_roce_scc_module[i].module_name)) == 0; + if (is_found) { + g_roce_scc_param_t.sub_cmd = g_roce_scc_module[i].sub_cmd_code; + return 0; + } + } + + snprintf(self->err_str, sizeof(self->err_str), "Invalid module param!"); + self->err_no = -EINVAL; + return -EINVAL; +} + +static int hikp_roce_scc_clear_set(struct major_cmd_ctrl *self, const char *argv) +{ + g_roce_scc_param_t.reset_flag = 1; + + return 0; +} + +static int hikp_roce_scc_clear_module_check(void) +{ + if (g_roce_scc_param_t.sub_cmd == COMMON) + return 0; + + return -EINVAL; +} + +static int hikp_roce_scc_get_data(struct hikp_cmd_ret **cmd_ret, const uint32_t *block_id) +{ + struct roce_scc_req_param req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + + req_data.block_id = *block_id; + req_data.bdf = g_roce_scc_param_t.target.bdf; + req_data.reset_flag = g_roce_scc_param_t.reset_flag; + if (g_roce_scc_param_t.sub_cmd == 0) { + printf("please enter module name: -m/--modlue\n"); + return -EINVAL; + } + + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_SCC_CMD, g_roce_scc_param_t.sub_cmd); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (*cmd_ret == NULL) { + printf("hikptool roce_scc cmd_ret malloc failed\n"); + return -EIO; + } + + return 0; +} + +static void hikp_roce_scc_reg_data_free(uint32_t **offset, uint32_t **data) +{ + if (*offset) { + free(*offset); + *offset = NULL; + } + if (*data) { + free(*data); + *data = NULL; + } +} + +static void hikp_roce_scc_cmd_ret_free(struct hikp_cmd_ret **cmd_ret) +{ + if (*cmd_ret) { + free(*cmd_ret); + *cmd_ret = NULL; + } +} + +static int hikp_roce_scc_get_total_data_num(struct roce_scc_head *res_head, + uint32_t **offset, uint32_t **data, uint32_t *block_id) +{ + struct roce_scc_res_param *roce_scc_res; + struct hikp_cmd_ret *cmd_ret = NULL; + size_t max_size; + size_t cur_size; + int ret; + + ret = hikp_roce_scc_get_data(&cmd_ret, block_id); + if (ret) { + printf("hikptool roce_scc get total data failed\n"); + return ret; + } + + roce_scc_res = (struct roce_scc_res_param *)cmd_ret->rsp_data; + max_size = roce_scc_res->head.total_block_num * sizeof(uint32_t); + *offset = (uint32_t *)calloc(1, max_size); + *data = (uint32_t *)calloc(1, max_size); + if ((*offset == NULL) || (*data == NULL)) { + printf("hikptool roce_scc alloc log memmory 0x%x failed\n", max_size); + ret = -ENOMEM; + goto get_data_error; + } + + cur_size = roce_scc_res->head.cur_block_num * sizeof(uint32_t); + if (cur_size > max_size) { + printf("hikptool roce_scc log data copy size error, " + "data size: 0x%x, max size: 0x%x\n", cur_size, max_size); + ret = -EINVAL; + goto get_data_error; + } + memcpy(*offset, roce_scc_res->reg_data.offset, cur_size); + memcpy(*data, roce_scc_res->reg_data.data, cur_size); + + *res_head = roce_scc_res->head; + *block_id = roce_scc_res->block_id; + ret = 0; + +get_data_error: + hikp_roce_scc_cmd_ret_free(&cmd_ret); + return ret; +} + +static int hikp_roce_scc_get_next_data(struct roce_scc_head *res_head, + uint32_t **offset, uint32_t **data, + uint32_t *block_id, size_t data_size) +{ + struct roce_scc_res_param *roce_scc_res; + struct hikp_cmd_ret *cmd_ret = NULL; + size_t cur_size; + int ret; + + ret = hikp_roce_scc_get_data(&cmd_ret, block_id); + if (ret) { + printf("hikptool roce_scc get next data failed\n"); + return ret; + } + + roce_scc_res = (struct roce_scc_res_param *)cmd_ret->rsp_data; + cur_size = roce_scc_res->head.cur_block_num * sizeof(uint32_t); + if (cur_size > data_size) { + hikp_roce_scc_cmd_ret_free(&cmd_ret); + printf("hikptool roce_scc next log data copy size error, " + "data size: 0x%x, max size: 0x%x\n", cur_size, data_size); + return -EINVAL; + } + memcpy(*offset, roce_scc_res->reg_data.offset, cur_size); + memcpy(*data, roce_scc_res->reg_data.data, cur_size); + + *block_id = roce_scc_res->block_id; + res_head->cur_block_num = roce_scc_res->head.cur_block_num; + res_head->total_block_num = res_head->total_block_num - roce_scc_res->head.cur_block_num; + hikp_roce_scc_cmd_ret_free(&cmd_ret); + + return 0; +} + +static void hikp_roce_scc_print(uint8_t total_block_num, + const uint32_t *offset, const uint32_t *data) +{ + uint32_t i; + + printf("**************SCC INFO*************\n"); + for (i = 0; i < total_block_num; i++) + printf("[0x%08X] : 0x%08X\n", offset[i], data[i]); + printf("***********************************\n"); +} + +static void hikp_roce_scc_execute(struct major_cmd_ctrl *self) +{ + struct roce_scc_head res_head; + uint32_t *offset_start = NULL; + uint32_t *data_start = NULL; + uint8_t total_block_num; + uint32_t *offset = NULL; + uint32_t *data = NULL; + uint32_t block_id; + size_t data_size; + uint32_t times; + uint32_t i; + + block_id = 0; + if (g_roce_scc_param_t.reset_flag) { + self->err_no = hikp_roce_scc_clear_module_check(); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "roce_scc clear function module selection error."); + return; + } + } + self->err_no = hikp_roce_scc_get_total_data_num(&res_head, &offset, &data, &block_id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "get the first roce_scc block dfx fail."); + hikp_roce_scc_reg_data_free(&offset, &data); + return; + } + total_block_num = res_head.total_block_num; + res_head.total_block_num = res_head.total_block_num - res_head.cur_block_num; + offset_start = offset; + data_start = data; + if (res_head.total_block_num) { + times = res_head.total_block_num / ROCE_HIKP_SCC_REG_NUM + 1; + for (i = 0; i < times; i++) { + offset = offset + res_head.cur_block_num; + data = data + res_head.cur_block_num; + data_size = res_head.total_block_num * sizeof(uint32_t); + self->err_no = hikp_roce_scc_get_next_data(&res_head, &offset, + &data, &block_id, data_size); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "get multiple roce_scc block dfx fail."); + hikp_roce_scc_reg_data_free(&offset_start, &data_start); + return; + } + } + } + hikp_roce_scc_print(total_block_num, offset_start, data_start); + hikp_roce_scc_reg_data_free(&offset_start, &data_start); +} + +static void cmd_roce_scc_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_scc_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_scc_help); + cmd_option_register("-i", "--interface", true, hikp_roce_scc_target); + cmd_option_register("-m", "--module", true, hikp_roce_scc_module_select); + cmd_option_register("-c", "--clear", false, hikp_roce_scc_clear_set); +} + +HIKP_CMD_DECLARE("roce_scc", "get or clear roce_scc registers information", cmd_roce_scc_init); diff --git a/net/roce/roce_scc/hikp_roce_scc.h b/net/roce/roce_scc/hikp_roce_scc.h new file mode 100644 index 0000000..de8772e --- /dev/null +++ b/net/roce/roce_scc/hikp_roce_scc.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022 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_ROCE_SCC_H__ +#define __HIKP_ROCE_SCC_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_SCC_REG_NUM 29 +#define MAX_SCC_MODULE_NAME_LEN 20 +#define ROCE_SCC_HANDLE(x) \ + { \ + #x, x \ + } + +struct roce_scc_req_param { + struct bdf_t bdf; + uint8_t reset_flag; + uint32_t block_id; +}; + +struct cmd_roce_scc_param_t { + struct tool_target target; + uint8_t reset_flag; + uint32_t sub_cmd; +}; + +struct roce_scc_head { + uint8_t total_block_num; + uint8_t cur_block_num; + uint16_t rsvd; +}; + +struct roce_scc_res { + uint32_t offset[ROCE_HIKP_SCC_REG_NUM]; + uint32_t data[ROCE_HIKP_SCC_REG_NUM]; +}; + +struct roce_scc_res_param { + uint32_t block_id; + struct roce_scc_head head; + struct roce_scc_res reg_data; +}; + +struct roce_scc_module { + uint8_t module_name[MAX_SCC_MODULE_NAME_LEN]; + uint32_t sub_cmd_code; +}; + +enum roce_scc_type { + COMMON = 1, + DCQCN, + DIP, + HC3, + LDCP, + CFG, +}; + +#endif /* __HIKP_ROCE_SCC_H__ */ diff --git a/net/roce/roce_timer/hikp_roce_timer.c b/net/roce/roce_timer/hikp_roce_timer.c new file mode 100644 index 0000000..c4e979f --- /dev/null +++ b/net/roce/roce_timer/hikp_roce_timer.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_timer.h" + +static struct cmd_roce_timer_params g_roce_timer_param = { 0 }; + +static int hikp_roce_timer_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-c", "--clear=", "clear timer registers"); + printf("\n"); + + return 0; +} + +static int hikp_roce_timer_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_timer_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + return 0; +} + +static int hikp_roce_timer_clear_set(struct major_cmd_ctrl *self, const char *argv) +{ + g_roce_timer_param.flag = ROCE_TIMER_CMD_CLEAR; + return 0; +} + +static void hikp_roce_timer_print(struct roce_timer_rsp_data *timer_rsp) +{ + int index = 0; + + while (index < timer_rsp->reg_num) { + printf("0x%08X : 0x%08X\n", timer_rsp->timer_content[index][0], + timer_rsp->timer_content[index][1]); + index++; + } + printf("*****************************************\n"); +} + +static int hikp_roce_timer_show_qpc(struct major_cmd_ctrl *self) +{ + struct roce_timer_req_para req_data = { 0 }; + struct roce_timer_rsp_data *timer_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + req_data.bdf = g_roce_timer_param.target.bdf; + if (g_roce_timer_param.flag) + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_TIMER_CMD, TIMER_QPC_CLEAR); + else + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_TIMER_CMD, TIMER_SHOW_QPC); + + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto out; + + timer_rsp = (struct roce_timer_rsp_data *)(cmd_ret->rsp_data); + printf("**************QPC TIMER INFO*************\n"); + hikp_roce_timer_print(timer_rsp); +out: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static int hikp_roce_timer_show_cqc(struct major_cmd_ctrl *self) +{ + struct roce_timer_req_para req_data = { 0 }; + struct roce_timer_rsp_data *timer_rsp = NULL; + struct hikp_cmd_header req_header = { 0 }; + struct hikp_cmd_ret *cmd_ret = NULL; + int ret; + + req_data.bdf = g_roce_timer_param.target.bdf; + if (g_roce_timer_param.flag) + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_TIMER_CMD, TIMER_CQC_CLEAR); + else + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_TIMER_CMD, TIMER_SHOW_CQC); + + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret != 0) + goto out; + + timer_rsp = (struct roce_timer_rsp_data *)(cmd_ret->rsp_data); + printf("**************CQC TIMER INFO*************\n"); + hikp_roce_timer_print(timer_rsp); +out: + free(cmd_ret); + cmd_ret = NULL; + return ret; +} + +static int hikp_roce_timer_clear(struct major_cmd_ctrl *self) +{ + int ret_clear_qpc; + int ret_clear_cqc; + + ret_clear_cqc = hikp_roce_timer_show_cqc(self); + if (ret_clear_cqc != 0) { + printf("clear cqc failed\n"); + return ret_clear_cqc; + } + + ret_clear_qpc = hikp_roce_timer_show_qpc(self); + if (ret_clear_qpc != 0) { + printf("clear qpc failed\n"); + return ret_clear_qpc; + } + + return 0; +} + +static void hikp_roce_timer_execute(struct major_cmd_ctrl *self) +{ + int (*func[])(struct major_cmd_ctrl *self) = { + hikp_roce_timer_show_cqc, hikp_roce_timer_show_qpc + }; + char *function[] = {"show cqc", "show qpc"}; + int i = 0; + int ret; + + if (g_roce_timer_param.flag) { + ret = hikp_roce_timer_clear(self); + } else { + for (i = 0; i < HIKP_ARRAY_SIZE(func); i++) { + ret = func[i](self); + if (ret != 0) + break; + } + } + + if (ret != 0) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), + "roce_timer %s function failed\n", function[i]); + } +} + +static void cmd_roce_timer_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_timer_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_timer_help); + cmd_option_register("-i", "--interface", true, hikp_roce_timer_target); + cmd_option_register("-c", "--clear", false, hikp_roce_timer_clear_set); +} + +HIKP_CMD_DECLARE("roce_timer", "get or clear roce_timer registers information", + cmd_roce_timer_init); diff --git a/net/roce/roce_timer/hikp_roce_timer.h b/net/roce/roce_timer/hikp_roce_timer.h new file mode 100644 index 0000000..a4a32b1 --- /dev/null +++ b/net/roce/roce_timer/hikp_roce_timer.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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_ROCE_TIMER_H__ +#define __HIKP_ROCE_TIMER_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_TIMER_REG_NUM 25 +#define ROCE_TIMER_CMD_CLEAR (1 << 0) + +enum roce_timer_cmd_type { + TIMER_SHOW_QPC = 0x1, + TIMER_SHOW_CQC, + TIMER_QPC_CLEAR, + TIMER_CQC_CLEAR, +}; + +struct cmd_roce_timer_params { + struct tool_target target; + uint8_t flag; +}; + +struct roce_timer_req_para { + struct bdf_t bdf; +}; + +struct roce_timer_rsp_data { + uint32_t reg_num; + uint32_t timer_content[ROCE_HIKP_TIMER_REG_NUM][2]; +}; + +#endif /* __HIKP_ROCE_TIMER_H__ */ diff --git a/net/roce/roce_trp/hikp_roce_trp.c b/net/roce/roce_trp/hikp_roce_trp.c new file mode 100644 index 0000000..8befb06 --- /dev/null +++ b/net/roce/roce_trp/hikp_roce_trp.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_trp.h" + +struct cmd_roce_trp_param_t g_roce_trp_param_t = { 0 }; +struct roce_trp_module g_roce_trp_module[] = { + ROCE_TRP_HANDLE(TRP_RX), + ROCE_TRP_HANDLE(GEN_AC), + ROCE_TRP_HANDLE(PAYL), + ROCE_TRP_HANDLE(COMMON), +}; + +static int hikp_roce_trp_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-m", "--module=", + "this is necessary param COMMON/TRP_RX/GEN_AC/PAYL"); + printf(" %s, %-25s %s\n", "-b", "--bank=", + "[option]set which bank to read. (default 0) " + "COMMON : 0~3\n PAYL: 0~1\n GEN_AC : 0~1\n "); + printf("\n"); + + return 0; +} + +static int hikp_roce_trp_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_trp_param_t.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_trp_module_select(struct major_cmd_ctrl *self, const char *argv) +{ + bool is_found; + uint32_t i; + + for (i = 0; i < HIKP_ARRAY_SIZE(g_roce_trp_module); i++) { + is_found = strncmp(argv, (const char *)g_roce_trp_module[i].module_name, + sizeof(g_roce_trp_module[i].module_name)) == 0; + if (is_found) { + g_roce_trp_param_t.sub_cmd = g_roce_trp_module[i].sub_cmd_code; + return 0; + } + } + snprintf(self->err_str, sizeof(self->err_str), "Invalid module param!"); + self->err_no = -EINVAL; + + return self->err_no; +} + +static int hikp_roce_trp_bank_get(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t temp; + + self->err_no = string_toui(argv, &temp); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "get roce_trp bank param failed."); + return self->err_no; + } + + g_roce_trp_param_t.bank_enter_flag = 1; + g_roce_trp_param_t.bank_id = temp; + return 0; +} + +static int hikp_roce_trp_bank_check(void) +{ + uint32_t temp; + + temp = g_roce_trp_param_t.bank_id; + switch (g_roce_trp_param_t.sub_cmd) { + case (COMMON): + if (temp > TRP_MAX_BANK_NUM || temp < 0) + return -EINVAL; + break; + case (PAYL): + if (temp > PAYL_MAX_BANK_NUM || temp < 0) + return -EINVAL; + break; + case (GEN_AC): + if (temp > GAC_MAX_BANK_NUM || temp < 0) + return -EINVAL; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int hikp_roce_trp_get_data(struct hikp_cmd_ret **cmd_ret, const uint32_t *block_id) +{ + struct roce_trp_req_param req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + + req_data.block_id = *block_id; + req_data.bdf = g_roce_trp_param_t.target.bdf; + req_data.bank_id = g_roce_trp_param_t.bank_id; + if (g_roce_trp_param_t.sub_cmd == 0) { + printf("please enter module name: -m/--modlue\n"); + return -EINVAL; + } + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_TRP_CMD, g_roce_trp_param_t.sub_cmd); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (*cmd_ret == NULL) { + printf("hikptool roce_trp cmd_ret malloc failed\n"); + return -EIO; + } + + return 0; +} + +static void hikp_roce_trp_reg_data_free(uint32_t **offset, uint32_t **data) +{ + if (*offset) { + free(*offset); + *offset = NULL; + } + if (*data) { + free(*data); + *data = NULL; + } +} + +static void hikp_roce_trp_cmd_ret_free(struct hikp_cmd_ret **cmd_ret) +{ + if (*cmd_ret) { + free(*cmd_ret); + *cmd_ret = NULL; + } +} + +static int hikp_roce_trp_get_total_data_num(struct roce_trp_head *res_head, + uint32_t **offset, uint32_t **data, uint32_t *block_id) +{ + struct roce_trp_res_param *roce_trp_res; + struct hikp_cmd_ret *cmd_ret = NULL; + size_t max_size; + size_t cur_size; + int ret; + + ret = hikp_roce_trp_get_data(&cmd_ret, block_id); + if (ret) { + printf("hikptool roce_trp get total data failed\n"); + return ret; + } + + roce_trp_res = (struct roce_trp_res_param *)cmd_ret->rsp_data; + max_size = roce_trp_res->head.total_block_num * sizeof(uint32_t); + *offset = (uint32_t *)calloc(1, max_size); + *data = (uint32_t *)calloc(1, max_size); + if ((*offset == NULL) || (*data == NULL)) { + printf("hikptool roce_trp alloc log memmory 0x%x failed\n", max_size); + ret = -ENOMEM; + goto get_data_error; + } + + cur_size = roce_trp_res->head.cur_block_num * sizeof(uint32_t); + if (cur_size > max_size) { + printf("hikptool roce_trp log data copy size error, " + "data size: 0x%x, max size: 0x%x\n", cur_size, max_size); + ret = -EINVAL; + goto get_data_error; + } + memcpy(*offset, roce_trp_res->reg_data.offset, cur_size); + memcpy(*data, roce_trp_res->reg_data.data, cur_size); + + *res_head = roce_trp_res->head; + *block_id = roce_trp_res->block_id; + ret = 0; + +get_data_error: + hikp_roce_trp_cmd_ret_free(&cmd_ret); + return ret; +} + +static int hikp_roce_trp_get_next_data(struct roce_trp_head *res_head, + uint32_t **offset, uint32_t **data, + uint32_t *block_id, size_t data_size) +{ + struct roce_trp_res_param *roce_trp_res; + struct hikp_cmd_ret *cmd_ret = NULL; + size_t cur_size; + int ret; + + ret = hikp_roce_trp_get_data(&cmd_ret, block_id); + if (ret) { + printf("hikptool roce_trp get next data failed\n"); + return ret; + } + + roce_trp_res = (struct roce_trp_res_param *)cmd_ret->rsp_data; + cur_size = roce_trp_res->head.cur_block_num * sizeof(uint32_t); + + if (cur_size > data_size) { + hikp_roce_trp_cmd_ret_free(&cmd_ret); + printf("hikptool roce_trp next log data copy size error, " + "data size: 0x%x, max size: 0x%x\n", cur_size, data_size); + return -EINVAL; + } + memcpy(*offset, roce_trp_res->reg_data.offset, cur_size); + memcpy(*data, roce_trp_res->reg_data.data, cur_size); + + *block_id = roce_trp_res->block_id; + res_head->cur_block_num = roce_trp_res->head.cur_block_num; + res_head->total_block_num = res_head->total_block_num - roce_trp_res->head.cur_block_num; + hikp_roce_trp_cmd_ret_free(&cmd_ret); + + return 0; +} + +static void hikp_roce_trp_print(uint8_t total_block_num, + const uint32_t *offset, const uint32_t *data) +{ + uint32_t i; + + printf("**************TRP INFO*************\n"); + for (i = 0; i < total_block_num; i++) + printf("[0x%08X] : 0x%08X\n", offset[i], data[i]); + printf("***********************************\n"); +} + +static void hikp_roce_trp_execute(struct major_cmd_ctrl *self) +{ + struct roce_trp_head res_head; + uint32_t *offset_start = NULL; + uint32_t *data_start = NULL; + uint8_t total_block_num; + uint32_t *offset = NULL; + uint32_t *data = NULL; + uint32_t block_id; + size_t data_size; + uint32_t times; + uint32_t i; + + block_id = 0; + if (g_roce_trp_param_t.bank_enter_flag) { + self->err_no = hikp_roce_trp_bank_check(); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid bank number!"); + return; + } + } + self->err_no = hikp_roce_trp_get_total_data_num(&res_head, &offset, &data, &block_id); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "get the first roce_trp block dfx fail."); + hikp_roce_trp_reg_data_free(&offset, &data); + return; + } + total_block_num = res_head.total_block_num; + res_head.total_block_num = res_head.total_block_num - res_head.cur_block_num; + offset_start = offset; + data_start = data; + if (res_head.total_block_num) { + times = res_head.total_block_num / ROCE_HIKP_TRP_REG_NUM + 1; + for (i = 0; i < times; i++) { + offset = offset + res_head.cur_block_num; + data = data + res_head.cur_block_num; + data_size = res_head.total_block_num * sizeof(uint32_t); + self->err_no = hikp_roce_trp_get_next_data(&res_head, &offset, + &data, &block_id, data_size); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "get multiple roce_trp block dfx fail."); + hikp_roce_trp_reg_data_free(&offset_start, &data_start); + return; + } + } + } + hikp_roce_trp_print(total_block_num, offset_start, data_start); + hikp_roce_trp_reg_data_free(&offset_start, &data_start); +} + +static void cmd_roce_trp_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_trp_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_trp_help); + cmd_option_register("-i", "--interface", true, hikp_roce_trp_target); + cmd_option_register("-b", "--bank", true, hikp_roce_trp_bank_get); + cmd_option_register("-m", "--module", true, hikp_roce_trp_module_select); +} + +HIKP_CMD_DECLARE("roce_trp", "get roce_trp registers information", cmd_roce_trp_init); diff --git a/net/roce/roce_trp/hikp_roce_trp.h b/net/roce/roce_trp/hikp_roce_trp.h new file mode 100644 index 0000000..db58216 --- /dev/null +++ b/net/roce/roce_trp/hikp_roce_trp.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 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_ROCE_TRP_H__ +#define __HIKP_ROCE_TRP_H__ + +#include "hikp_net_lib.h" + +#define TRP_DIV_NUM_T 4 +#define ROCE_HIKP_TRP_REG_NUM 29 +#define MAX_TRP_MODULE_NAME_LEN 20 +#define ROCE_TRP_HANDLE(x) \ + { \ + #x, x \ + } +#define TRP_MAX_BANK_NUM 0x3 +#define PAYL_MAX_BANK_NUM 0x1 +#define GAC_MAX_BANK_NUM 0x1 +#define PER_TRP_DATA_NUM 2 + +struct roce_trp_req_param { + struct bdf_t bdf; + uint32_t bank_id; + uint32_t block_id; +}; + +struct cmd_roce_trp_param_t { + uint32_t sub_cmd; + uint32_t bank_id; + uint8_t bank_enter_flag; + struct tool_target target; +}; + +struct roce_trp_head { + uint8_t total_block_num; + uint8_t cur_block_num; + uint16_t rsvd; +}; + +struct roce_trp_res { + uint32_t offset[ROCE_HIKP_TRP_REG_NUM]; + uint32_t data[ROCE_HIKP_TRP_REG_NUM]; +}; + +struct roce_trp_res_param { + uint32_t block_id; + struct roce_trp_head head; + struct roce_trp_res reg_data; +}; + +struct roce_trp_module { + uint8_t module_name[MAX_TRP_MODULE_NAME_LEN]; + uint32_t sub_cmd_code; +}; + +enum roce_trp_type { + TRP_RX = 1, + GEN_AC, + PAYL, + COMMON, +}; + +#endif /* __HIKP_ROCE_TRP_H__ */ diff --git a/net/roce/roce_tsp/hikp_roce_tsp.c b/net/roce/roce_tsp/hikp_roce_tsp.c new file mode 100644 index 0000000..5d06ede --- /dev/null +++ b/net/roce/roce_tsp/hikp_roce_tsp.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2022 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 "hikp_roce_tsp.h" + +static struct cmd_roce_tsp_param_t g_roce_tsp_param_t = { 0 }; +static struct roce_tsp_module g_roce_tsp_module[] = { + TSP_HANDLE(COMMON), + TSP_HANDLE(TDP), + TSP_HANDLE(TGP_TMP), +}; + +static int hikp_roce_tsp_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0"); + printf(" %s, %-25s %s\n", "-m", "--module=", + "this is necessary param COMMON/TDP/TGP_TMP"); + printf(" %s, %-25s %s\n", "-c", "--clear=", "clear TDP registers"); + printf(" %s, %-25s %s\n", "-b", "--bank=", + "[option]set which bank to read. (default 0) COMMON : 0~7\n TGP_TMP: 0~3\n "); + printf("\n"); + + return 0; +} + +static int hikp_roce_tsp_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_roce_tsp_param_t.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_roce_tsp_module_select(struct major_cmd_ctrl *self, const char *argv) +{ + bool is_found; + uint32_t i; + + for (i = 0; i < HIKP_ARRAY_SIZE(g_roce_tsp_module); i++) { + is_found = strncmp(argv, (const char *)g_roce_tsp_module[i].module_name, + sizeof(g_roce_tsp_module[i].module_name)) == 0; + if (is_found) { + g_roce_tsp_param_t.sub_cmd_code = g_roce_tsp_module[i].sub_cmd_code; + return 0; + } + } + snprintf(self->err_str, sizeof(self->err_str), "Invalid module param!"); + self->err_no = -EINVAL; + + return -EINVAL; +} + +static int hikp_roce_tsp_bank_get(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t temp; + + self->err_no = string_toui(argv, &temp); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "get roce_tsp bank param failed."); + return self->err_no; + } + + g_roce_tsp_param_t.bank_enter_flag = 1; + g_roce_tsp_param_t.bank_id = temp; + return 0; +} + +static int hikp_roce_tsp_bank_check(void) +{ + uint32_t temp; + + temp = g_roce_tsp_param_t.bank_id; + switch (g_roce_tsp_param_t.sub_cmd_code) { + case (COMMON): + if ((temp > MAX_TSP_BANK_NUM) || temp < 0) + return -EINVAL; + break; + case (TGP_TMP): + if ((temp > MAX_TGP_TMP_BANK_NUM) || temp < 0) + return -EINVAL; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int hikp_roce_tsp_clear_set(struct major_cmd_ctrl *self, const char *argv) +{ + g_roce_tsp_param_t.reset_flag = 1; + + return 0; +} + +static int hikp_roce_tsp_clear_module_check(void) +{ + if (g_roce_tsp_param_t.sub_cmd_code == TDP) + return 0; + + return -EINVAL; +} + +static int hikp_roce_tsp_get_data(struct hikp_cmd_ret **cmd_ret, + struct roce_tsp_req_param req_data, uint32_t sub_cmd_code) +{ + struct hikp_cmd_header req_header = { 0 }; + + if (g_roce_tsp_param_t.sub_cmd_code == 0) { + printf("please enter module name: -m/--modlue\n"); + return -EINVAL; + } + hikp_cmd_init(&req_header, ROCE_MOD, GET_ROCEE_TSP_CMD, sub_cmd_code); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (*cmd_ret == NULL) { + printf("hikptool roce_tsp cmd_ret malloc failed\n"); + return -EIO; + } + + return 0; +} + +static void hikp_roce_tsp_print(uint32_t total_block_num, + const uint32_t *offset, const uint32_t *data) +{ + uint32_t i; + + printf("**************TSP INFO*************\n"); + for (i = 0; i < total_block_num; i++) + printf("[0x%08X] : 0x%08X\n", offset[i], data[i]); + printf("***********************************\n"); +} + +static void hikp_roce_tsp_execute(struct major_cmd_ctrl *self) +{ + struct roce_tsp_res_param *roce_tsp_res; + struct roce_tsp_req_param req_data; + struct hikp_cmd_ret *cmd_ret; + int ret; + + if (g_roce_tsp_param_t.reset_flag) { + self->err_no = hikp_roce_tsp_clear_module_check(); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "roce_tsp clear function module selection error."); + return; + } + } + + if (g_roce_tsp_param_t.bank_enter_flag) { + self->err_no = hikp_roce_tsp_bank_check(); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "Invalid bank number!"); + return; + } + } + req_data.bdf = g_roce_tsp_param_t.target.bdf; + req_data.reset_flag = g_roce_tsp_param_t.reset_flag; + req_data.bank_id = g_roce_tsp_param_t.bank_id; + ret = hikp_roce_tsp_get_data(&cmd_ret, req_data, g_roce_tsp_param_t.sub_cmd_code); + if (ret < 0) { + self->err_no = ret; + return; + } + + roce_tsp_res = (struct roce_tsp_res_param *)cmd_ret->rsp_data; + hikp_roce_tsp_print(roce_tsp_res->total_block_num, + roce_tsp_res->reg_data.offset, roce_tsp_res->reg_data.data); + + free(cmd_ret); + cmd_ret = NULL; +} + +static void cmd_roce_tsp_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_roce_tsp_execute; + + cmd_option_register("-h", "--help", false, hikp_roce_tsp_help); + cmd_option_register("-i", "--interface", true, hikp_roce_tsp_target); + cmd_option_register("-m", "--module", true, hikp_roce_tsp_module_select); + cmd_option_register("-b", "--bank", true, hikp_roce_tsp_bank_get); + cmd_option_register("-c", "--clear", false, hikp_roce_tsp_clear_set); +} + +HIKP_CMD_DECLARE("roce_tsp", "get or clear roce_tsp registers information", cmd_roce_tsp_init); diff --git a/net/roce/roce_tsp/hikp_roce_tsp.h b/net/roce/roce_tsp/hikp_roce_tsp.h new file mode 100644 index 0000000..ae864ba --- /dev/null +++ b/net/roce/roce_tsp/hikp_roce_tsp.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 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_ROCE_TSP_H__ +#define __HIKP_ROCE_TSP_H__ + +#include "hikp_net_lib.h" + +#define ROCE_HIKP_TSP_REG_NUM 29 +#define TSP_PER_REG_NUM 2 +#define MAX_TSP_MODULE_NAME_LEN 20 +#define MAX_TSP_BANK_NUM 0x7 +#define MAX_TGP_TMP_BANK_NUM 0x3 +#define TSP_HANDLE(x) \ + { \ + #x, x \ + } + +struct cmd_roce_tsp_param_t { + uint32_t sub_cmd_code; + uint32_t bank_id; + uint8_t reset_flag; + uint8_t bank_enter_flag; + struct tool_target target; +}; + +struct roce_tsp_req_param { + struct bdf_t bdf; + uint8_t reset_flag; + uint32_t bank_id; +}; + +struct roce_trp_res_data { + uint32_t offset[ROCE_HIKP_TSP_REG_NUM]; + uint32_t data[ROCE_HIKP_TSP_REG_NUM]; +}; + +struct roce_tsp_res_param { + uint32_t total_block_num; + struct roce_trp_res_data reg_data; +}; + +struct roce_tsp_module { + uint8_t module_name[MAX_TSP_MODULE_NAME_LEN]; + uint32_t sub_cmd_code; +}; + +enum roce_tsp_sub_cmd_code { + COMMON = 1, + TDP, + TGP_TMP, +}; + +#endif /* __HIKP_ROCE_TSP_H__ */ -- Gitee From 530393d8c55a60919041cd2b434c18ba17102048 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:29:31 +0800 Subject: [PATCH 11/14] support querying SoCIP module information support dump register function for SoCIP module Signed-off-by: fengsheng (cherry picked from commit 7c630f196cd70277ab48bfd99afd9cb0296e4154) --- CMakeLists.txt | 1 + socip/hikp_socip.h | 49 +++++++++++ socip/hikp_socip_dumpreg.c | 167 +++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 socip/hikp_socip.h create mode 100644 socip/hikp_socip_dumpreg.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a51ba3..2ad9386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ file(GLOB_RECURSE HIKPTOOL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sata/*.c ${CMAKE_CURRENT_SOURCE_DIR}/serdes/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/socip/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tool_lib/*.c ${CMAKE_CURRENT_SOURCE_DIR}/hikp_init_main.c ) diff --git a/socip/hikp_socip.h b/socip/hikp_socip.h new file mode 100644 index 0000000..c98f136 --- /dev/null +++ b/socip/hikp_socip.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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_SOCIP_H__ +#define __HIKP_SOCIP_H__ + +#include + +/*************************************************** + hikptool socip module +****************************************************/ + +/* hikptool socip command code */ +enum { + // socip.dumpreg + HIKP_SOCIP_CMD_DUMPREG = 1, +}; + +/* hikptool socip sub command code */ +enum { + // socip.dumpreg.i2c + HIKP_SOCIP_SUBCMD_DUMPREG_I2C = 1, + // socip.dumpreg.gpio + HIKP_SOCIP_SUBCMD_DUMPREG_GPIO = 2, + // socip.dumpreg.spi + HIKP_SOCIP_SUBCMD_DUMPREG_SPI = 3, + // socip.dumpreg.sfc + HIKP_SOCIP_SUBCMD_DUMPREG_SFC = 4, + // socip.dumpreg.btc + HIKP_SOCIP_SUBCMD_DUMPREG_BTC = 5, +}; + +// dumpreg.request +struct socip_dump_reg_req_data_t { + uint8_t chip_id; + uint8_t die_id; + uint8_t controller_id; +}; + +#endif /* __HIKP_SOCIP_H__ */ diff --git a/socip/hikp_socip_dumpreg.c b/socip/hikp_socip_dumpreg.c new file mode 100644 index 0000000..088f5dd --- /dev/null +++ b/socip/hikp_socip_dumpreg.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2022 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 "hikp_socip.h" +#include "tool_lib.h" +#include "tool_cmd.h" +#include "hikptdev_plug.h" + +enum { + CHIP_ID_INDEX = 0, + DIE_ID_INDEX = 1, + MODULE_ID_INDEX = 2, + CONTROLLER_ID_INDEX = 3, +}; +#define SOCIP_DUMP_REG_PARAM_NUM 4 + +struct dump_reg_param_t { + uint8_t val; + bool is_vaild; +}; + +static const char *g_param_desc[SOCIP_DUMP_REG_PARAM_NUM] = { + "chip id", + "die id", + "module id", + "controller id", +}; + +static struct dump_reg_param_t g_dump_reg_param[SOCIP_DUMP_REG_PARAM_NUM] = {0}; + +static int cmd_socip_dump_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, + "-c -d -m -i "); + printf("\n %s\n", self->cmd_ptr->help_info); + printf("\n Options:\n\n"); + printf(" -h, %-15s %s\n", "--help", "the help info"); + printf(" -c, %-15s %s\n", "--chip id", "the chip id"); + printf(" -d, %-15s %s\n", "--die id", "the die id"); + printf(" -m, %-15s %s\n", "--module id", "e.g. 1:i2c 2:gpio 3:spi 4:sfc 5:btc"); + printf(" -i, %-15s %s\n", "--controller id", + "e.g. while the module is i2c, 0:i2c0 1:i2c1 ..."); + + return 0; +} + +static int get_param(struct major_cmd_ctrl *self, const char *argv, uint32_t index) +{ + struct dump_reg_param_t *param = &g_dump_reg_param[index]; + + if (string_toub(argv, ¶m->val)) { + snprintf(self->err_str, sizeof(self->err_str), "%s=%s\n", + g_param_desc[index], argv); + self->err_no = -EINVAL; + return -EINVAL; + } + param->is_vaild = true; + + return 0; +} + +static int cmd_chip_id(struct major_cmd_ctrl *self, const char *argv) +{ + return get_param(self, argv, CHIP_ID_INDEX); +} + +static int cmd_die_id(struct major_cmd_ctrl *self, const char *argv) +{ + return get_param(self, argv, DIE_ID_INDEX); +} + +static int cmd_module_id(struct major_cmd_ctrl *self, const char *argv) +{ + return get_param(self, argv, MODULE_ID_INDEX); +} + +static int cmd_controller_id(struct major_cmd_ctrl *self, const char *argv) +{ + return get_param(self, argv, CONTROLLER_ID_INDEX); +} + +static bool check_socip_dumpreg_param(void) +{ + struct dump_reg_param_t *param = &g_dump_reg_param[0]; + bool ret = true; + uint32_t i; + + for (i = 0; i < HIKP_ARRAY_SIZE(g_dump_reg_param); i++) { + if (!param->is_vaild) { + ret = false; + HIKP_ERROR_PRINT("%s is not set\n", g_param_desc[i]); + } + param++; + } + + return ret; +} + +static void dump_reg_info(const uint32_t *reg_data, uint32_t data_num) +{ +#define ONE_LINE_PRINT_DATA_NUM 4 + struct dump_reg_param_t *param = &g_dump_reg_param[0]; + uint32_t i; + + for (i = 0; i < data_num; i++) { + if (!(i % ONE_LINE_PRINT_DATA_NUM)) { + if (i) + printf("\n"); + printf("%08x:", i); // print offset + } + + printf("%08x ", reg_data[i]); + } + printf("\n"); +} + +static void hikp_socip_dumpreg_execute(struct major_cmd_ctrl *self) +{ + struct dump_reg_param_t *param = &g_dump_reg_param[0]; + struct hikp_cmd_header req_header = {0}; + struct socip_dump_reg_req_data_t req_data = {0}; + struct hikp_cmd_ret *cmd_ret; + + if (!check_socip_dumpreg_param()) { + cmd_socip_dump_help(self, NULL); + return; + } + + req_data.chip_id = param[CHIP_ID_INDEX].val; + req_data.die_id = param[DIE_ID_INDEX].val; + req_data.controller_id = param[CONTROLLER_ID_INDEX].val; + hikp_cmd_init(&req_header, SOCIP_MOD, HIKP_SOCIP_CMD_DUMPREG, param[MODULE_ID_INDEX].val); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + if (!cmd_ret) { + HIKP_ERROR_PRINT("hikp_cmd_alloc\n"); + return; + } + + dump_reg_info(&cmd_ret->rsp_data[0], cmd_ret->rsp_data_num); + free(cmd_ret); + cmd_ret = NULL; +} + +static void cmd_socip_dump_reg_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_socip_dumpreg_execute; + + cmd_option_register("-h", "--help", false, cmd_socip_dump_help); + cmd_option_register("-c", "--chip", true, cmd_chip_id); + cmd_option_register("-d", "--die", true, cmd_die_id); + cmd_option_register("-m", "--module", true, cmd_module_id); + cmd_option_register("-i", "--controller", true, cmd_controller_id); +} + +HIKP_CMD_DECLARE("socip_dumpreg", "Dump SoCIP registers", cmd_socip_dump_reg_init); -- Gitee From 59093d465e45cf050aee93069da913a815d65451 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:30:47 +0800 Subject: [PATCH 12/14] support querying NIC module information querying information about the NIC module, including hardware SSU/PPP/IGU_EGU/MASTER/TXDMA/BIOS_COMMON/RCB/NCSI module statistics, firmware logs, and PF hardware resource information. Signed-off-by: cjx_2021 (cherry picked from commit e05c70e1ff25feef7c6d62df39ba5ff9460cf996) --- net/nic/nic_dfx/hikp_nic_dfx.c | 365 +++++++++++++++++++++++++++++++ net/nic/nic_dfx/hikp_nic_dfx.h | 141 ++++++++++++ net/nic/nic_info/hikp_nic_info.c | 317 +++++++++++++++++++++++++++ net/nic/nic_info/hikp_nic_info.h | 73 +++++++ net/nic/nic_log/hikp_nic_log.c | 212 ++++++++++++++++++ net/nic/nic_log/hikp_nic_log.h | 41 ++++ 6 files changed, 1149 insertions(+) create mode 100644 net/nic/nic_dfx/hikp_nic_dfx.c create mode 100644 net/nic/nic_dfx/hikp_nic_dfx.h create mode 100644 net/nic/nic_info/hikp_nic_info.c create mode 100644 net/nic/nic_info/hikp_nic_info.h create mode 100644 net/nic/nic_log/hikp_nic_log.c create mode 100644 net/nic/nic_log/hikp_nic_log.h diff --git a/net/nic/nic_dfx/hikp_nic_dfx.c b/net/nic/nic_dfx/hikp_nic_dfx.c new file mode 100644 index 0000000..3584493 --- /dev/null +++ b/net/nic/nic_dfx/hikp_nic_dfx.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2022 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 "hikp_net_lib.h" +#include "hikp_nic_dfx.h" + +struct nic_dfx_param g_dfx_param = { 0 }; + +static const struct dfx_module_cmd g_dfx_module_parse[] = { + {"SSU", SSU_DFX_REG_DUMP}, + {"IGU_EGU", IGU_EGU_DFX_REG_DUMP}, + {"PPP", PPP_DFX_REG_DUMP}, + {"NCSI", NCSI_DFX_REG_DUMP}, + {"BIOS", BIOS_COMM_DFX_REG_DUMP}, + {"RCB", RCB_DFX_REG_DUMP}, + {"TXDMA", TXDMA_DFX_REG_DUMP}, + {"MASTER", MASTER_DFX_REG_DUMP}, +}; + +static const struct dfx_type_parse g_dfx_type_parse[] = { + {INCORRECT_REG_TYPE, WIDTH_32_BIT, "INCORRECT TYPE"}, + {TYPE_32_RX_ERROR_STATS, WIDTH_32_BIT, "32 bit RX error statistics"}, + {TYPE_32_RX_DROP_STATS, WIDTH_32_BIT, "32 bit RX drop statistics"}, + {TYPE_32_RX_NORMAL_STATS, WIDTH_32_BIT, "32 bit RX statistics"}, + {TYPE_32_TX_ERROR_STATS, WIDTH_32_BIT, "32 bit TX error statistics"}, + {TYPE_32_TX_DROP_STATS, WIDTH_32_BIT, "32 bit TX drop statistics"}, + {TYPE_32_TX_NORMAL_STATS, WIDTH_32_BIT, "32 bit TX statistics"}, + {TYPE_32_ERROR_STATUS, WIDTH_32_BIT, "32 bit error status"}, + {TYPE_32_RUNNING_STATUS, WIDTH_32_BIT, "32 bit running status"}, + {TYPE_32_CFG_STATUS, WIDTH_32_BIT, "32 bit config status"}, + {TYPE_32_RX_PORT_ERROR_STATS, WIDTH_32_BIT, "32 bit RX port error statistics"}, + {TYPE_32_RX_PORT_DROP_STATS, WIDTH_32_BIT, "32 bit RX port drop statistics"}, + {TYPE_32_RX_PORT_NORMAL_STATS, WIDTH_32_BIT, "32 bit RX port statistics"}, + {TYPE_32_TX_PORT_ERROR_STATS, WIDTH_32_BIT, "32 bit TX port error statistics"}, + {TYPE_32_TX_PORT_DROP_STATS, WIDTH_32_BIT, "32 bit TX port drop statistics"}, + {TYPE_32_TX_PORT_NORMAL_STATS, WIDTH_32_BIT, "32 bit TX port statistics"}, + {TYPE_32_PORT_ERROR_STATUS, WIDTH_32_BIT, "32 bit port error status"}, + {TYPE_32_PORT_RUNNING_STATUS, WIDTH_32_BIT, "32 bit port running status"}, + {TYPE_32_PORT_CFG_STATUS, WIDTH_32_BIT, "32 bit port config status"}, + {TYPE_32_COMM_STATS, WIDTH_32_BIT, "32 bit common statistics"}, + {TYPE_32_COMM_DROP_STATS, WIDTH_32_BIT, "32 bit common drop statistics"}, + {TYPE_32_COMM_ERROR_STATS, WIDTH_32_BIT, "32 bit common error statistics"}, + {TYPE_64_RX_ERROR_STATS, WIDTH_64_BIT, "64 bit RX error statistics"}, + {TYPE_64_RX_DROP_STATS, WIDTH_64_BIT, "64 bit RX drop statistics"}, + {TYPE_64_RX_NORMAL_STATS, WIDTH_64_BIT, "64 bit RX statistics"}, + {TYPE_64_TX_ERROR_STATS, WIDTH_64_BIT, "64 bit TX error statistics"}, + {TYPE_64_TX_DROP_STATS, WIDTH_64_BIT, "64 bit TX drop statistics"}, + {TYPE_64_TX_NORMAL_STATS, WIDTH_64_BIT, "64 bit TX statistics"}, + {TYPE_64_RX_PORT_ERROR_STATS, WIDTH_64_BIT, "64 bit RX port error statistics"}, + {TYPE_64_RX_PORT_DROP_STATS, WIDTH_64_BIT, "64 bit RX port drop statistics"}, + {TYPE_64_RX_PORT_NORMAL_STATS, WIDTH_64_BIT, "64 bit RX port statistics"}, + {TYPE_64_TX_PORT_ERROR_STATS, WIDTH_64_BIT, "64 bit TX port error statistics"}, + {TYPE_64_TX_PORT_DROP_STATS, WIDTH_64_BIT, "64 bit TX port drop statistics"}, + {TYPE_64_TX_PORT_NORMAL_STATS, WIDTH_64_BIT, "64 bit TX port statistics"}, + {TYPE_64_COMM_STATS, WIDTH_64_BIT, "64 bit common statistics"}, + {TYPE_64_COMM_DROP_STATS, WIDTH_64_BIT, "64 bit common drop statistics"}, + {TYPE_64_COMM_ERROR_STATS, WIDTH_64_BIT, "64 bit common error statistics"}, + {TYPE_64_TX_PF_ERROR_STATS, WIDTH_64_BIT, "64 bit TX pf error statistics"}, + {TYPE_64_TX_PF_DROP_STATS, WIDTH_64_BIT, "64 bit TX pf drop statistics"}, + {TYPE_64_TX_PF_NORMAL_STATS, WIDTH_64_BIT, "64 bit TX pf statistics"}, +}; + +static void dfx_help_info(const struct major_cmd_ctrl *self) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", "device target, e.g. eth0~7"); + printf(" %s\n", " [-m/--module SSU/IGU_EGU/PPP/NCSI/BIOS/RCB/TXDMA/MASTER] :" + "this is necessary param\n"); +} + +static int hikp_cmd_dfx_help(struct major_cmd_ctrl *self, const char *argv) +{ + dfx_help_info(self); + return 0; +} + +static int hikp_nic_cmd_dfx_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_dfx_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_dfx_get_blk(struct hikp_cmd_ret **cmd_ret, + uint32_t blk_id, uint32_t sub_cmd_code) +{ + struct nic_dfx_req_para req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + + req_data.bdf = g_dfx_param.target.bdf; + req_data.block_id = blk_id; + hikp_cmd_init(&req_header, NIC_MOD, GET_DFX_INFO_CMD, sub_cmd_code); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + + return hikp_rsp_normal_check(*cmd_ret); +} + +static int hikp_nic_get_first_blk_dfx(struct nic_dfx_rsp_head_t *rsp_head, uint32_t **reg_data, + uint32_t *max_dfx_size, uint32_t *version) +{ + struct nic_dfx_rsp_t *dfx_rsp = NULL; + struct hikp_cmd_ret *cmd_ret; + int ret; + + ret = hikp_nic_dfx_get_blk(&cmd_ret, 0, g_dfx_param.sub_cmd_code); + if (ret < 0) + return ret; + + dfx_rsp = (struct nic_dfx_rsp_t *)(cmd_ret->rsp_data); + *version = cmd_ret->version; + *rsp_head = dfx_rsp->rsp_head; + if (rsp_head->total_blk_num == 0) { + /* if total block number is zero, set total type number to zero anyway */ + rsp_head->total_type_num = 0; + goto err_out; + } + *max_dfx_size = (uint32_t)(rsp_head->total_blk_num * MAX_DFX_DATA_NUM * sizeof(uint32_t)); + *reg_data = (uint32_t *)calloc(1, *max_dfx_size); + if (*reg_data == NULL) { + HIKP_ERROR_PRINT("malloc log memory 0x%x failed.\n", *max_dfx_size); + ret = -ENOMEM; + goto err_out; + } + + if (rsp_head->cur_blk_size > *max_dfx_size) { + free(*reg_data); + *reg_data = NULL; + HIKP_ERROR_PRINT("blk0 reg_data copy size error, data size: 0x%x, max size: 0x%x\n", + rsp_head->cur_blk_size, *max_dfx_size); + ret = -EINVAL; + goto err_out; + } + memcpy(*reg_data, dfx_rsp->reg_data, rsp_head->cur_blk_size); + + *max_dfx_size -= (uint32_t)rsp_head->cur_blk_size; +err_out: + free(cmd_ret); + cmd_ret = NULL; + + return ret; +} + +static int hikp_nic_get_blk_dfx(struct nic_dfx_rsp_head_t *rsp_head, uint32_t blk_id, + uint32_t *reg_data, uint32_t *max_dfx_size) +{ + struct nic_dfx_rsp_t *dfx_rsp = NULL; + struct hikp_cmd_ret *cmd_ret; + int ret; + + ret = hikp_nic_dfx_get_blk(&cmd_ret, blk_id, g_dfx_param.sub_cmd_code); + if (ret < 0) + return ret; + + dfx_rsp = (struct nic_dfx_rsp_t *)(cmd_ret->rsp_data); + *rsp_head = dfx_rsp->rsp_head; + if (rsp_head->cur_blk_size > *max_dfx_size) { + HIKP_ERROR_PRINT("blk%u reg_data copy size error, " + "data size: 0x%x, max size: 0x%x\n", + blk_id, rsp_head->cur_blk_size, *max_dfx_size); + free(cmd_ret); + cmd_ret = NULL; + return -EINVAL; + } + memcpy(reg_data, dfx_rsp->reg_data, rsp_head->cur_blk_size); + *max_dfx_size -= (uint32_t)rsp_head->cur_blk_size; + free(cmd_ret); + cmd_ret = NULL; + + return 0; +} + +static int cmd_dfx_module_select(struct major_cmd_ctrl *self, const char *argv) +{ + size_t arr_size = HIKP_ARRAY_SIZE(g_dfx_module_parse); + bool is_found; + size_t i; + + for (i = 0; i < arr_size; i++) { + is_found = strncmp(argv, (const char *)g_dfx_module_parse[i].module_name, + sizeof(g_dfx_module_parse[i].module_name)) == 0; + if (is_found) { + g_dfx_param.sub_cmd_code = g_dfx_module_parse[i].sub_cmd_code; + g_dfx_param.module_idx = i; + g_dfx_param.flag |= MODULE_SET_FLAG; + return 0; + } + } + dfx_help_info(self); + snprintf(self->err_str, sizeof(self->err_str), "-m/--module param error!!!"); + self->err_no = -EINVAL; + + return -EINVAL; +} + +static void hikp_nic_dfx_print_b32(uint32_t num, uint32_t *reg_data) +{ + uint32_t word_num = num * WORD_NUM_PER_REG; + uint16_t offset; + uint32_t value; + uint32_t index; + uint32_t i; + + for (i = 0, index = 1; i < word_num; i = i + WORD_NUM_PER_REG, index++) { + offset = (uint16_t)HI_GET_BITFIELD(reg_data[i], 0, DFX_REG_ADDR_MASK); + value = reg_data[i + 1]; + printf("%03u: 0x%04x\t0x%08x\n", index, offset, value); + } +} + +static void hikp_nic_dfx_print_b64(uint32_t num, uint32_t *reg_data) +{ + uint32_t word_num = num * WORD_NUM_PER_REG; + uint16_t offset; + uint64_t value; + uint32_t index; + uint32_t i; + + for (i = 0, index = 1; i < word_num; i = i + WORD_NUM_PER_REG, index++) { + offset = (uint16_t)HI_GET_BITFIELD(reg_data[i], 0, DFX_REG_ADDR_MASK); + value = (uint64_t)reg_data[i + 1] | + (HI_GET_BITFIELD((uint64_t)reg_data[i], DFX_REG_VALUE_OFF, + DFX_REG_VALUE_MASK) << BIT_NUM_OF_WORD); + printf("%03u: 0x%04x\t0x%016lx\n", index, offset, value); + } +} + +static bool is_type_found(uint16_t type_id, uint32_t *index) +{ + size_t arr_size = HIKP_ARRAY_SIZE(g_dfx_type_parse); + size_t i; + + for (i = 0; i < arr_size; i++) { + if (g_dfx_type_parse[i].type_id == type_id) { + *index = i; + return true; + } + } + + return false; +} + +static void hikp_nic_dfx_print_type_head(uint8_t type_id, uint8_t *last_type_id) +{ + uint32_t index = 0; + + if (type_id != *last_type_id) { + printf("-----------------------------------------------------\n"); + if (is_type_found(type_id, &index)) + printf("type name: %s\n\n", g_dfx_type_parse[index].type_name); + else + HIKP_WARN_PRINT("type name: unknown type, type id is %u\n\n", type_id); + + *last_type_id = type_id; + } +} + +static void hikp_nic_dfx_print(const struct nic_dfx_rsp_head_t *rsp_head, uint32_t *reg_data) +{ + struct nic_dfx_type_head *type_head; + uint8_t last_type_id = 0; + uint32_t *ptr = reg_data; + uint8_t i; + + printf("****************** module %s reg dump start ********************\n", + g_dfx_module_parse[g_dfx_param.module_idx].module_name); + for (i = 0; i < rsp_head->total_type_num; i++) { + type_head = (struct nic_dfx_type_head *)ptr; + if (type_head->type_id == INCORRECT_REG_TYPE) { + HIKP_ERROR_PRINT("No.%u type is incorrect reg type\n", i + 1u); + break; + } + hikp_nic_dfx_print_type_head(type_head->type_id, &last_type_id); + ptr++; + if (type_head->bit_width == WIDTH_32_BIT) { + hikp_nic_dfx_print_b32((uint32_t)type_head->reg_num, ptr); + } else if (type_head->bit_width == WIDTH_64_BIT) { + hikp_nic_dfx_print_b64((uint32_t)type_head->reg_num, ptr); + } else { + HIKP_ERROR_PRINT("type%u's bit width error.\n", type_head->type_id); + break; + } + ptr += (uint32_t)type_head->reg_num * WORD_NUM_PER_REG; + } + printf("################### ====== dump end ====== ######################\n"); +} + +static void hikp_nic_dfx_cmd_execute(struct major_cmd_ctrl *self) +{ + struct nic_dfx_rsp_head_t rsp_head = { 0 }; + struct nic_dfx_rsp_head_t tmp_head = { 0 }; + uint32_t *reg_data = NULL; + uint32_t real_reg_size; + uint32_t max_dfx_size; + uint32_t version; + uint32_t i; + int ret; + + if (!(g_dfx_param.flag & MODULE_SET_FLAG)) { + self->err_no = -EINVAL; + snprintf(self->err_str, sizeof(self->err_str), "Please specify a module."); + dfx_help_info(self); + return; + } + self->err_no = hikp_nic_get_first_blk_dfx(&rsp_head, ®_data, &max_dfx_size, &version); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "get the first block dfx fail."); + return; + } + real_reg_size = (uint32_t)rsp_head.cur_blk_size; + for (i = 1; i < rsp_head.total_blk_num; i++) { + self->err_no = hikp_nic_get_blk_dfx(&tmp_head, i, + reg_data + (real_reg_size / sizeof(uint32_t)), + &max_dfx_size); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), + "getting block%u reg fail.", i); + free(reg_data); + return; + } + real_reg_size += (uint32_t)tmp_head.cur_blk_size; + memset(&tmp_head, 0, sizeof(struct nic_dfx_rsp_head_t)); + } + + printf("DFX cmd version: 0x%x\n\n", version); + hikp_nic_dfx_print((const struct nic_dfx_rsp_head_t *)&rsp_head, reg_data); + free(reg_data); +} + +static void cmd_nic_dfx_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_dfx_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_cmd_dfx_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_dfx_target); + cmd_option_register("-m", "--module", true, cmd_dfx_module_select); +} + +HIKP_CMD_DECLARE("nic_dfx", "dump dfx info of hardware", cmd_nic_dfx_init); diff --git a/net/nic/nic_dfx/hikp_nic_dfx.h b/net/nic/nic_dfx/hikp_nic_dfx.h new file mode 100644 index 0000000..3f23b59 --- /dev/null +++ b/net/nic/nic_dfx/hikp_nic_dfx.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2022 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_NIC_DFX_H__ +#define __HIKP_NIC_DFX_H__ + +#include "hikp_net_lib.h" + +enum nic_dfx_cmd_type { + SSU_DFX_REG_DUMP = 0, + IGU_EGU_DFX_REG_DUMP = 1, + PPP_DFX_REG_DUMP = 2, + NCSI_DFX_REG_DUMP = 3, + BIOS_COMM_DFX_REG_DUMP = 4, + RCB_DFX_REG_DUMP = 5, + TXDMA_DFX_REG_DUMP = 6, + MASTER_DFX_REG_DUMP = 7, + INVALID_MODULE = 0xFFFFFFFF, +}; + +enum nic_dfx_reg_type { + INCORRECT_REG_TYPE = 0, + TYPE_32_RX_ERROR_STATS = 1, + TYPE_32_RX_DROP_STATS = 2, + TYPE_32_RX_NORMAL_STATS = 3, + TYPE_32_TX_ERROR_STATS = 4, + TYPE_32_TX_DROP_STATS = 5, + TYPE_32_TX_NORMAL_STATS = 6, + TYPE_32_RX_PORT_ERROR_STATS = 7, + TYPE_32_RX_PORT_DROP_STATS = 8, + TYPE_32_RX_PORT_NORMAL_STATS = 9, + TYPE_32_TX_PORT_ERROR_STATS = 10, + TYPE_32_TX_PORT_DROP_STATS = 11, + TYPE_32_TX_PORT_NORMAL_STATS = 12, + TYPE_32_ERROR_STATUS = 13, + TYPE_32_RUNNING_STATUS = 14, + TYPE_32_CFG_STATUS = 15, + TYPE_32_PORT_ERROR_STATUS = 16, + TYPE_32_PORT_RUNNING_STATUS = 17, + TYPE_32_PORT_CFG_STATUS = 18, + TYPE_32_COMM_STATS = 19, + TYPE_32_COMM_DROP_STATS = 20, + TYPE_32_COMM_ERROR_STATS = 21, + TYPE_64_RX_ERROR_STATS = 30, + TYPE_64_RX_DROP_STATS = 31, + TYPE_64_RX_NORMAL_STATS = 32, + TYPE_64_TX_ERROR_STATS = 33, + TYPE_64_TX_DROP_STATS = 34, + TYPE_64_TX_NORMAL_STATS = 35, + TYPE_64_RX_PORT_ERROR_STATS = 36, + TYPE_64_RX_PORT_DROP_STATS = 37, + TYPE_64_RX_PORT_NORMAL_STATS = 38, + TYPE_64_TX_PORT_ERROR_STATS = 39, + TYPE_64_TX_PORT_DROP_STATS = 40, + TYPE_64_TX_PORT_NORMAL_STATS = 41, + TYPE_64_COMM_STATS = 42, + TYPE_64_COMM_DROP_STATS = 43, + TYPE_64_COMM_ERROR_STATS = 44, + TYPE_64_TX_PF_ERROR_STATS = 45, + TYPE_64_TX_PF_DROP_STATS = 46, + TYPE_64_TX_PF_NORMAL_STATS = 47, + TYPE_INVALID = 255, +}; + +#define MAX_MODULE_NAME_LEN 20 +struct dfx_module_cmd { + uint8_t module_name[MAX_MODULE_NAME_LEN]; + uint32_t sub_cmd_code; +}; + +#define MAX_TYPE_NAME_LEN 40 + +enum nic_dfx_reg_width { + WIDTH_32_BIT = 32, + WIDTH_64_BIT = 64, +}; + +struct dfx_type_parse { + uint8_t type_id; + uint8_t bit_width; + uint8_t type_name[MAX_TYPE_NAME_LEN]; +}; + +struct nic_dfx_type_head { + uint8_t type_id; + uint8_t bit_width; + uint8_t reg_num; + uint8_t flag; +}; + +struct nic_dfx_req_para { + struct bdf_t bdf; + uint8_t block_id; +}; + +struct nic_dfx_param { + struct tool_target target; + uint32_t sub_cmd_code; + uint8_t module_idx; + uint8_t flag; +}; + +#define MODULE_SET_FLAG 0x1 + +#define MAX_DFX_DATA_NUM 59 + +/********************************************************* + * All registers are returned as key-value pairs, and divided + * into three groups of data. + * 1. 32bit regs: R0 bit0~bit15: offset, R1 bit0~bit31: value + * 2. 64bit regs: R0 bit0~bit15: offset, R0 bit16~bit31 high16 value, R1 bit0~bit31: low32 value + *********************************************************/ +#define DFX_REG_VALUE_OFF 16 +#define DFX_REG_VALUE_MASK 0xFFFF +#define DFX_REG_ADDR_MASK 0xFFFF + +#define WORD_NUM_PER_REG 2 +#define BIT_NUM_OF_WORD 32 +struct nic_dfx_rsp_head_t { + uint8_t total_blk_num; + uint8_t total_type_num; + uint8_t cur_blk_size; + uint8_t rsvd; +}; + +struct nic_dfx_rsp_t { + struct nic_dfx_rsp_head_t rsp_head; + uint32_t reg_data[MAX_DFX_DATA_NUM]; +}; + +#endif diff --git a/net/nic/nic_info/hikp_nic_info.c b/net/nic/nic_info/hikp_nic_info.c new file mode 100644 index 0000000..1853d95 --- /dev/null +++ b/net/nic/nic_info/hikp_nic_info.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2022 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 "hikp_net_lib.h" +#include "hikp_nic_info.h" + +static struct nic_info_param g_info_param = { 0 }; + +static int hikp_nic_cmd_get_info_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i "); + 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", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + + printf("\n"); + + return 0; +} + +static int hikp_nic_cmd_get_info_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_info_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + g_info_param.have_interface = true; + + return 0; +} + +static int hikp_nic_get_hw_info(struct hikp_cmd_ret **cmd_ret) +{ + struct nic_info_req_para req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + + req_data.bdf = g_info_param.target.bdf; + hikp_cmd_init(&req_header, NIC_MOD, GET_CHIP_INFO_CMD, CHIP_INFO_DUMP); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + + return hikp_rsp_normal_check(*cmd_ret); +} + +static int hikp_nic_get_curr_die_info(void) +{ + struct nic_info_rsp_t *info_rsp = NULL; + struct hikp_cmd_ret *cmd_ret; + int ret; + + ret = hikp_nic_get_hw_info(&cmd_ret); + if (ret != 0) { + HIKP_ERROR_PRINT("Get chip info fail.\n"); + return ret; + } + info_rsp = (struct nic_info_rsp_t *)(cmd_ret->rsp_data); + g_info_param.info = *info_rsp; + free(cmd_ret); + cmd_ret = NULL; + + ret = get_revision_id_by_bdf(&g_info_param.target.bdf, g_info_param.revision_id); + if (ret != 0) { + HIKP_ERROR_PRINT("Getting revision fail.\n"); + return ret; + } + ret = get_numvfs_by_bdf(&g_info_param.target.bdf, &g_info_param.numvfs); + if (ret != 0) + HIKP_ERROR_PRINT("Getting numvfs fail, ret = %d.\n", ret); + ret = get_dev_name_by_bdf(&g_info_param.target.bdf, g_info_param.target.dev_name); + if ((ret != 0) && (ret != -ENOENT)) { + HIKP_ERROR_PRINT("Getting dev name fail.\n"); + return ret; + } + + return 0; +} + +static void hikp_nic_info_print_cur_pf(const struct bdf_t *bdf) +{ + struct tool_target *pf_target = &g_info_param.target; + struct tool_target target = { 0 }; + uint8_t pf_id = bdf->fun_id; + uint8_t i; + int ret; + + printf("Current function: pf%u\n", pf_id); + printf("\t%-16s %s\n", "pf mode:", + g_info_param.info.pf_info[pf_id].pf_mode ? "X86" : "ARM"); + printf("\t%-16s %04x:%02x:%02x.%u\n", "bdf id:", + bdf->domain, bdf->bus_id, bdf->dev_id, bdf->fun_id); + printf("\t%-16s %u\n", "mac id:", g_info_param.info.pf_info[pf_id].mac_id); + printf("\t%-16s %s\n", "mac type:", + g_info_param.info.pf_info[pf_id].mac_type ? "ROH" : "ETH"); + printf("\t%-16s %u\n", "func_num:", g_info_param.info.pf_info[pf_id].func_num); + printf("\t%-16s %u\n", "tqp_num:", g_info_param.info.pf_info[pf_id].tqp_num); + printf("\t%-16s 0x%x\n", "pf_cap_flag:", g_info_param.info.pf_info[pf_id].pf_cap_flag); + if (pf_target->dev_name[0] != 0) { + printf("\t%-16s %s\n", "dev name:", pf_target->dev_name); + for (i = 0; i < g_info_param.numvfs; i++) { + ret = get_vf_dev_info_by_pf_dev_name((const char *)pf_target->dev_name, + &target, i); + if (ret == -ENOENT) + continue; + + if (ret != 0) { + HIKP_ERROR_PRINT("Getting vf's dev name fail.\n"); + return; + } + printf("\t pf%u-vf%u: %s <-> %04x:%02x:%02x.%u\n", pf_id, i, + target.dev_name, target.bdf.domain, target.bdf.bus_id, + target.bdf.dev_id, target.bdf.fun_id); + } + } + printf("\n"); +} + +static void hikp_nic_info_print_cur_die(void) +{ + uint8_t i; + + printf("Current die(chip%u-die%u) info:\n", + g_info_param.info.chip_id, g_info_param.info.die_id); + printf("revision id: %s", g_info_param.revision_id); + printf("mac mode: %u\n", g_info_param.info.mac_mode); + printf("pf number: %u\n", g_info_param.info.pf_num); + printf("pf's capability flag: 0x%x\n", g_info_param.info.cap_flag); + printf("pf's attributes and capabilities:\n"); + printf("%-16s", "pf id:"); + for (i = 0; i < g_info_param.info.pf_num; i++) + printf("pf%u\t", i); + + printf("\n%-16s", "pf mode:"); + for (i = 0; i < g_info_param.info.pf_num; i++) + printf("%s\t", g_info_param.info.pf_info[i].pf_mode ? "X86" : "ARM"); + + printf("\n%-16s", "mac id:"); + for (i = 0; i < g_info_param.info.pf_num; i++) + printf("mac%u\t", g_info_param.info.pf_info[i].mac_id); + + printf("\n%-16s", "mac type:"); + for (i = 0; i < g_info_param.info.pf_num; i++) + printf("%s\t", g_info_param.info.pf_info[i].mac_type ? "ROH" : "ETH"); + + printf("\n%-16s", "func num:"); + for (i = 0; i < g_info_param.info.pf_num; i++) + printf("%u\t", g_info_param.info.pf_info[i].func_num); + + printf("\n%-16s", "tqp num:"); + for (i = 0; i < g_info_param.info.pf_num; i++) + printf("%u\t", g_info_param.info.pf_info[i].tqp_num); + + printf("\n\n"); +} + +static bool is_bus_id_accessed(void) +{ + uint8_t i; + + for (i = 0; i < g_info_param.accessed_die_num; i++) { + if (g_info_param.accessed_bus_id[i] == g_info_param.target.bdf.bus_id) + return true; + } + g_info_param.accessed_bus_id[i] = g_info_param.target.bdf.bus_id; + + return false; +} + +static int hikp_nic_get_and_print_curr_die(int sockfd, struct tool_target *target, + char *revision_id, struct ifaddrs *ifa_node) +{ + int ret; + + memset(target, 0, sizeof(struct tool_target)); + memset(revision_id, 0, MAX_PCI_ID_LEN + 1); + + if (strlen(ifa_node->ifa_name) >= IFNAMSIZ) { + HIKP_ERROR_PRINT("parameter of device name is too long.\n"); + return -EINVAL; + } + strncpy(target->dev_name, ifa_node->ifa_name, sizeof(target->dev_name)); + target->dev_name[sizeof(target->dev_name) - 1] = '\0'; + if (!is_dev_valid_and_special(sockfd, target) || + is_bus_id_accessed()) { + return 0; + } + ret = hikp_nic_get_curr_die_info(); + if (ret != 0) + return ret; + hikp_nic_info_print_cur_die(); + g_info_param.accessed_die_num++; + + return 0; +} + +static int hikp_nic_traverse_all_hns3_dev_and_get_info(void) +{ + struct tool_target *target = &g_info_param.target; + char *revision_id = g_info_param.revision_id; + struct ifaddrs *ifa_node; + struct ifaddrs *ifa_lst; + int sockfd; + int ret; + + sockfd = hikp_net_creat_sock(); + if (sockfd < MIN_SOCKFD) { + HIKP_ERROR_PRINT("creat sockfd failed, sockfd is %d.\n", sockfd); + return -EIO; + } + ret = getifaddrs(&ifa_lst); + if (ret < 0) { + HIKP_ERROR_PRINT("getifaddrs failed.\n"); + goto sock_out; + } + for (ifa_node = ifa_lst; ifa_node != NULL; ifa_node = ifa_node->ifa_next) { + if (ifa_node->ifa_addr == NULL) + continue; + + if (ifa_node->ifa_addr->sa_family != AF_PACKET) + continue; + + ret = hikp_nic_get_and_print_curr_die(sockfd, target, revision_id, ifa_node); + if (ret != 0) + break; + } + freeifaddrs(ifa_lst); +sock_out: + close(sockfd); + + return ret; +} + +static void hikp_nic_info_print_cur_vf(const struct bdf_t *bdf) +{ + struct tool_target target = { 0 }; + int ret; + + printf("Current function is vf:\n"); + printf("\t%-16s %04x:%02x:%02x.%u\n", "vf bdf id:", + bdf->domain, bdf->bus_id, bdf->dev_id, bdf->fun_id); + ret = get_dev_name_by_bdf(&g_info_param.target.bdf, g_info_param.target.dev_name); + if ((ret != 0) && (ret != -ENOENT)) { + HIKP_ERROR_PRINT("Getting dev name fail.\n"); + return; + } + if (g_info_param.target.dev_name[0] != 0) + printf("\t%-16s %s\n", "vf dev name:", g_info_param.target.dev_name); + + if (ret == 0) { + ret = get_pf_dev_info_by_vf_dev_name((const char *)g_info_param.target.dev_name, + &target); + if ((ret != 0) && (ret != -ENOENT)) { + HIKP_ERROR_PRINT("Getting pf dev name fail.\n"); + return; + } + printf("Belong to:\n"); + printf("\t%-16s pf%u\n", "pf id:", target.bdf.fun_id); + printf("\t%-16s %04x:%02x:%02x.%u\n", "pf bdf id:", target.bdf.domain, + target.bdf.bus_id, target.bdf.dev_id, target.bdf.fun_id); + printf("\t%-16s %s\n", "pf dev name:", target.dev_name); + } +} + +static void hikp_nic_info_cmd_execute(struct major_cmd_ctrl *self) +{ + struct bdf_t *bdf = &g_info_param.target.bdf; + + if (!g_info_param.have_interface) { + self->err_no = hikp_nic_traverse_all_hns3_dev_and_get_info(); + if (self->err_no != 0) + snprintf(self->err_str, sizeof(self->err_str), + "traverse all hns3 dev fail."); + return; + } + if (bdf->dev_id != 0) { + hikp_nic_info_print_cur_vf(&g_info_param.target.bdf); + return; + } + self->err_no = hikp_nic_get_curr_die_info(); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "get current die info fail."); + return; + } + hikp_nic_info_print_cur_pf(&g_info_param.target.bdf); + hikp_nic_info_print_cur_die(); +} + +static void cmd_nic_get_info_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_info_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_cmd_get_info_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_get_info_target); +} + +HIKP_CMD_DECLARE("nic_info", "show basic info of network!", cmd_nic_get_info_init); diff --git a/net/nic/nic_info/hikp_nic_info.h b/net/nic/nic_info/hikp_nic_info.h new file mode 100644 index 0000000..7419209 --- /dev/null +++ b/net/nic/nic_info/hikp_nic_info.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 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_NIC_INFO_H__ +#define __HIKP_NIC_INFO_H__ + +#include "hikp_net_lib.h" + +#define MAX_DIE_NUM 32 + +struct nic_info_req_para { + struct bdf_t bdf; +}; + +struct nic_info_pf_info { + uint8_t pf_mode; + uint8_t mac_id; + uint8_t mac_type; + uint8_t rsv1; + uint16_t func_num; + uint16_t tqp_num; + /********************************************** + * pf_cap_flag: + * bit0 == ncsi enable status + * bit1~bit31 == reserved + **********************************************/ + uint32_t pf_cap_flag; + uint32_t rsvd[3]; +}; + +enum nic_info_cmd_type { + CHIP_INFO_DUMP = 0, +}; + +#define NIC_INFO_RSVD_NUM 10 +struct nic_info_rsp_t { + uint8_t mac_mode; + uint8_t chip_id; + uint8_t die_id; + uint8_t pf_num; + /********************************************** + * cap_flag: + * bit0 == sgpio enable status + * bit1 == tm enable status + * bit2 == torus enable status + * bit3~bit31 == reserved + **********************************************/ + uint32_t cap_flag; + uint32_t rsv1[NIC_INFO_RSVD_NUM]; + struct nic_info_pf_info pf_info[HIKP_MAX_PF_NUM]; +}; + +struct nic_info_param { + struct tool_target target; + struct nic_info_rsp_t info; + char revision_id[MAX_PCI_ID_LEN + 1]; + uint8_t accessed_bus_id[MAX_DIE_NUM]; + uint8_t accessed_die_num; + uint8_t numvfs; + bool have_interface; +}; + +#endif diff --git a/net/nic/nic_log/hikp_nic_log.c b/net/nic/nic_log/hikp_nic_log.c new file mode 100644 index 0000000..527f9e9 --- /dev/null +++ b/net/nic/nic_log/hikp_nic_log.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2022 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 "hikp_net_lib.h" +#include "op_logs.h" +#include "hikp_nic_log.h" + +static struct log_param g_log_param = { 0 }; + +static int hikp_nic_cmd_log_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s %s\n", self->cmd_ptr->name, "-i \n"); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit"); + printf(" %s, %-25s %s\n", "-i", "--interface=", + "device target or bdf id, e.g. eth0~7 or 0000:35:00.0"); + + return 0; +} + +static int hikp_nic_cmd_log_target(struct major_cmd_ctrl *self, const char *argv) +{ + self->err_no = tool_check_and_get_valid_bdf_id(argv, &(g_log_param.target)); + if (self->err_no != 0) { + snprintf(self->err_str, sizeof(self->err_str), "Unknown device %s.", argv); + return self->err_no; + } + + return 0; +} + +static int hikp_nic_write_data_to_file(uint8_t *data, uint32_t len) +{ + uint8_t file_path[OP_LOG_FILE_PATH_MAXLEN] = { 0 }; + uint8_t file_name[MAX_LOG_NAME_LEN] = { 0 }; + size_t write_cnt; + FILE *fp = NULL; + int ret; + + ret = generate_file_name(file_name, MAX_LOG_NAME_LEN, (const unsigned char *)"m7"); + if (ret < 0) + return ret; + + ret = snprintf((char *)file_path, sizeof(file_path), HIKP_LOG_DIR_PATH"%s", file_name); + if (ret < 0) { + HIKP_ERROR_PRINT("creat log file path fail.\n"); + return -EIO; + } + (void)remove((const char *)file_path); + fp = fopen((char *)file_path, "w+"); + if (fp == NULL) { + HIKP_ERROR_PRINT("open %s failed, errno is %d\n", file_path, errno); + return -errno; + } + write_cnt = fwrite(data, 1, len, fp); + if (write_cnt != len) + HIKP_ERROR_PRINT("write %s failed, write cnt %lu.\n", file_path, write_cnt); + + printf("dump m7 log completed, log file: %s.\n", file_path); + (void)chmod((char *)file_path, 0440); + (void)fclose(fp); + return 0; +} + +static int hikp_nic_get_blk_log(struct hikp_cmd_ret **cmd_ret, uint32_t blk_id) +{ + struct nic_log_req_para req_data = { 0 }; + struct hikp_cmd_header req_header = { 0 }; + + req_data.bdf = g_log_param.target.bdf; + req_data.block_id = blk_id; + hikp_cmd_init(&req_header, NIC_MOD, GET_FW_LOG_INFO_CMD, FW_LOG_DUMP); + *cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + return hikp_rsp_normal_check(*cmd_ret); +} + +static int hikp_nic_get_first_blk_info(uint32_t *total_blk_num, + uint32_t *cur_blk_size, uint8_t **log_data) +{ + struct nic_log_rsp_data *log_rsp = NULL; + struct hikp_cmd_ret *cmd_ret; + uint32_t log_size; + int ret; + + ret = hikp_nic_get_blk_log(&cmd_ret, 0); + if (ret < 0) + return ret; + + log_rsp = (struct nic_log_rsp_data *)(cmd_ret->rsp_data); + log_size = (uint32_t)(log_rsp->total_blk_num * MAX_LOG_DATA_NUM * sizeof(uint32_t)); + if (log_size < log_rsp->cur_blk_size) { + HIKP_ERROR_PRINT("log size must bigger than current block size.\n"); + ret = -EINVAL; + goto err_out; + } + *log_data = (uint8_t *)calloc(1, log_size); + if (*log_data == NULL) { + HIKP_ERROR_PRINT("malloc log memory 0x%x failed.", log_size); + ret = -ENOMEM; + goto err_out; + } + + *total_blk_num = (uint32_t)log_rsp->total_blk_num; + *cur_blk_size = (uint32_t)log_rsp->cur_blk_size; + memcpy(*log_data, log_rsp->log_data, log_rsp->cur_blk_size); +err_out: + free(cmd_ret); + cmd_ret = NULL; + + return ret; +} + +static int hikp_nic_get_log_info(uint32_t blk_id, uint32_t *cur_blk_size, uint8_t *log_data, + uint32_t max_log_size, uint32_t *blk_num) +{ + struct nic_log_rsp_data *log_rsp = NULL; + struct hikp_cmd_ret *cmd_ret; + int ret; + + ret = hikp_nic_get_blk_log(&cmd_ret, blk_id); + if (ret) + return ret; + + log_rsp = (struct nic_log_rsp_data *)(cmd_ret->rsp_data); + *cur_blk_size = (uint32_t)log_rsp->cur_blk_size; + *blk_num = (uint32_t)log_rsp->total_blk_num; + if (max_log_size < *cur_blk_size) { + HIKP_ERROR_PRINT("log size must bigger than current block(%u) size.\n", blk_id); + ret = -EINVAL; + goto err_out; + } + memcpy(log_data, log_rsp->log_data, log_rsp->cur_blk_size); +err_out: + free(cmd_ret); + cmd_ret = NULL; + + return ret; +} + +static int hikp_nic_dump_m7_log(struct major_cmd_ctrl *self) +{ + uint32_t real_log_size = 0; + uint32_t total_blk_num = 0; + uint8_t *log_data = NULL; + uint32_t cur_blk_size; + uint32_t max_log_size; + uint32_t blk_num; + uint32_t i; + + self->err_no = hikp_nic_get_first_blk_info(&total_blk_num, &cur_blk_size, &log_data); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), "get the first block log fail."); + return self->err_no; + } + max_log_size = (uint32_t)(total_blk_num * MAX_LOG_DATA_NUM * sizeof(uint32_t) - + cur_blk_size); + real_log_size += cur_blk_size; + for (i = 1; i < total_blk_num; i++) { + self->err_no = hikp_nic_get_log_info(i, &cur_blk_size, log_data + real_log_size, + max_log_size, &blk_num); + if (self->err_no) { + snprintf(self->err_str, sizeof(self->err_str), + "getting block%u log fail.", i); + free(log_data); + return self->err_no; + } + max_log_size -= cur_blk_size; + real_log_size += cur_blk_size; + if (blk_num == 0 || cur_blk_size == 0) + break; + } + self->err_no = hikp_nic_write_data_to_file(log_data, real_log_size); + free(log_data); + + return self->err_no; +} + +static void hikp_nic_log_cmd_execute(struct major_cmd_ctrl *self) +{ + self->err_no = hikp_nic_dump_m7_log(self); +} + +static void cmd_nic_log_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = hikp_nic_log_cmd_execute; + + cmd_option_register("-h", "--help", false, hikp_nic_cmd_log_help); + cmd_option_register("-i", "--interface", true, hikp_nic_cmd_log_target); +} + +HIKP_CMD_DECLARE("nic_log", "dump m7 log info.", cmd_nic_log_init); diff --git a/net/nic/nic_log/hikp_nic_log.h b/net/nic/nic_log/hikp_nic_log.h new file mode 100644 index 0000000..ff2bb87 --- /dev/null +++ b/net/nic/nic_log/hikp_nic_log.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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_NIC_LOG_H__ +#define __HIKP_NIC_LOG_H__ + +#include "hikp_net_lib.h" + +#define MAX_LOG_NAME_LEN 128 +#define MAX_LOG_DATA_NUM 59 + +enum nic_log_cmd_type { + FW_LOG_DUMP = 0, +}; + +struct nic_log_req_para { + struct bdf_t bdf; + uint32_t block_id; +}; + +struct nic_log_rsp_data { + uint16_t total_blk_num; + uint16_t cur_blk_size; + uint32_t log_data[MAX_LOG_DATA_NUM]; +}; + +struct log_param { + struct tool_target target; +}; + +#endif -- Gitee From db8edaf2ffc2b6f14a6cf0aa203c874fb3adf512 Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:32:58 +0800 Subject: [PATCH 13/14] support querying PCIe module information queries PCIe module information, including trace, link status, and PCIe port division. Signed-off-by: hesiyuan (cherry picked from commit 968c3c4960981fda8aeec756d149131a69828b1c) --- CMakeLists.txt | 1 + pcie/func_lib/osal/os_common.c | 29 ++ pcie/func_lib/osal/os_common.h | 41 ++ pcie/func_lib/pcie_func/pcie_common.h | 50 ++ pcie/func_lib/pcie_func/pcie_link_ltssm.c | 282 ++++++++++ pcie/func_lib/pcie_func/pcie_link_ltssm.h | 55 ++ pcie/func_lib/pcie_func/pcie_reg_dump.c | 490 ++++++++++++++++++ pcie/func_lib/pcie_func/pcie_reg_dump.h | 44 ++ pcie/func_lib/pcie_func/pcie_reg_read.c | 102 ++++ pcie/func_lib/pcie_func/pcie_reg_read.h | 60 +++ pcie/func_lib/pcie_func/pcie_statistics.c | 166 ++++++ pcie/func_lib/pcie_func/pcie_statistics.h | 120 +++++ pcie/usr_cmd/cmd_analysis/pcie_cmd_dumpreg.c | 131 +++++ pcie/usr_cmd/cmd_analysis/pcie_cmd_info.c | 139 +++++ pcie/usr_cmd/cmd_analysis/pcie_cmd_reg_read.c | 151 ++++++ pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c | 158 ++++++ .../usr_cmd/cmd_analysis/pcie_tools_include.h | 32 ++ pcie/usr_cmd/interface/pcie_common_api.c | 36 ++ pcie/usr_cmd/interface/pcie_common_api.h | 40 ++ 19 files changed, 2127 insertions(+) create mode 100644 pcie/func_lib/osal/os_common.c create mode 100644 pcie/func_lib/osal/os_common.h create mode 100644 pcie/func_lib/pcie_func/pcie_common.h create mode 100644 pcie/func_lib/pcie_func/pcie_link_ltssm.c create mode 100644 pcie/func_lib/pcie_func/pcie_link_ltssm.h create mode 100644 pcie/func_lib/pcie_func/pcie_reg_dump.c create mode 100644 pcie/func_lib/pcie_func/pcie_reg_dump.h create mode 100644 pcie/func_lib/pcie_func/pcie_reg_read.c create mode 100644 pcie/func_lib/pcie_func/pcie_reg_read.h create mode 100644 pcie/func_lib/pcie_func/pcie_statistics.c create mode 100644 pcie/func_lib/pcie_func/pcie_statistics.h create mode 100644 pcie/usr_cmd/cmd_analysis/pcie_cmd_dumpreg.c create mode 100644 pcie/usr_cmd/cmd_analysis/pcie_cmd_info.c create mode 100644 pcie/usr_cmd/cmd_analysis/pcie_cmd_reg_read.c create mode 100644 pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c create mode 100644 pcie/usr_cmd/cmd_analysis/pcie_tools_include.h create mode 100644 pcie/usr_cmd/interface/pcie_common_api.c create mode 100644 pcie/usr_cmd/interface/pcie_common_api.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad9386..1d79a31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ file(GLOB_RECURSE HIKPTOOL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/cxl/*.c ${CMAKE_CURRENT_SOURCE_DIR}/net/*.c ${CMAKE_CURRENT_SOURCE_DIR}/ossl/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/pcie/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sas/*.c ${CMAKE_CURRENT_SOURCE_DIR}/sata/*.c ${CMAKE_CURRENT_SOURCE_DIR}/serdes/*.c diff --git a/pcie/func_lib/osal/os_common.c b/pcie/func_lib/osal/os_common.c new file mode 100644 index 0000000..3ebf10c --- /dev/null +++ b/pcie/func_lib/osal/os_common.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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 "os_common.h" + +void hilog(int pri, const char *module, const char *fun, int line, const char *fmt, ...) +{ + va_list ap; + (void)pri; + (void)module; + (void)fun; + (void)line; + + va_start(ap, fmt); + (void)vprintf(fmt, ap); + va_end(ap); +} diff --git a/pcie/func_lib/osal/os_common.h b/pcie/func_lib/osal/os_common.h new file mode 100644 index 0000000..480202c --- /dev/null +++ b/pcie/func_lib/osal/os_common.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 _OS_COMMON_H_ +#define _OS_COMMON_H_ + +enum { + HW_LOG_TIPS = 0, + HW_LOG_DBG, + HW_LOG_INFO, + HW_LOG_WARN, + HW_LOG_ERR +}; + +#define LOG_PCIE "[PCIE]" + +void hilog(int pri, const char *module, const char *fun, int line, const char *fmt, ...); + +#define Log(pri, module, fmt, args...) hilog(pri, module, __func__, __LINE__, fmt, ##args) + +#define Err(module, fmt, args...) hilog(HW_LOG_ERR, module, __func__, __LINE__, fmt, ##args) + +#define Warn(module, fmt, args...) hilog(HW_LOG_WARN, module, __func__, __LINE__, fmt, ##args) + +#define Info(module, fmt, args...) hilog(HW_LOG_INFO, module, __func__, __LINE__, fmt, ##args) + +#define Debug(module, fmt, args...) hilog(HW_LOG_DBG, module, __func__, __LINE__, fmt, ##args) + +#define Tips(module, fmt, args...) hilog(HW_LOG_TIPS, module, __func__, __LINE__, fmt, ##args) + +#endif diff --git a/pcie/func_lib/pcie_func/pcie_common.h b/pcie/func_lib/pcie_func/pcie_common.h new file mode 100644 index 0000000..434b4ed --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_common.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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 __PCIE_COMMON_H_ +#define __PCIE_COMMON_H_ + +/* PCIe command code */ +enum pcie_cmd_type { + PCIE_TRACE = 0, + PCIE_INFO = 1, + PCIE_DUMP = 2, + PCIE_REGRD = 3, +}; + +enum pcie_trace_cmd_type { + TRACE_HELP = 0, + TRACE_SHOW = 1, + TRACE_CLEAR = 2, + TRACE_INFO = 3, + TRACE_MODE = 4, +}; + +enum pcie_info_cmd_type { + INFO_HELP = 0, + INFO_DISTRIBUTION = 1, + INFO_ERR_STATE_SHOW = 2, + INFO_ERR_STATE_CLEAR = 3, +}; + +enum pcie_dump_cmd_type { + DUMPREG_HELP = 0, + DUMPREG_DUMP = 1, +}; + +enum pcie_reg_read_cmd_type { + REGRD_HELP = 0, + REGRD_READ = 1, +}; + +#endif diff --git a/pcie/func_lib/pcie_func/pcie_link_ltssm.c b/pcie/func_lib/pcie_func/pcie_link_ltssm.c new file mode 100644 index 0000000..d57688b --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_link_ltssm.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2022 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 "os_common.h" +#include "pcie_common.h" +#include "hikptdev_plug.h" +#include "pcie_link_ltssm.h" + +union ltssm_state_reg { + struct { + uint64_t ltssm_state : 6; /* [0:5] */ + uint64_t duration_counter : 4; /* [6:9] */ + uint64_t mac_rate : 2; /* [10:11] */ + uint64_t train_bit_map1 : 8; /* [12:19] */ + uint64_t rxl0s_st : 2; /* [20:21] */ + uint64_t any_change_pipe_req : 1; /* [22] */ + uint64_t rcv_eios : 1; /* [23] */ + uint64_t dl_retrain : 1; /* [24] */ + uint64_t all_phy_rxeleidle : 1; /* [25] */ + uint64_t directed_speed_change : 1; /* [26] */ + uint64_t any_det_eieos_ts : 1; /* [27] */ + uint64_t rxl0s_to_recovery : 1; /* [28] */ + uint64_t any_lane_rcv_speed_change : 1; /* [29] */ + uint64_t changed_speed_recovery : 1; /* [30] */ + uint64_t successful_speed_negotiation : 1; /* [31] */ + uint64_t train_bit_map2 : 16; /* [32:47] */ + uint64_t txdetrx : 16; /* [48: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; + 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_SHOW); + 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 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 ltssm trace num received from TF */ + *ltssm_num = cmd_ret->rsp_data[0]; + + if ((cmd_ret->rsp_data_num - 1) * sizeof(uint32_t) != (*ltssm_num) * sizeof(uint64_t)) { + Err("PCIe Base", "rsp data number check failed, rsp_data_num: %u, ltssm_num: %u.\n", + cmd_ret->rsp_data_num, *ltssm_num); + ret = -EINVAL; + goto free_cmd_ret; + } + + src_size = (*ltssm_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(ltssm_status, (cmd_ret->rsp_data + 1), src_size); + +free_cmd_ret: + free(cmd_ret); + + return ret; +} + +struct pcie_ltssm_num_string g_ltssm_string_table[] = { + {0x0, "ltssm_init"}, + {0x1, "ltssm_reset_pipe_afifo"}, + {0x2, "ltssm_detect_quiet"}, + {0x3, "ltssm_detect_active"}, + {0x4, "ltssm_detect_wait"}, + {0x5, "ltssm_detect_pwr_p0"}, + {0x6, "ltssm_poll_active"}, + {0x7, "ltssm_poll_config"}, + {0x8, "ltssm_poll_comp"}, + {0x9, "ltssm_config_lw_str"}, + {0xa, "ltssm_config_lw_acc"}, + {0xb, "ltssm_config_ln_wait"}, + {0xc, "ltssm_config_ln_acc"}, + {0xd, "ltssm_config_complete"}, + {0xe, "ltssm_config_idle1"}, + {0xf, "ltssm_config_idle2"}, + {0x10, "ltssm_l0"}, + {0x11, "ltssm_rx_l0s"}, + {0x14, "ltssm_tx_l0s_entry"}, + {0x15, "ltssm_tx_l0s_idle"}, + {0x16, "ltssm_tx_l0s_fts"}, + {0x17, "ltssm_l1"}, + {0x18, "ltssm_l2"}, + {0x19, "ltssm_tx_beacon_begin"}, + {0x1a, "ltssm_tx_beacon_end"}, + {0x30, "ltssm_tx_eios_st"}, + {0x31, "ltssm_chg_rate_gen1"}, + {0x32, "ltssm_change_power"}, + {0x33, "ltssm_hot_reset"}, + {0x34, "ltssm_disable_p1"}, + {0x35, "ltssm_disable_p2"}, + {0x38, "ltssm_loopback_entry"}, + {0x39, "ltssm_loopback_active"}, + {0x3a, "ltssm_loopback_exit"}, + {0x20, "ltssm_recovery_rcvlock"}, + {0x21, "ltssm_recovery_rcvcfg"}, + {0x22, "ltssm_recovery_speed"}, + {0x23, "ltssm_recovery_idle1"}, + {0x24, "ltssm_recovery_idle2"}, + {0x25, "ltssm_recovery_eq_p0"}, + {0x26, "ltssm_recovery_eq_p1"}, + {0x27, "ltssm_recovery_eq_p2"}, + {0x28, "ltssm_recovery_eq_p3"}, + {-1, "unknown"} /* end of array */ +}; + +static char *hisi_pcie_ltssm_string_get(uint32_t ltssm) +{ + int i = 0; + + while (g_ltssm_string_table[i].ltssm >= 0) { + if ((uint32_t)g_ltssm_string_table[i].ltssm != ltssm) { + i++; + continue; + } + break; + } + + return g_ltssm_string_table[i].ltssm_c; +} + +static int pcie_print_ltssm_trace(const uint64_t *ltssm_input, uint32_t ltssm_num) +{ + uint32_t i; + char *ltssm_c = NULL; + union ltssm_state_reg ltssm_val; + + if (ltssm_num > TRACER_DEPTH || ltssm_num == 0) { + Err("PCIe Base", "ltssm_num(%u) is over range or zero\n", ltssm_num); + return -EINVAL; + } + Info("PCIe Base", "ltssm tracer:\n"); + Info("PCIe Base", "\ttrace mode: %llx\n", *ltssm_input); + Info("PCIe Base", + "\tltssm[ii]: 63:48 47:32 31 30 29 28 27 26 25 24 23 22 21:" + "20 19:12 11:10 9:6 5:0 ltssm\n"); + for (i = 1; i < ltssm_num; i++) { + ltssm_val.val = ltssm_input[i]; + ltssm_c = hisi_pcie_ltssm_string_get((uint32_t)ltssm_val.bits.ltssm_state); + Info("PCIe Base", + "\tltssm[%02u]: 0x%04x %04x %x %x %x %x %x %x %x " + "%x %x %x %x %02x %x %x %02x %s\n", + i, + (uint32_t)ltssm_val.bits.txdetrx, + (uint32_t)ltssm_val.bits.train_bit_map2, + (uint32_t)ltssm_val.bits.successful_speed_negotiation, + (uint32_t)ltssm_val.bits.changed_speed_recovery, + (uint32_t)ltssm_val.bits.any_lane_rcv_speed_change, + (uint32_t)ltssm_val.bits.rxl0s_to_recovery, + (uint32_t)ltssm_val.bits.any_det_eieos_ts, + (uint32_t)ltssm_val.bits.directed_speed_change, + (uint32_t)ltssm_val.bits.all_phy_rxeleidle, + (uint32_t)ltssm_val.bits.dl_retrain, + (uint32_t)ltssm_val.bits.rcv_eios, + (uint32_t)ltssm_val.bits.any_change_pipe_req, + (uint32_t)ltssm_val.bits.rxl0s_st, + (uint32_t)ltssm_val.bits.train_bit_map1, + (uint32_t)ltssm_val.bits.mac_rate, + (uint32_t)ltssm_val.bits.duration_counter, + (uint32_t)ltssm_val.bits.ltssm_state, + ltssm_c); + } + + return 0; +} + +int pcie_ltssm_trace_show(uint32_t port_id) +{ + int ret; + uint32_t ltssm_num = 0; + uint64_t ltssm_st_save[TRACER_DEPTH]; + + ret = pcie_get_ltssm_trace(port_id, ltssm_st_save, <ssm_num); + if (ret) + return ret; + + return pcie_print_ltssm_trace(ltssm_st_save, ltssm_num); +} + +int pcie_ltssm_trace_mode_set(uint32_t port_id, uint32_t mode) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct pcie_trace_req_para req_data = { 0 }; + int ret; + + req_data.port_id = port_id; + req_data.trace_mode = mode; + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_TRACE, TRACE_MODE); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + free(cmd_ret); + + return ret; +} + +int pcie_ltssm_trace_clear(uint32_t port_id) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct pcie_trace_req_para req_data = { 0 }; + int ret; + + req_data.port_id = port_id; + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_TRACE, TRACE_CLEAR); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + free(cmd_ret); + + return ret; +} + +int pcie_ltssm_link_status_get(uint32_t port_id) +{ + uint32_t i; + union pcie_link_info reg_val; + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct pcie_trace_req_para req_data = { 0 }; + char *ltssm_sts; + int ret; + + req_data.port_id = port_id; + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_TRACE, TRACE_INFO); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) + goto free_cmd_ret; + + if (cmd_ret->rsp_data_num == 0) { + Err("PCIe Base", "rsp data number check failed, rsp_data_num: %u.\n", + cmd_ret->rsp_data_num); + ret = -EINVAL; + goto free_cmd_ret; + } + reg_val.u32 = cmd_ret->rsp_data[0]; + ltssm_sts = hisi_pcie_ltssm_string_get(reg_val.bits.mac_ltssm_st); + + Info(LOG_PCIE, "Port[%u] mac link information:\n", port_id); + Info(LOG_PCIE, " ltssm status: %s\n", ltssm_sts); + Info(LOG_PCIE, " speed: Gen%u\n", reg_val.bits.mac_cur_link_speed); + Info(LOG_PCIE, " width: X%u\n", reg_val.bits.mac_cur_link_width); + Info(LOG_PCIE, " link_up: %u\n", reg_val.bits.mac_link_up); + Info(LOG_PCIE, " lane_reverse: %u\n", reg_val.bits.lane_reverse); +free_cmd_ret: + free(cmd_ret); + + return ret; +} diff --git a/pcie/func_lib/pcie_func/pcie_link_ltssm.h b/pcie/func_lib/pcie_func/pcie_link_ltssm.h new file mode 100644 index 0000000..eb57ead --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_link_ltssm.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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 __PCIE_LINK_LTSSM_H_ +#define __PCIE_LINK_LTSSM_H_ + +#include "pcie_common_api.h" + +#define TRACE_STR_NUM 0x20 +#define TRACER_DEPTH 65 + +struct pcie_ltssm_num_string { + int ltssm; + char ltssm_c[TRACE_STR_NUM]; +}; + +struct pcie_trace_req_para { + uint32_t port_id; + uint32_t trace_mode; +}; + +union pcie_link_info { + /* Define the struct bits */ + struct { + uint32_t mac_cur_link_width : 6; /* [5..0] */ + uint32_t reserved_0 : 2; /* [7..6] */ + uint32_t mac_cur_link_speed : 4; /* [11..8] */ + uint32_t reserved_1 : 4; /* [15..12] */ + uint32_t mac_link_up : 1; /* [16] */ + uint32_t reserved_2 : 2; /* [18..17] */ + uint32_t lane_reverse : 1; /* [19] */ + uint32_t reserved_3 : 4; /* [23..20] */ + uint32_t mac_ltssm_st : 6; /* [29..24] */ + uint32_t reserved_4 : 2; /* [31..30] */ + } bits; + + uint32_t u32; +}; + +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); + +#endif diff --git a/pcie/func_lib/pcie_func/pcie_reg_dump.c b/pcie/func_lib/pcie_func/pcie_reg_dump.c new file mode 100644 index 0000000..7d91969 --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_reg_dump.c @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2022 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_lib.h" +#include "hikptdev_plug.h" +#include "os_common.h" +#include "pcie_common.h" +#include "pcie_reg_dump.h" + +int g_pcie_dumpreg_fd; + +struct pcie_dumpreg_info g_reg_table_tl[] = { + {0, "TL_ASPM_IDLE_CNT"}, + {0, "TL_ASPM_IDLE_EN"}, + {0, "TL_PM_DC_CTRL"}, + {0, "TL_PM_STATE"}, + {0, "TL_PM_UC_CTRL"}, + {0, "TL_ENTER_L0_CTRL"}, + {0, "TL_PM_TIMEOUT_CTRL"}, + {0, "TL_INT_STATUS0"}, + {0, "TL_INT_STATUS1"}, + {0, "TL_RX_POSTED_CREDIT_DF"}, + {0, "TL_RX_NON_POSTED_CREDIT_DF"}, + {0, "TL_RX_CPL_CREDIT_DF"}, + {0, "TL_RX_CDT_INI_UP_DF"}, + {0, "RX_ASYN_STONE_FIFO_STATUS"}, + {0, "TL_RX_ERR_STATUS"}, + {0, "TL_TX_VC0_P_FC_LEFT"}, + {0, "TL_TX_VC0_NP_FC_LEFT"}, + {0, "TL_TX_VC0_CPL_FC_LEFT"}, + {0, "TL_TX_VC1_P_FC_LEFT"}, + {0, "TL_TX_ORDER_P_NUM"}, + {0, "TL_TX_ORDER_NP_CPL_NUM"}, + {0, "TL_RX_VC0_POST_CREDIT_LEFT"}, + {0, "TL_RX_VC0_NONPOST_CREDIT_LEFT"}, + {0, "TL_RX_VC0_CPL_CREDIT_LEFT"}, + {0, "RX_RX_BUFFER_STATUS"}, + {0, "TL_RX_POSTED_CREDIT"}, + {0, "TL_RX_NON_POSTED_CREDIT"}, + {0, "TL_RX_CPL_CREDIT"}, + {0, "TL_RX_ERR_CNT"}, + {0, "TL_RX_NULL_CNT"}, + {0, "TL_RX_UR_TLP_CNT"}, + {0, "TL_RX_TOTAL_CNT"}, + {0, "TL_RX_RCV_PNP_CNT"}, + {0, "TL_RX_RCV_CPL_CNT"}, + {0, "TL_RX_POST_CNT"}, + {0, "TL_RX_NONPOST_CNT"}, + {0, "TL_RX_CPL_CNT"}, + {0, "TL_RX_LOC_TLP_CNT"}, + {0, "TL_RX_ERR_STATUS"}, + {0, "TL_CFGSPACE_BDF"}, +}; + +struct pcie_dumpreg_info g_reg_table_dl[] = { + {0, "DFX_LCRC_ERR_NUM"}, + {0, "DFX_DCRC_ERR_NUM"}, + {0, "DFX_FSM_STATE"}, + {0, "DL_INT_STATUS"}, + {0, "DFX_MAC_BP_TIMER"}, + {0, "DFX_RETRY_CNT"}, + {0, "DL_MAC_RETRAIN_CNT"}, + {0, "DFX_DLLP_RX_COUNT_NUM"}, + {0, "DFX_DLLP_TX_COUNT_NUM"}, + {0, "DFX_RX_NAK_COUNT"}, + {0, "DFX_RX_BAD_DLLP_TYPE"}, + {0, "DL_FC_INIT_ERR_STATUS"}, +}; + +struct pcie_dumpreg_info g_reg_table_mac[] = { + {0, "MAC_REQ_TX_LINK_NUM"}, + {0, "MAC_REG_MAC_INT_STATUS"}, + {0, "MAC_REG_MAC_INT_MASK"}, + {0, "MAC_REG_TEST_COUNTER"}, + {0, "MAC_REG_LINK_INFO"}, + {0, "MAC_REG_SYMBOL_UNLOCL_COUNTER"}, + {0, "MAC_REG_MAC_INT_RO"}, + {0, "MAC_REG_ENTER_L1L2_TIMEOUT_VAL"}, + {0, "MAC_PCS_RX_ERR_CNT"}, + {0, "MAC_RX_ERR_CHECK_EN"}, + {0, "MAC_TRACE_2BIT_ECC_CNT"}, + {0, "MAC_TRACE_1BIT_ECC_CNT"}, + {0, "MAC_LTSSM_TIMEOUT_ENABLE"}, + {0, "MAC_FRAMING_ERR_CNT"}, + {0, "MAC_FRAMING_ERR_CTRL"}, + {0, "MAC_LEAVE_L0_INFO"}, + {0, "MAC_INT_CE_NFE_SEL"}, + {0, "MAC_REG_NI_INT_RO"}, + {0, "MAC_REG_FE_INT_RO"}, + {0, "MAC_REG_CE_INT_RO"}, + {0, "MAC_REG_NFE_INT_RO"}, +}; + +struct pcie_dumpreg_info g_reg_table_pcs[] = { + {0, "SERDES_STATUS_RPT"}, + {0, "EBUF_STATUS"}, + {0, "GEN3_DEC_ENC_STATUS"}, + {0, "WAKE_STATUS"}, + {0, "RECV_DET_OR_PWR_CHAGE"}, + {0, "EQEVAL_STATUS"}, + {0, "LANE_INTR_STATUS"}, +}; + +struct pcie_dumpreg_info g_reg_table_iob_tx[] = { + {0, "IOB_TX_ECAM_BASE_ADDR_L"}, + {0, "IOB_TX_ECAM_BASE_ADDR_H"}, + {0, "IOB_TX_CXL_BASE_BUS_0"}, + {0, "IOB_TX_CXL_RCRB_BASE_L_0"}, + {0, "IOB_TX_CXL_RCRB_BASE_H_0"}, + {0, "IOB_TX_INT_STATUS0"}, + {0, "IOB_TX_INT_STATUS1"}, + {0, "IOB_TX_INT_STATUS2"}, + {0, "IOB_TX_INT_STATUS3"}, + {0, "IOB_TX_INT_STATUS4"}, + {0, "IOB_TX_INT_STATUS5"}, + {0, "IOB_TX_INT_RO0"}, + {0, "IOB_TX_INT_RO1"}, + {0, "IOB_TX_INT_RO2"}, + {0, "IOB_TX_INT_RO3"}, + {0, "IOB_TX_INT_RO4"}, + {0, "IOB_TX_INT_RO5"}, + {0, "IOB_TX_INT_SEVERITY0"}, + {0, "IOB_TX_INT_SEVERITY1"}, + {0, "IOB_TX_INT_SEVERITY2"}, + {0, "IOB_TX_INT_SEVERITY3"}, + {0, "IOB_TX_INT_SEVERITY4"}, + {0, "IOB_TX_INT_SEVERITY5"}, +}; + +struct pcie_dumpreg_info g_reg_table_iob_rx[] = { + {0, "IOB_RX_INT_STATUS"}, + {0, "IOB_RX_INT_RO"}, + {0, "IOB_RX_INT_SEVERITY"}, + {0, "IOB_RX_MSI_MSIX_CTRL_0"}, + {0, "IOB_RX_MSI_MSIX_ADDR_HIGH_0"}, + {0, "IOB_RX_MSI_MSIX_ADDR_LOW_0"}, +}; + +struct pcie_dumpreg_info g_reg_table_ap_glb[] = { + {0, "PCIE_ERR_MAPPING"}, + {0, "PCIE_CXL_ERR_MAPPING"}, + {0, "PCIE_CE_ENA"}, + {0, "PCIE_CE_MASK"}, + {0, "PCIE_UNF_ENA"}, + {0, "PCIE_UNF_MASK"}, + {0, "PCIE_UF_ENA"}, + {0, "PCIE_UF_MASK"}, + {0, "PCIE_CE_STATUS"}, + {0, "PCIE_UNF_STATUS"}, + {0, "PCIE_UF_STATUS"}, + {0, "PCIE_CXL_CE_ENA"}, + {0, "PCIE_CXL_CE_MASK"}, + {0, "PCIE_CXL_UNF_ENA"}, + {0, "PCIE_CXL_UNF_MASK"}, + {0, "PCIE_CXL_UF_ENA"}, + {0, "PCIE_CXL_UF_MASK"}, + {0, "PCIE_CXL_CE_STATUS"}, + {0, "PCIE_CXL_UNF_STATUS"}, + {0, "PCIE_CXL_UF_STATUS"}, + {0, "PCIE_MSI_MASK"}, + {0, "PCIE_MSI_STATUS"}, + {0, "PCIE_AP_NI_ENA"}, + {0, "PCIE_AP_CE_ENA"}, + {0, "PCIE_AP_UNF_ENA"}, + {0, "PCIE_AP_UF_ENA"}, + {0, "PCIE_AP_NI_MASK"}, + {0, "PCIE_AP_CE_MASK"}, + {0, "PCIE_AP_UNF_MASK"}, + {0, "PCIE_AP_UF_MASK"}, + {0, "PCIE_AP_NI_STATUS"}, + {0, "PCIE_AP_CE_STATUS"}, + {0, "PCIE_AP_UNF_STATUS"}, + {0, "PCIE_AP_UF_STATUS"}, + {0, "PCIE_CORE_NI_ENA"}, + {0, "PCIE_CORE_CE_ENA"}, + {0, "PCIE_CORE_UNF_ENA"}, + {0, "PCIE_CORE_UF_ENA"}, + {0, "PCIE_CORE_NI_MASK"}, + {0, "PCIE_CORE_CE_MASK"}, + {0, "PCIE_CORE_UNF_MASK"}, + {0, "PCIE_CORE_UF_MASK"}, + {0, "PCIE_CORE_NI_STATUS"}, + {0, "PCIE_CORE_CE_STATUS"}, + {0, "PCIE_CORE_UNF_STATUS"}, + {0, "PCIE_CORE_UF_STATUS"}, + {0, "PORT_INTX_MAPPING"}, + {0, "PORT_INTX_INTERRUPT_MODE"}, + {0, "PORT_INTX_ASSERT_MASK"}, + {0, "PORT_INTX_DEASSERT_MASK"}, + {0, "PORT_INTX_ASSERT_STATUS"}, + {0, "PORT_INTX_DEASSERT_STATUS"}, + {0, "AP_P2P_PORT_BITMAP_0"}, + {0, "AP_P2P_CTRL"}, + {0, "AP_P2P_INFO"}, + {0, "AP_PORT_EN"}, +}; + +struct pcie_dumpreg_info g_reg_table_core_glb[] = { + {0, "PORT_RESET"}, + {0, "PHY_RESET"}, + {0, "PORT_EN"}, + {0, "PORT_RESET_CFG"}, + {0, "GLB_PCIEC_MODE_SEL"}, + {0, "HILINK_INT_MASK"}, + {0, "HILINK_INT_RO"}, + {0, "HILINK_INT_STATUS"}, + {0, "CORE_INT_NI_MSK_0"}, + {0, "CORE_INT_NI_STATUS_0"}, + {0, "CORE_INT_NI_RO_0"}, + {0, "CORE_INT_NI_MSK_1"}, + {0, "CORE_INT_NI_STATUS_1"}, + {0, "CORE_INT_NI_RO_1"}, + {0, "CORE_INT_CE_MSK_0"}, + {0, "CORE_INT_CE_STATUS_0"}, + {0, "CORE_INT_CE_RO_0"}, + {0, "CORE_INT_CE_MSK_1"}, + {0, "CORE_INT_CE_STATUS_1"}, + {0, "CORE_INT_CE_RO_1"}, + {0, "CORE_INT_NFE_MSK_0"}, + {0, "CORE_INT_NFE_STATUS_0"}, + {0, "CORE_INT_NFE_RO_0"}, + {0, "CORE_INT_NFE_MSK_1"}, + {0, "CORE_INT_NFE_STATUS_1"}, + {0, "CORE_INT_NFE_RO_1"}, + {0, "CORE_INT_FE_MSK_0"}, + {0, "CORE_INT_FE_STATUS_0"}, + {0, "CORE_INT_FE_RO_0"}, + {0, "CORE_INT_FE_MSK_1"}, + {0, "CORE_INT_FE_STATUS_1"}, + {0, "CORE_INT_FE_RO_1"}, + {0, "CORE_INT_NI_MSK_2"}, + {0, "CORE_INT_NI_STATUS_2"}, + {0, "CORE_INT_NI_RO_2"}, + {0, "CORE_INT_CE_MSK_2"}, + {0, "CORE_INT_CE_STATUS_2"}, + {0, "CORE_INT_CE_RO_2"}, + {0, "CORE_INT_NFE_MSK_2"}, + {0, "CORE_INT_NFE_STATUS_2"}, + {0, "CORE_INT_NFE_RO_2"}, + {0, "CORE_INT_FE_MSK_2"}, + {0, "CORE_INT_FE_STATUS_2"}, + {0, "CORE_INT_FE_RO_2"}, +}; + +static int pcie_create_dumpreg_log_file(uint32_t port_id, uint32_t dump_level) +{ + char file_name[MAX_LOG_NAME_LEN + 1] = { 0 }; + char info_str[MAX_LOG_NAME_LEN + 1] = { 0 }; + int fd_file; + int ret; + + ret = snprintf(info_str, sizeof(info_str), "%s_port%u_level%u", + PCIE_DUMPREG_LOGFILE_NAME, port_id, dump_level); + if (ret < 0) + return -EINVAL; + + ret = generate_file_name((unsigned char *)file_name, MAX_LOG_NAME_LEN, + (const unsigned char *)info_str); + if (ret) + return -EINVAL; + + (void)remove((const char *)file_name); + /* Add write permission to the file */ + fd_file = open(file_name, O_RDWR | O_SYNC | O_CREAT, 0640); + if (fd_file < 0) { + Err("PCIe DUMPREG", "open %s failed.\n", file_name); + return -EPERM; + } + g_pcie_dumpreg_fd = fd_file; + + return 0; +} + +static int pcie_close_dumpreg_log_file(void) +{ + int ret; + + ret = fchmod(g_pcie_dumpreg_fd, 0440); + close(g_pcie_dumpreg_fd); + /* Revoke write permission of file */ + g_pcie_dumpreg_fd = -1; + + return ret; +} + +static void pcie_dumpreg_write_value_to_file(const char *reg_name, uint32_t val) +{ + char str[MAX_STR_LEN] = { 0 }; + ssize_t wr_ret; + int ret; + + ret = snprintf(str, sizeof(str), " %-40s : 0x%x\n", reg_name, val); + if (ret < 0 || ret >= sizeof(str)) { + Err("PCIe DUMPREG", "pcie dumpreg write info to logfile failed.\n"); + } else { + wr_ret = write(g_pcie_dumpreg_fd, str, strlen(str)); + if (wr_ret == -1) + Err("PCIe DUMPREG", "write info to logfile failed.\n"); + } +} + +static void pcie_dumpreg_save_glb_analysis_log(const uint32_t *data, uint32_t data_num) +{ + uint32_t item_i, data_i; + + data_i = 0; + /* IOB_TX REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_iob_tx) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_iob_tx[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_iob_tx[item_i].name, + g_reg_table_iob_tx[item_i].val); + } + /* IOB_RX REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_iob_rx) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_iob_rx[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_iob_rx[item_i].name, + g_reg_table_iob_rx[item_i].val); + } + /* AP_GLB REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_ap_glb) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_ap_glb[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_ap_glb[item_i].name, + g_reg_table_ap_glb[item_i].val); + } + /* CORE_GLB REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_core_glb) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_core_glb[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_core_glb[item_i].name, + g_reg_table_core_glb[item_i].val); + } +} + +static void pcie_dumpreg_save_port_analysis_log(uint32_t *data, uint32_t data_num) +{ + uint32_t item_i, data_i; + + data_i = 0; + /* TL REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_tl) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_tl[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_tl[item_i].name, + g_reg_table_tl[item_i].val); + } + /* DL REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_dl) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_dl[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_dl[item_i].name, + g_reg_table_dl[item_i].val); + } + /* MAC REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_mac) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_mac[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_mac[item_i].name, + g_reg_table_mac[item_i].val); + } + /* PCS REG */ + for (item_i = 0; item_i < HIKP_ARRAY_SIZE(g_reg_table_pcs) && + data_i < data_num; item_i++, data_i++) { + g_reg_table_pcs[item_i].val = data[data_i]; + pcie_dumpreg_write_value_to_file(g_reg_table_pcs[item_i].name, + g_reg_table_pcs[item_i].val); + } +} + +static int pcie_dumpreg_write_header_to_file(uint32_t version, + const struct pcie_dump_req_para *req_data) +{ + char str[MAX_STR_LEN] = {0}; + ssize_t wr_ret; + int ret; + + ret = snprintf(str, sizeof(str), "Command Version[%u], dump_level[%u], port_id[%u]\n\n", + version, req_data->level, req_data->port_id); + if (ret < 0) { + Err("PCIe DUMPREG", "pcie dumpreg write header to logfile failed.\n"); + return -EIO; + } + + wr_ret = write(g_pcie_dumpreg_fd, str, strlen(str)); + if (wr_ret == -1) { + Err("PCIe DUMPREG", "write header to logfile failed.\n"); + return -EIO; + } + + return 0; +} + +static int pcie_dumpreg_save_log(uint32_t *data, uint32_t data_num, + uint32_t version, struct pcie_dump_req_para *req_data) +{ + size_t expect_data_num = 0; + char reg_name[PCIE_REG_NAME_LEN]; + uint32_t i; + int ret; + + (void)pcie_dumpreg_write_header_to_file(version, req_data); + + switch (req_data->level) { + case DUMP_GLOBAL_LEVEL: + expect_data_num = HIKP_ARRAY_SIZE(g_reg_table_iob_tx) + + HIKP_ARRAY_SIZE(g_reg_table_iob_rx) + HIKP_ARRAY_SIZE(g_reg_table_ap_glb) + + HIKP_ARRAY_SIZE(g_reg_table_core_glb); + break; + case DUMP_PORT_LEVEL: + expect_data_num = HIKP_ARRAY_SIZE(g_reg_table_tl) + + HIKP_ARRAY_SIZE(g_reg_table_dl) + + HIKP_ARRAY_SIZE(g_reg_table_mac) + + HIKP_ARRAY_SIZE(g_reg_table_pcs); + break; + default: + Err("PCIe DUMPREG", "check dump level failed.\n"); + return -EINVAL; + } + + if (expect_data_num != data_num || version != ORIGINAL_VERSION) { + for (i = 0; i < data_num; i++) { + ret = snprintf(reg_name, sizeof(reg_name), "REG_%03u", i); + if (ret < 0) + Err("PCIe DUMPREG", "save log snprintf failed.\n"); + pcie_dumpreg_write_value_to_file(reg_name, data[i]); + } + } else if (req_data->level == DUMP_GLOBAL_LEVEL) { + pcie_dumpreg_save_glb_analysis_log(data, data_num); + } else { + pcie_dumpreg_save_port_analysis_log(data, data_num); + } + + return 0; +} + +int pcie_dumpreg_do_dump(uint32_t port_id, uint32_t dump_level) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret = NULL; + struct pcie_dump_req_para req_data = { 0 }; + int ret = 0; + + Info("PCIe DUMPREG", "pcie reg dump start.\n"); + + req_data.port_id = port_id; + req_data.level = dump_level; + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_DUMP, DUMPREG_DUMP); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) { + Err("PCIe DUMPREG", "pcie dump cmd_ret check failed, ret: %d.\n", ret); + goto free_cmd_ret; + } + ret = pcie_create_dumpreg_log_file(port_id, dump_level); + if (ret) + goto free_cmd_ret; + + ret = pcie_dumpreg_save_log(cmd_ret->rsp_data, + cmd_ret->rsp_data_num, cmd_ret->version, &req_data); + if (ret) { + Err("PCIe DUMPREG", "pcie dump save log failed, ret: %d.\n", ret); + goto close_file_ret; + } + + Info("PCIe DUMPREG", "pcie reg dump finish.\n"); +close_file_ret: + (void)pcie_close_dumpreg_log_file(); +free_cmd_ret: + free(cmd_ret); + + return ret; +} diff --git a/pcie/func_lib/pcie_func/pcie_reg_dump.h b/pcie/func_lib/pcie_func/pcie_reg_dump.h new file mode 100644 index 0000000..1993c1f --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_reg_dump.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 __PCIE_REG_DUMP_H_ +#define __PCIE_REG_DUMP_H_ + +#include "pcie_common_api.h" + +#define PCIE_REG_NAME_LEN 60 +#define MAX_STR_LEN 80 +#define PCIE_DUMPREG_LOGFILE_NAME "pcie_dumpreg" + +enum pcie_dump_level { + DUMP_GLOBAL_LEVEL = 1, + DUMP_PORT_LEVEL = 2, +}; + +enum pcie_dump_log_version { + ORIGINAL_VERSION = 0, +}; + +struct pcie_dumpreg_info { + uint32_t val; + char name[PCIE_REG_NAME_LEN]; +}; + +struct pcie_dump_req_para { + uint32_t port_id; + uint32_t level; +}; + +int pcie_dumpreg_do_dump(uint32_t port_id, uint32_t dump_level); + +#endif diff --git a/pcie/func_lib/pcie_func/pcie_reg_read.c b/pcie/func_lib/pcie_func/pcie_reg_read.c new file mode 100644 index 0000000..6ba4f07 --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_reg_read.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "hikptdev_plug.h" +#include "os_common.h" +#include "pcie_common.h" +#include "pcie_reg_read.h" + +static struct pcie_module_table g_module_table[] = { + {"AP_IOB_TX_REG", AP_IOB_TX_REG_ID}, + {"AP_IOB_RX_REG", AP_IOB_RX_REG_ID}, + {"AP_P2P_REG", AP_P2P_REG_ID}, + {"AP_APAT_REG", AP_APAT_REG_ID}, + {"AP_GLOBAL_REG", AP_GLOBAL_REG_ID}, + {"PCIPC_REG", PCIPC_REG_ID}, + {"AP_MCTP_REG", AP_MCTP_REG_ID}, + {"AP_ENGINE_REG", AP_ENGINE_REG_ID}, + {"AP_INT_REG", AP_INT_REG_ID}, + {"AP_DMA_REG", AP_DMA_REG_ID}, + {"TOP_REG", TOP_REG_ID}, + {"CORE_GLOBAL_REG", CORE_GLOBAL_REG_ID}, + {"DL_REG", DL_REG_ID}, + {"MAC_REG", MAC_REG_ID}, + {"TL_REG", TL_REG_ID}, + {"TL_CORE_REG", TL_CORE_REG_ID}, + {"TL_CORE_PF_REG", TL_CORE_PF_REG_ID}, + {"TL_CORE_DFX_REG", TL_CORE_DFX_REG_ID}, + {"CFGSPACE", CFGSPACE_ID}, + {"CXL_RCRB", CXL_RCRB_ID}, + {"PCS_GLB_REG", PCS_GLB_REG_ID}, + {"PCS_LANE_REG", PCS_LANE_REG_ID}, +}; + +int pcie_read_name2module_id(const char *module_name, uint32_t *module_id) +{ + size_t i, num; + + if (module_name == NULL || module_id == NULL) + return -EINVAL; + + num = HIKP_ARRAY_SIZE(g_module_table); + for (i = 0; i < num; i++) { + if (strcmp(module_name, g_module_table[i].module_name) == 0) { + *module_id = g_module_table[i].module_id; + return 0; + } + } + + return -EINVAL; +} + +static int pcie_reg_read_result_show(const struct hikp_cmd_ret *cmd_ret) +{ + if (cmd_ret->rsp_data_num != 1) { /* 1 uint32_t data for reg read cmd */ + Err("PCIe REGREAD", "pcie reg read data num check failed, num: %u.\n", + cmd_ret->rsp_data_num); + return -EINVAL; + } + Info("PCIe REGREAD", "RIGISTER VALUE[0x%08x].\n", cmd_ret->rsp_data[0]); + + return 0; +} + +int pcie_reg_read(uint32_t port_id, uint32_t module_id, uint32_t offset) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret = NULL; + struct pcie_reg_read_req_para req_data = { 0 }; + int ret = 0; + + req_data.port_id = port_id; + req_data.module_id = module_id; + req_data.offset = offset; + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_REGRD, REGRD_READ); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) { + Err("PCIe REGREAD", "pcie reg read cmd_ret check failed, ret: %d.\n", ret); + goto free_cmd_ret; + } + ret = pcie_reg_read_result_show(cmd_ret); + +free_cmd_ret: + free(cmd_ret); + + return ret; +} diff --git a/pcie/func_lib/pcie_func/pcie_reg_read.h b/pcie/func_lib/pcie_func/pcie_reg_read.h new file mode 100644 index 0000000..05d509a --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_reg_read.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 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 __PCIE_REG_READ_H_ +#define __PCIE_REG_READ_H_ + +#include "pcie_common_api.h" + +#define MAX_PCIE_MODULE_NAME_LEN 20 + +struct pcie_reg_read_req_para { + uint32_t port_id; + uint32_t module_id; + uint32_t offset; +}; + +struct pcie_module_table { + char module_name[MAX_PCIE_MODULE_NAME_LEN]; + uint32_t module_id; +}; + +enum pcie_module_id_list { + AP_IOB_TX_REG_ID = 0, + AP_IOB_RX_REG_ID = 1, + AP_P2P_REG_ID = 2, + AP_APAT_REG_ID = 3, + AP_GLOBAL_REG_ID = 4, + PCIPC_REG_ID = 5, + AP_MCTP_REG_ID = 6, + AP_ENGINE_REG_ID = 7, + AP_INT_REG_ID = 8, + AP_DMA_REG_ID = 9, + TOP_REG_ID = 10, + CORE_GLOBAL_REG_ID = 11, + DL_REG_ID = 12, + MAC_REG_ID = 13, + TL_REG_ID = 14, + TL_CORE_REG_ID = 15, + TL_CORE_PF_REG_ID = 16, + TL_CORE_DFX_REG_ID = 17, + CFGSPACE_ID = 18, + CXL_RCRB_ID = 19, + PCS_GLB_REG_ID = 20, + PCS_LANE_REG_ID = 21, +}; + +int pcie_reg_read(uint32_t port_id, uint32_t module_id, uint32_t offset); +int pcie_read_name2module_id(const char *module_name, uint32_t *module_id); + +#endif diff --git a/pcie/func_lib/pcie_func/pcie_statistics.c b/pcie/func_lib/pcie_func/pcie_statistics.c new file mode 100644 index 0000000..f12660d --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_statistics.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "os_common.h" +#include "pcie_common.h" +#include "hikptdev_plug.h" +#include "pcie_statistics.h" + +static const char *g_global_width_name[GLOBAL_WIDTH_TABLE_SIZE] = { + "PCIE_WITDH_X1", "PCIE_WITDH_X2", "PCIE_WITDH_X4", "PCIE_WITDH_X8", "PCIE_WITDH_X16" +}; + +static int port_distribution_rsp_data_check(const struct hikp_cmd_ret *cmd_ret, uint32_t *port_num) +{ + size_t rsp_data_size, expect_data_size; + struct pcie_port_info *port_info; + int ret; + + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) { + Err("PCIe Base", "port distribution cmd_ret normal check failed, ret: %d.\n", ret); + return ret; + } + rsp_data_size = cmd_ret->rsp_data_num * sizeof(uint32_t); + /* Check whether enough data of a port unit */ + if (rsp_data_size < sizeof(struct pcie_port_info)) { + Err("PCIe Base", "port distribution rsp check failed, size: %u.\n", + rsp_data_size); + return -EINVAL; + } + /* Check whether enough data of n pairs */ + port_info = (struct pcie_port_info *)cmd_ret->rsp_data; + *port_num = port_info->port_num; + expect_data_size = sizeof(struct pcie_port_info) + + sizeof(struct pcie_info_distribution_pair) * (*port_num); + if (expect_data_size > rsp_data_size) { + Err("PCIe Base", + "port distribution data size check failed, size: %u, expect size: %u.\n", + rsp_data_size, expect_data_size); + return -EINVAL; + } + + return 0; +} + +int pcie_port_distribution_get(uint32_t chip_id) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct pcie_info_req_para req_data = { 0 }; + uint32_t src_size, dst_size, pair_num; + struct pcie_port_info *port_info; + uint32_t i; + int ret; + + req_data.interface_id = chip_id; + + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_INFO, INFO_DISTRIBUTION); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = port_distribution_rsp_data_check(cmd_ret, &pair_num); + if (ret) + goto free_cmd_ret; + + port_info = (struct pcie_port_info *)cmd_ret->rsp_data; + Info("PCIe Base", "Port Distribution Info (CHIP : 0x%x)Port_id Port_width\n", chip_id); + for (i = 0; i < pair_num; i++) { + if (port_info->info_pair[i].port_width >= HIKP_ARRAY_SIZE(g_global_width_name)) { + Info("PCIe Base", "port_id[%u] %s\n", port_info->info_pair[i].port_id, + "UNKNOWN_WITDH"); + continue; + } + Info("PCIe Base", "port_id[%u] %s\n", port_info->info_pair[i].port_id, + g_global_width_name[port_info->info_pair[i].port_width]); + } +free_cmd_ret: + free(cmd_ret); + + return ret; +} + +static int port_err_state_rsp_data_check(struct hikp_cmd_ret *cmd_ret) +{ + size_t rsp_data_size; + int ret; + + ret = hikp_rsp_normal_check(cmd_ret); + if (ret) { + Err("PCIe Base", "error state get cmd_ret normal check failed, ret: %d.\n", ret); + return ret; + } + rsp_data_size = cmd_ret->rsp_data_num * sizeof(uint32_t); + if (rsp_data_size < sizeof(struct pcie_err_state)) { + Err("PCIe Base", + "err state get rsp size check failed, rsp size: %u, expect size:%u.\n", + rsp_data_size, sizeof(struct pcie_err_state)); + return -EINVAL; + } + + return 0; +} + +int pcie_error_state_get(uint32_t port_id) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct pcie_info_req_para req_data = { 0 }; + struct pcie_err_state *state; + int ret; + + req_data.interface_id = port_id; + + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_INFO, INFO_ERR_STATE_SHOW); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = port_err_state_rsp_data_check(cmd_ret); + if (ret) + goto free_cmd_ret; + + state = (struct pcie_err_state *)cmd_ret->rsp_data; + + Info("PCIe Base", "phy_lane_err_counter = %u\n", state->test_cnt.bits.phy_lane_err_counter); + Info("PCIe Base", "symbol_unlock_counter = %u\n", + state->symbol_unlock_cnt.bits.symbol_unlock_counter); + Info("PCIe Base", "mac_int_status = 0x%x\n", state->mac_int_status); + Info("PCIe Base", "loop_back_link_data_err_cnt = %u\n", + state->loop_link_data_err_cnt.bits.loop_back_link_data_err_cnt); + Info("PCIe Base", "pcs_rx_err_cnt = %u\n", state->rx_err_cnt.bits.pcs_rx_err_cnt); + Info("PCIe Base", "reg_framing_err_count = %u\n", + state->framing_err_cnt.bits.reg_framing_err_count); + Info("PCIe Base", "dl_lcrc_err_num = %u\n", state->lcrc_err_num.bits.dl_lcrc_err_num); + Info("PCIe Base", "dl_dcrc_err_num = %u\n", state->dcrc_err_num.bits.dl_dcrc_err_num); +free_cmd_ret: + free(cmd_ret); + + return ret; +} + +int pcie_error_state_clear(uint32_t port_id) +{ + struct hikp_cmd_header req_header; + struct hikp_cmd_ret *cmd_ret; + struct pcie_info_req_para req_data = { 0 }; + int ret; + + req_data.interface_id = port_id; + hikp_cmd_init(&req_header, PCIE_MOD, PCIE_INFO, INFO_ERR_STATE_CLEAR); + cmd_ret = hikp_cmd_alloc(&req_header, &req_data, sizeof(req_data)); + ret = hikp_rsp_normal_check(cmd_ret); + free(cmd_ret); + + return ret; +} diff --git a/pcie/func_lib/pcie_func/pcie_statistics.h b/pcie/func_lib/pcie_func/pcie_statistics.h new file mode 100644 index 0000000..2a3cc66 --- /dev/null +++ b/pcie/func_lib/pcie_func/pcie_statistics.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022 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 __PCIE_STATISTICS_H_ +#define __PCIE_STATISTICS_H_ + +#include "pcie_common_api.h" + +#define GLOBAL_WIDTH_TABLE_SIZE 5 + +union mac_test_cnt { + /* Define the struct bits */ + struct { + unsigned int phy_lane_err_counter : 16; /* [15..0] */ + unsigned int reserved_0 : 16; /* [31..16] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +union mac_symbol_unlock_cnt { + /* Define the struct bits */ + struct { + unsigned int symbol_unlock_counter : 16; /* [15..0] */ + unsigned int reserved_0 : 16; /* [31..16] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +union mac_loop_link_data_err_cnt { + /* Define the struct bits */ + struct { + unsigned int loop_back_link_data_err_cnt : 16; /* [15..0] */ + unsigned int reserved_0 : 16; /* [31..16] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +union mac_rx_err_cnt { + /* Define the struct bits */ + struct { + unsigned int pcs_rx_err_cnt : 16; /* [15..0] */ + unsigned int reserved_0 : 16; /* [31..16] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +union mac_framing_err_cnt { + /* Define the struct bits */ + struct { + unsigned int reg_framing_err_count : 16; /* [15..0] */ + unsigned int resvered : 16; /* [31..16] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +union dfx_lcrc_err_num { + /* Define the struct bits */ + struct { + unsigned int dl_lcrc_err_num : 8; /* [7..0] */ + unsigned int reserved_0 : 24; /* [31..8] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +union dfx_dcrc_err_num { + /* Define the struct bits */ + struct { + unsigned int dl_dcrc_err_num : 8; /* [7..0] */ + unsigned int reserved_0 : 24; /* [31..8] */ + } bits; + /* Define an unsigned member */ + unsigned int u32; +}; + +struct pcie_info_distribution_pair { + uint32_t port_id; + uint32_t port_width; +}; + +struct pcie_port_info { + uint32_t port_num; + struct pcie_info_distribution_pair info_pair[0]; +}; + +struct pcie_err_state { + union mac_test_cnt test_cnt; + union mac_symbol_unlock_cnt symbol_unlock_cnt; + union mac_loop_link_data_err_cnt loop_link_data_err_cnt; + uint32_t mac_int_status; + union mac_rx_err_cnt rx_err_cnt; + union mac_framing_err_cnt framing_err_cnt; + union dfx_lcrc_err_num lcrc_err_num; + union dfx_dcrc_err_num dcrc_err_num; +}; + +struct pcie_info_req_para { + uint32_t interface_id; +}; + +int pcie_port_distribution_get(uint32_t chip_id); +int pcie_error_state_get(uint32_t port_id); +int pcie_error_state_clear(uint32_t port_id); + +#endif diff --git a/pcie/usr_cmd/cmd_analysis/pcie_cmd_dumpreg.c b/pcie/usr_cmd/cmd_analysis/pcie_cmd_dumpreg.c new file mode 100644 index 0000000..f6399b4 --- /dev/null +++ b/pcie/usr_cmd/cmd_analysis/pcie_cmd_dumpreg.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "pcie_common_api.h" +#include "pcie_common.h" +#include "pcie_tools_include.h" +#include "pcie_reg_dump.h" + +struct tool_pcie_cmd g_dumpreg_cmd = { + .cmd_type = 0, + .chip_id = (uint32_t)(-1), + .port_id = (uint32_t)(-1), + .trace_mode_val = 0, + .dump_level_val = DUMP_PORT_LEVEL, +}; + +static int pcie_dumpreg_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first\n"); + printf(" %s, %-25s %s\n", "-l", "--level", + "set dump level 1:global, 2:port classification\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-d", "--dump", + "dump important regs to pcie_dumpreg.log file\n"); + printf("\n"); + + return 0; +} + +static int pcie_port_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("info set port id err %d.\n", ret); + return -EINVAL; + } + g_dumpreg_cmd.port_id = val; + + return 0; +} + +static int dump_level_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret || val < DUMP_GLOBAL_LEVEL || val > DUMP_PORT_LEVEL) { + printf("info set id err, ret = %d, val = %u\n", ret, val); + return -EINVAL; + } + g_dumpreg_cmd.dump_level_val = val; + + return 0; +} + +static int pcie_dumpreg_dump(struct major_cmd_ctrl *self, const char *argv) +{ + g_dumpreg_cmd.cmd_type = DUMPREG_DUMP; + + return 0; +} + +static int pcie_dumpreg_excute_funs_call(uint32_t cmd_type) +{ + struct pcie_comm_api *comm_api = pcie_get_comm_api(); + uint32_t port_id = g_dumpreg_cmd.port_id; + uint32_t level = g_dumpreg_cmd.dump_level_val; + + if (cmd_type != DUMPREG_DUMP) + return -EINVAL; + + return comm_api->reg_dump(port_id, level); +} + +static void pcie_dumpreg_execute(struct major_cmd_ctrl *self) +{ + int ret; + const char *suc_msg[] = { + "", + "dumpreg_dump success." + }; + const char *err_msg[] = { + "pcie_dumpreg sub command type error.", + "dumpreg_dump error." + }; + + ret = pcie_dumpreg_excute_funs_call(g_dumpreg_cmd.cmd_type); + if (ret) { + snprintf(self->err_str, sizeof(self->err_str), "%s\n", + err_msg[g_dumpreg_cmd.cmd_type]); + self->err_no = ret; + return; + } + printf("%s\n", suc_msg[g_dumpreg_cmd.cmd_type]); +} + +static void cmd_pcie_dumpreg_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = pcie_dumpreg_execute; + + cmd_option_register("-h", "--help", false, pcie_dumpreg_help); + cmd_option_register("-d", "--dump", false, pcie_dumpreg_dump); + cmd_option_register("-i", "--interface", true, pcie_port_set); + cmd_option_register("-l", "--level", true, dump_level_set); +} + +HIKP_CMD_DECLARE("pcie_dumpreg", "pcie dump important regs for problem location", + cmd_pcie_dumpreg_init); diff --git a/pcie/usr_cmd/cmd_analysis/pcie_cmd_info.c b/pcie/usr_cmd/cmd_analysis/pcie_cmd_info.c new file mode 100644 index 0000000..aeab241 --- /dev/null +++ b/pcie/usr_cmd/cmd_analysis/pcie_cmd_info.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "pcie_common_api.h" +#include "pcie_common.h" +#include "pcie_tools_include.h" + +struct tool_pcie_cmd g_info_cmd = { + .cmd_type = 0, + .chip_id = (uint32_t)(-1), + .port_id = (uint32_t)(-1), + .trace_mode_val = 0, +}; + +static int pcie_info_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", + "please input chip[x] or port[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-d", "--distribution", "show distribution on this chip\n"); + printf(" %s, %-25s %s\n", "-es", "--error-show", "show error state on this port\n"); + printf(" %s, %-25s %s\n", "-ec", "--error-clear", "clear error state on this port\n"); + printf("\n"); + + return 0; +} + +static int pcie_distribution_show(struct major_cmd_ctrl *self, const char *argv) +{ + g_info_cmd.cmd_type = INFO_DISTRIBUTION; + + return 0; +} + +static int pcie_err_state_show(struct major_cmd_ctrl *self, const char *argv) +{ + g_info_cmd.cmd_type = INFO_ERR_STATE_SHOW; + + return 0; +} + +static int pcie_err_state_clear(struct major_cmd_ctrl *self, const char *argv) +{ + g_info_cmd.cmd_type = INFO_ERR_STATE_CLEAR; + + return 0; +} + +static int pcie_port_chip_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("info set id err %d\n", ret); + return -EINVAL; + } + g_info_cmd.chip_id = val; + g_info_cmd.port_id = val; + + return 0; +} + +static int pcie_info_excute_funs_call(uint32_t cmd_type) +{ + struct pcie_comm_api *comm_api = pcie_get_comm_api(); + uint32_t chip_id = g_info_cmd.chip_id; + uint32_t port_id = g_info_cmd.port_id; + + if (!comm_api) + return -EINVAL; + + if (cmd_type == INFO_DISTRIBUTION) + return comm_api->distribution_show(chip_id); + else if (cmd_type == INFO_ERR_STATE_SHOW) + return comm_api->err_status_show(port_id); + else if (cmd_type == INFO_ERR_STATE_CLEAR) + return comm_api->err_status_clear(port_id); + else + return -EINVAL; +} + +static void pcie_info_execute(struct major_cmd_ctrl *self) +{ + int ret; + const char *suc_msg[] = { + "", + "distribution_show success.", + "err_status_show success.", + "err_status_clear success." + }; + const char *err_msg[] = { + "pcie_info sub command type error.", + "distribution_show error.", + "err_status_show error.", + "err_status_clear error." + }; + + ret = pcie_info_excute_funs_call(g_info_cmd.cmd_type); + if (ret) { + snprintf(self->err_str, sizeof(self->err_str), "%s\n", + err_msg[g_info_cmd.cmd_type]); + self->err_no = ret; + return; + } + printf("%s\n", suc_msg[g_info_cmd.cmd_type]); +} + +static void cmd_pcie_info_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = pcie_info_execute; + + cmd_option_register("-h", "--help", false, pcie_info_help); + cmd_option_register("-d", "--distribution", false, pcie_distribution_show); + cmd_option_register("-es", "--error-show", false, pcie_err_state_show); + cmd_option_register("-ec", "--error-clear", false, pcie_err_state_clear); + cmd_option_register("-i", "--interface", true, pcie_port_chip_set); +} + +HIKP_CMD_DECLARE("pcie_info", "pcie information", cmd_pcie_info_init); diff --git a/pcie/usr_cmd/cmd_analysis/pcie_cmd_reg_read.c b/pcie/usr_cmd/cmd_analysis/pcie_cmd_reg_read.c new file mode 100644 index 0000000..6e54516 --- /dev/null +++ b/pcie/usr_cmd/cmd_analysis/pcie_cmd_reg_read.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "pcie_common_api.h" +#include "pcie_common.h" +#include "pcie_tools_include.h" +#include "pcie_reg_dump.h" +#include "pcie_reg_read.h" + +struct tool_pcie_cmd g_regread_cmd = { + .cmd_type = 0, + .chip_id = (uint32_t)(-1), + .port_id = (uint32_t)(-1), + .trace_mode_val = 0, + .dump_level_val = DUMP_PORT_LEVEL, + .read_offset_val = (uint32_t)(-1), + .read_module_val = (uint32_t)(-1), +}; + +static int pcie_reg_read_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first\n"); + printf(" %s, %-25s %s\n", "-m", "--module", "set read module\n"); + printf(" %s, %-25s %s\n", "-o", "--offset", "set reg offset\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-r", "--read", "read pcie reg in specific module\n"); + printf("\n"); + + return 0; +} + +static int pcie_port_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("info set port id err %d.\n", ret); + return -EINVAL; + } + g_regread_cmd.port_id = val; + + return 0; +} + +static int read_module_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = pcie_read_name2module_id(argv, &val); + if (ret) { + printf("undefined module \"%s\".\n", argv); + return -EINVAL; + } + g_regread_cmd.read_module_val = val; + + return 0; +} + +static int read_offset_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("info set offset err %d.\n", ret); + return -EINVAL; + } + g_regread_cmd.read_offset_val = val; + + return 0; +} + +static int pcie_reg_read_exe(struct major_cmd_ctrl *self, const char *argv) +{ + g_regread_cmd.cmd_type = REGRD_READ; + + return 0; +} + +static int pcie_reg_read_excute_funs_call(uint32_t cmd_type) +{ + struct pcie_comm_api *comm_api = pcie_get_comm_api(); + uint32_t port_id = g_regread_cmd.port_id; + uint32_t module_id = g_regread_cmd.read_module_val; + uint32_t offset = g_regread_cmd.read_offset_val; + + if (cmd_type == REGRD_READ) + return comm_api->reg_read(port_id, module_id, offset); + else + return -EINVAL; + + return 0; +} + +static void pcie_reg_read_execute(struct major_cmd_ctrl *self) +{ + int ret; + const char *suc_msg[] = { + "", + "regrd_read success." + }; + const char *err_msg[] = { + "pcie_regrd sub command type error.", + "regrd_read error." + }; + + ret = pcie_reg_read_excute_funs_call(g_regread_cmd.cmd_type); + if (ret == 0) { + printf("%s\n", suc_msg[g_regread_cmd.cmd_type]); + } else { + snprintf(self->err_str, sizeof(self->err_str), "%s\n", + err_msg[g_regread_cmd.cmd_type]); + self->err_no = ret; + } +} + +static void cmd_pcie_reg_read_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = pcie_reg_read_execute; + + cmd_option_register("-h", "--help", false, pcie_reg_read_help); + cmd_option_register("-r", "--read", false, pcie_reg_read_exe); + cmd_option_register("-i", "--interface", true, pcie_port_set); + cmd_option_register("-m", "--module", true, read_module_set); + cmd_option_register("-o", "--offset", true, read_offset_set); +} + +HIKP_CMD_DECLARE("pcie_regrd", "pcie reg read for problem location", cmd_pcie_reg_read_init); diff --git a/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c b/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c new file mode 100644 index 0000000..e50b434 --- /dev/null +++ b/pcie/usr_cmd/cmd_analysis/pcie_cmd_trace.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2022 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 "tool_lib.h" +#include "tool_cmd.h" +#include "pcie_common_api.h" +#include "pcie_tools_include.h" +#include "pcie_common.h" + +struct tool_pcie_cmd g_trace_cmd = { + .cmd_type = 0, + .chip_id = (uint32_t)(-1), + .port_id = (uint32_t)(-1), + .trace_mode_val = 0, +}; + + +static int pcie_trace_help(struct major_cmd_ctrl *self, const char *argv) +{ + printf("\n Usage: %s\n", self->cmd_ptr->name); + printf("\n %s\n", self->cmd_ptr->help_info); + printf(" %s, %-25s %s\n", "-i", "--interface", "please input port[x] first\n"); + printf("\n Options:\n\n"); + printf(" %s, %-25s %s\n", "-h", "--help", "display this help and exit\n"); + printf(" %s, %-25s %s\n", "-c", "--clear", "clear ltssm trace\n"); + printf(" %s, %-25s %s\n", "-s", "--show", "show ltssm trace\n"); + 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("\n"); + + return 0; +} + +static int pcie_trace_clear(struct major_cmd_ctrl *self, const char *argv) +{ + g_trace_cmd.cmd_type = TRACE_CLEAR; + + return 0; +} + + +static int pcie_trace_show(struct major_cmd_ctrl *self, const char *argv) +{ + g_trace_cmd.cmd_type = TRACE_SHOW; + + return 0; +} + +static int pcie_trace_mode_set(struct major_cmd_ctrl *self, const char *argv) +{ + int ret; + uint32_t val = 0; + + g_trace_cmd.cmd_type = TRACE_MODE; + ret = string_toui(argv, &val); + if (ret || val > 1) { + printf("tarce mode set err %d\n", ret); + return -EINVAL; + } + g_trace_cmd.trace_mode_val = val; + + return 0; +} + +static int pcie_link_information_get(struct major_cmd_ctrl *self, const char *argv) +{ + g_trace_cmd.cmd_type = TRACE_INFO; + return 0; +} + +static int pcie_port_id_set(struct major_cmd_ctrl *self, const char *argv) +{ + uint32_t val; + int ret; + + ret = string_toui(argv, &val); + if (ret) { + printf("trace set port id err %d\n", ret); + return -EINVAL; + } + g_trace_cmd.port_id = val; + + return 0; +} + +static int pcie_trace_excute_funs_call(int cmd_type) +{ + struct pcie_comm_api *comm_api = pcie_get_comm_api(); + uint32_t recover_en = g_trace_cmd.trace_mode_val; + uint32_t port_id = g_trace_cmd.port_id; + + if (cmd_type == TRACE_CLEAR) + return comm_api->ltssm_trace_clear(port_id); + else if (cmd_type == TRACE_SHOW) + return comm_api->ltssm_trace_show(port_id); + else if (cmd_type == TRACE_MODE) + 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 + return -EINVAL; +} + +static void pcie_trace_execute(struct major_cmd_ctrl *self) +{ + int ret; + const char *suc_msg[] = { + "", + "pcie_trace_show success.", + "pcie_trace_clear success.", + "get mac link information success.", + "pcie_trace_mode_set 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." + }; + + ret = pcie_trace_excute_funs_call(g_trace_cmd.cmd_type); + if (ret == 0) { + printf("%s\n", suc_msg[g_trace_cmd.cmd_type]); + } else { + snprintf(self->err_str, sizeof(self->err_str), "%s\n", + err_msg[g_trace_cmd.cmd_type]); + self->err_no = ret; + } +} + +static void cmd_pcie_trace_init(void) +{ + struct major_cmd_ctrl *major_cmd = get_major_cmd(); + + major_cmd->option_count = 0; + major_cmd->execute = pcie_trace_execute; + + cmd_option_register("-h", "--help", false, pcie_trace_help); + cmd_option_register("-c", "--clear", false, pcie_trace_clear); + cmd_option_register("-s", "--show", false, pcie_trace_show); + 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); +} + +HIKP_CMD_DECLARE("pcie_trace", "pcie ltssm trace", cmd_pcie_trace_init); diff --git a/pcie/usr_cmd/cmd_analysis/pcie_tools_include.h b/pcie/usr_cmd/cmd_analysis/pcie_tools_include.h new file mode 100644 index 0000000..83b7349 --- /dev/null +++ b/pcie/usr_cmd/cmd_analysis/pcie_tools_include.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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 __PCIE_TOOLS_INCLUDE_H_ +#define __PCIE_TOOLS_INCLUDE_H_ + +#include "hikptdev_plug.h" +#include "tool_lib.h" + +#define MAX_PARA_LENTH 10 + +struct tool_pcie_cmd { + uint32_t cmd_type; + uint32_t chip_id; + uint32_t port_id; + uint32_t trace_mode_val; + uint32_t dump_level_val; + uint32_t read_offset_val; + uint32_t read_module_val; +}; + +#endif diff --git a/pcie/usr_cmd/interface/pcie_common_api.c b/pcie/usr_cmd/interface/pcie_common_api.c new file mode 100644 index 0000000..491daf2 --- /dev/null +++ b/pcie/usr_cmd/interface/pcie_common_api.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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 "pcie_common_api.h" +#include "pcie_link_ltssm.h" +#include "pcie_statistics.h" +#include "pcie_reg_dump.h" +#include "pcie_reg_read.h" + +struct pcie_comm_api g_tools_api = { + .ltssm_trace_show = pcie_ltssm_trace_show, + .ltssm_trace_clear = pcie_ltssm_trace_clear, + .ltssm_trace_mode_set = pcie_ltssm_trace_mode_set, + .ltssm_link_information_get = pcie_ltssm_link_status_get, + .distribution_show = pcie_port_distribution_get, + .err_status_show = pcie_error_state_get, + .err_status_clear = pcie_error_state_clear, + .reg_dump = pcie_dumpreg_do_dump, + .reg_read = pcie_reg_read, +}; + + +struct pcie_comm_api *pcie_get_comm_api(void) +{ + return &g_tools_api; +} diff --git a/pcie/usr_cmd/interface/pcie_common_api.h b/pcie/usr_cmd/interface/pcie_common_api.h new file mode 100644 index 0000000..f6541bd --- /dev/null +++ b/pcie/usr_cmd/interface/pcie_common_api.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 __PCIE_COMMON_API_H_ +#define __PCIE_COMMON_API_H_ + +#include +#include + +struct print_info { + char *buff; + size_t buff_size; + size_t used_lenth; +}; + +struct pcie_comm_api { + int (*ltssm_trace_show)(uint32_t port_id); + int (*ltssm_trace_clear)(uint32_t port_id); + int (*ltssm_trace_mode_set)(uint32_t port_id, uint32_t mode); + int (*ltssm_link_information_get)(uint32_t port_id); + int (*distribution_show)(uint32_t chip_id); + int (*err_status_show)(uint32_t port_id); + 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); +}; + +struct pcie_comm_api *pcie_get_comm_api(void); + +#endif -- Gitee From 6292ce77393f85ff852c35b3fb57522e1cc11eac Mon Sep 17 00:00:00 2001 From: veega2022 Date: Sat, 26 Nov 2022 16:34:11 +0800 Subject: [PATCH 14/14] add the usage restriction description only the root user or a user with the root permission can use the hikptool. Signed-off-by: veega2022 (cherry picked from commit a4bf6c7bdecf958b9f12437db6c505db6cd969de) --- README.en.md | 4 +++- README.md | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.en.md b/README.en.md index 62b28ea..a9669ea 100644 --- a/README.en.md +++ b/README.en.md @@ -1,7 +1,9 @@ # hikptool #### Description -hikptool is a userspace tool for Linux providing enhanced capabilities of inband information collection and problem location on Kunpeng chips. +hikptool is a userspace tool for Linux providing enhanced capabilities of inband information collection and problem location on Kunpeng chips. + +Note: Only the root user or a user with the root permission can use the hikptool. #### Software Architecture Software architecture description diff --git a/README.md b/README.md index a92edba..db6baa2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # hikptool #### 介绍 -hikptool is a userspace tool for Linux providing enhanced capabilities of inband information collection and problem location on Kunpeng chips. +hikptool is a userspace tool for Linux providing enhanced capabilities of inband information collection and problem location on Kunpeng chips. + +Note: Only the root user or a user with the root permission can use the hikptool. #### 软件架构 软件架构说明 -- Gitee