From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DDB5E45A38; Thu, 26 Sep 2024 14:43:15 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 344BB40669; Thu, 26 Sep 2024 14:43:11 +0200 (CEST) Received: from szxga03-in.huawei.com (szxga03-in.huawei.com [45.249.212.189]) by mails.dpdk.org (Postfix) with ESMTP id 122444065F for ; Thu, 26 Sep 2024 14:43:09 +0200 (CEST) Received: from mail.maildlp.com (unknown [172.19.162.254]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4XDtY10LHDzFqqw; Thu, 26 Sep 2024 20:42:45 +0800 (CST) Received: from kwepemf500004.china.huawei.com (unknown [7.202.181.242]) by mail.maildlp.com (Postfix) with ESMTPS id B70D3180105; Thu, 26 Sep 2024 20:43:07 +0800 (CST) Received: from localhost.huawei.com (10.90.30.45) by kwepemf500004.china.huawei.com (7.202.181.242) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 26 Sep 2024 20:43:07 +0800 From: Jie Hai To: , , , CC: , , Subject: [PATCH v9 2/8] ethdev: add telemetry cmd for registers Date: Thu, 26 Sep 2024 20:42:43 +0800 Message-ID: <20240926124249.81679-3-haijie1@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20240926124249.81679-1-haijie1@huawei.com> References: <20231214015650.3738578-1-haijie1@huawei.com> <20240926124249.81679-1-haijie1@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.90.30.45] X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemf500004.china.huawei.com (7.202.181.242) X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This patch adds a telemetry command for registers dump, and supports obtaining the registers of a specified module. In one way, the number of registers that can be exported is limited by the number of elements carried by dict and container. In another way, the length of the string exported by telemetry is limited by MAX_OUTPUT_LEN. Therefore, when the number of registers to be exported exceeds, some information will be lost. Warn on the former case. An example usage is shown below: --> /ethdev/regs,0,ring { "/ethdev/regs": { "registers_length": 318, "registers_width": 4, "register_offset": "0x0", "version": "0x1140011", "group_0": { "Q0_ring_rx_bd_num": "0x0", "Q0_ring_rx_bd_len": "0x0", ... }, "group_1": { ... }, ... } Signed-off-by: Jie Hai Reviewed-by: Ferruh Yigit Acked-by: Chengwen Feng --- lib/ethdev/rte_ethdev_telemetry.c | 130 ++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/lib/ethdev/rte_ethdev_telemetry.c b/lib/ethdev/rte_ethdev_telemetry.c index 6b873e7abe68..181390691099 100644 --- a/lib/ethdev/rte_ethdev_telemetry.c +++ b/lib/ethdev/rte_ethdev_telemetry.c @@ -1395,6 +1395,134 @@ eth_dev_handle_port_tm_node_caps(const char *cmd __rte_unused, return ret; } +static void +eth_dev_add_reg_data(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info, + uint32_t idx) +{ + if (reg_info->width == sizeof(uint32_t)) + rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name, + *((uint32_t *)reg_info->data + idx), 0); + else + rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name, + *((uint64_t *)reg_info->data + idx), 0); +} + +static int +eth_dev_store_regs(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info) +{ + struct rte_tel_data *groups[RTE_TEL_MAX_DICT_ENTRIES]; + char group_name[RTE_TEL_MAX_STRING_LEN] = {0}; + struct rte_tel_data *group = NULL; + uint32_t grp_num = 0; + uint32_t i, max_cap; + int ret; + + rte_tel_data_start_dict(d); + rte_tel_data_add_dict_uint(d, "register_length", reg_info->length); + rte_tel_data_add_dict_uint(d, "register_width", reg_info->width); + rte_tel_data_add_dict_uint_hex(d, "register_offset", reg_info->offset, 0); + rte_tel_data_add_dict_uint_hex(d, "version", reg_info->version, 0); + + max_cap = (RTE_TEL_MAX_DICT_ENTRIES - 4) * RTE_TEL_MAX_DICT_ENTRIES; + if (reg_info->length > max_cap) { + RTE_ETHDEV_LOG_LINE(WARNING, + "Registers to be displayed are reduced from %u to %u due to limited capacity", + reg_info->length, max_cap); + reg_info->length = max_cap; + } + + for (i = 0; i < reg_info->length; i++) { + if (i % RTE_TEL_MAX_DICT_ENTRIES != 0) { + eth_dev_add_reg_data(group, reg_info, i); + continue; + } + + group = rte_tel_data_alloc(); + if (group == NULL) { + ret = -ENOMEM; + RTE_ETHDEV_LOG_LINE(WARNING, "No enough memory for group data"); + goto out; + } + groups[grp_num++] = group; + rte_tel_data_start_dict(group); + eth_dev_add_reg_data(group, reg_info, i); + } + + for (i = 0; i < grp_num; i++) { + snprintf(group_name, RTE_TEL_MAX_STRING_LEN, "group_%u", i); + rte_tel_data_add_dict_container(d, group_name, groups[i], 0); + } + return 0; +out: + for (i = 0; i < grp_num; i++) + rte_tel_data_free(groups[i]); + + return ret; +} + +static int +eth_dev_get_port_regs(int port_id, struct rte_tel_data *d, char *filter) +{ + struct rte_dev_reg_info reg_info; + int ret; + + memset(®_info, 0, sizeof(reg_info)); + reg_info.filter = filter; + + ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info); + if (ret != 0) { + RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret); + return ret; + } + + reg_info.data = calloc(reg_info.length, reg_info.width); + if (reg_info.data == NULL) { + RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.data"); + return -ENOMEM; + } + + reg_info.names = calloc(reg_info.length, sizeof(struct rte_eth_reg_name)); + if (reg_info.names == NULL) { + RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.names"); + free(reg_info.data); + return -ENOMEM; + } + + ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info); + if (ret != 0) { + RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret); + ret = -EINVAL; + goto out; + } + + ret = eth_dev_store_regs(d, ®_info); +out: + free(reg_info.data); + free(reg_info.names); + + return ret; +} + +static int +eth_dev_handle_port_regs(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d) +{ + char *filter, *end_param; + uint16_t port_id; + int ret; + + ret = eth_dev_parse_port_params(params, &port_id, &end_param, true); + if (ret != 0) + return ret; + + filter = strtok(end_param, ","); + if (filter != NULL && strlen(filter) == 0) + filter = NULL; + + return eth_dev_get_port_regs(port_id, d, filter); +} + RTE_INIT(ethdev_init_telemetry) { rte_telemetry_register_cmd("/ethdev/list", eth_dev_handle_port_list, @@ -1436,4 +1564,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns TM Level Capabilities info for a port. Parameters: int port_id, int level_id (see tm_capability for the max)"); rte_telemetry_register_cmd("/ethdev/tm_node_capability", eth_dev_handle_port_tm_node_caps, "Returns TM Node Capabilities info for a port. Parameters: int port_id, int node_id (see tm_capability for the max)"); + rte_telemetry_register_cmd("/ethdev/regs", eth_dev_handle_port_regs, + "Returns all or filtered registers info for a port. Parameters: int port_id, string module_name (Optional if show all)"); } -- 2.33.0