From patchwork Wed Jul 6 07:52:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aman Kumar X-Patchwork-Id: 113746 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8DBA9A0540; Wed, 6 Jul 2022 09:59:28 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0CC9442BD9; Wed, 6 Jul 2022 09:57:24 +0200 (CEST) Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) by mails.dpdk.org (Postfix) with ESMTP id 076B840DDE for ; Wed, 6 Jul 2022 09:57:22 +0200 (CEST) Received: by mail-pl1-f171.google.com with SMTP id d5so12966874plo.12 for ; Wed, 06 Jul 2022 00:57:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vvdntech-in.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Gdmhnw1pzKwwhXRdoaBwCnI5+Xqn3aP9sxhbXPOi050=; b=lik4hzLQYFPsRgJ4LPUfwrKqD2DIFbvpLw7WRNFgaE4fdujeeuSOzf1MsR7eGkMKqO xeET2JVXX8cnmvTin6iwNLsF5YEzsE7xmU/jTWmeH2MrZkXR9DPuekBds11SeCXSVOXZ +zeiooMVH0V1MXtj+zmOroQkhcDheR/PDc4rIF2Id7C8wnGvWwh177qp5OWPqee1IhMj rGYpdEeGEnCPqQ8FCMnqirxcKWF9B2VE2X0o73tsPksrcWxN4YcT7fGAFCIPLzjfgjDr 2BFDJcT7ylk7Q4SjBHrALtiQHESEQv5UwKjLetYGk8mYQV5L3IfW6C3DVjCMQh2gdhG1 cL9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Gdmhnw1pzKwwhXRdoaBwCnI5+Xqn3aP9sxhbXPOi050=; b=AKvCYFfuH5fEOW5X8sBv6+B77kcJpkpmBo52kKSJILNUP7AL75v1sEO3/IZjygl/I5 rjVbDtlwA+w4D+iHcP+NJcpm5MIkTv/ZuYYlL6SlXepFicb6o604bnus/ni0dVEwttU3 phGITMi5EygXc7OBFaAhQG8MOOds1+2W+PMuppw4M6nSq0jJsZ0KDI9/03xCcxhXthsx V8Gifg9BmLrVebUsQwMy3P5BMxX3jBBfLtkGbW1/LO0BoxxYHDomUODjanq23YZBrSAE k6XPKPzjoh/BfB9ZCvEW9yfGd9ykUah1/OvBUTiaGBmnDMQ1o+t/IJiDxzUeZ0SqYNQM UAmw== X-Gm-Message-State: AJIora8fSVUSVCW49gMeeOBUQp2kZEnqwS++jVu6TTNJCcOFPnaCXyvk gqr2/NtQfw+qm2qXtqdAcamehASsgYOsOIo1 X-Google-Smtp-Source: AGRyM1vQ+4Q9VOSwnpXT8XriYB88rThnPBXaNv1K25REmlk2gX6afgcRwlEb5Kz3r1/h1ngq2sQPQg== X-Received: by 2002:a17:903:11c6:b0:167:90e5:59c2 with SMTP id q6-20020a17090311c600b0016790e559c2mr45752239plh.50.1657094241022; Wed, 06 Jul 2022 00:57:21 -0700 (PDT) Received: from 470--5GDC--BLR.blore.vvdntech.com ([106.51.39.131]) by smtp.gmail.com with ESMTPSA id r4-20020a17090a438400b001ef81574355sm7378805pjg.12.2022.07.06.00.57.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Jul 2022 00:57:20 -0700 (PDT) From: Aman Kumar To: dev@dpdk.org Cc: maxime.coquelin@redhat.com, david.marchand@redhat.com, aman.kumar@vvdntech.in Subject: [RFC PATCH 28/29] net/qdma: add additional debug APIs Date: Wed, 6 Jul 2022 13:22:18 +0530 Message-Id: <20220706075219.517046-29-aman.kumar@vvdntech.in> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220706075219.517046-1-aman.kumar@vvdntech.in> References: <20220706075219.517046-1-aman.kumar@vvdntech.in> MIME-Version: 1.0 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 implements function to debug and dump PMD/QDMA specific data. Signed-off-by: Aman Kumar --- drivers/net/qdma/meson.build | 1 + drivers/net/qdma/qdma_xdebug.c | 1072 ++++++++++++++++++++++++++++++++ 2 files changed, 1073 insertions(+) create mode 100644 drivers/net/qdma/qdma_xdebug.c diff --git a/drivers/net/qdma/meson.build b/drivers/net/qdma/meson.build index 1dc4392666..7ba2c89442 100644 --- a/drivers/net/qdma/meson.build +++ b/drivers/net/qdma/meson.build @@ -29,6 +29,7 @@ sources = files( 'qdma_user.c', 'qdma_rxtx.c', 'qdma_vf_ethdev.c', + 'qdma_xdebug.c', 'qdma_access/eqdma_soft_access/eqdma_soft_access.c', 'qdma_access/eqdma_soft_access/eqdma_soft_reg_dump.c', 'qdma_access/qdma_s80_hard_access/qdma_s80_hard_access.c', diff --git a/drivers/net/qdma/qdma_xdebug.c b/drivers/net/qdma/qdma_xdebug.c new file mode 100644 index 0000000000..43f8380465 --- /dev/null +++ b/drivers/net/qdma/qdma_xdebug.c @@ -0,0 +1,1072 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2022 Xilinx, Inc. All rights reserved. + * Copyright(c) 2022 VVDN Technologies Private Limited. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qdma.h" +#include "rte_pmd_qdma.h" +#include "qdma_access_common.h" +#include "qdma_reg_dump.h" +#include "qdma_mbox_protocol.h" +#include "qdma_mbox.h" + +#define xdebug_info(args...) rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1,\ + ## args) +#define xdebug_error(args...) rte_log(RTE_LOG_ERR, RTE_LOGTYPE_USER1,\ + ## args) + +struct xdebug_desc_param { + uint16_t queue; + int start; + int end; + enum rte_pmd_qdma_xdebug_desc_type type; +}; + +const char *qdma_desc_eng_mode_info[QDMA_DESC_ENG_MODE_MAX] = { + "Internal and Bypass mode", + "Bypass only mode", + "Internal only mode" +}; + +static void print_header(const char *str) +{ + xdebug_info("\n\n%s\n\n", str); +} + +static int qdma_h2c_struct_dump(uint8_t port_id, uint16_t queue) +{ + struct rte_eth_dev *dev; + struct qdma_tx_queue *tx_q; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + tx_q = (struct qdma_tx_queue *)dev->data->tx_queues[queue]; + + if (queue >= dev->data->nb_tx_queues) { + xdebug_info("TX queue_id=%d not configured\n", queue); + return -EINVAL; + } + + if (tx_q) { + print_header("***********TX Queue struct************"); + xdebug_info("\t\t wb_pidx :%x\n", + tx_q->wb_status->pidx); + xdebug_info("\t\t wb_cidx :%x\n", + tx_q->wb_status->cidx); + xdebug_info("\t\t h2c_pidx :%x\n", + tx_q->q_pidx_info.pidx); + xdebug_info("\t\t tx_fl_tail :%x\n", + tx_q->tx_fl_tail); + xdebug_info("\t\t tx_desc_pend :%x\n", + tx_q->tx_desc_pend); + xdebug_info("\t\t nb_tx_desc :%x\n", + tx_q->nb_tx_desc); + xdebug_info("\t\t st_mode :%x\n", + tx_q->st_mode); + xdebug_info("\t\t tx_deferred_start :%x\n", + tx_q->tx_deferred_start); + xdebug_info("\t\t en_bypass :%x\n", + tx_q->en_bypass); + xdebug_info("\t\t bypass_desc_sz :%x\n", + tx_q->bypass_desc_sz); + xdebug_info("\t\t func_id :%x\n", + tx_q->func_id); + xdebug_info("\t\t port_id :%x\n", + tx_q->port_id); + xdebug_info("\t\t ringszidx :%x\n", + tx_q->ringszidx); + } + + return 0; +} + +static int qdma_c2h_struct_dump(uint8_t port_id, uint16_t queue) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + struct qdma_rx_queue *rx_q; + enum qdma_ip_type ip_type; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + ip_type = (enum qdma_ip_type)qdma_dev->ip_type; + rx_q = (struct qdma_rx_queue *)dev->data->rx_queues[queue]; + + if (queue >= dev->data->nb_rx_queues) { + xdebug_info("RX queue_id=%d not configured\n", queue); + return -EINVAL; + } + + if (rx_q) { + print_header(" ***********RX Queue struct********** "); + xdebug_info("\t\t wb_pidx :%x\n", + rx_q->wb_status->pidx); + xdebug_info("\t\t wb_cidx :%x\n", + rx_q->wb_status->cidx); + xdebug_info("\t\t rx_tail (ST) :%x\n", + rx_q->rx_tail); + xdebug_info("\t\t c2h_pidx :%x\n", + rx_q->q_pidx_info.pidx); + xdebug_info("\t\t rx_cmpt_cidx :%x\n", + rx_q->cmpt_cidx_info.wrb_cidx); + xdebug_info("\t\t cmpt_desc_len :%x\n", + rx_q->cmpt_desc_len); + xdebug_info("\t\t rx_buff_size :%x\n", + rx_q->rx_buff_size); + xdebug_info("\t\t nb_rx_desc :%x\n", + rx_q->nb_rx_desc); + xdebug_info("\t\t nb_rx_cmpt_desc :%x\n", + rx_q->nb_rx_cmpt_desc); + xdebug_info("\t\t ep_addr :%x\n", + rx_q->ep_addr); + xdebug_info("\t\t st_mode :%x\n", + rx_q->st_mode); + xdebug_info("\t\t rx_deferred_start :%x\n", + rx_q->rx_deferred_start); + xdebug_info("\t\t en_prefetch :%x\n", + rx_q->en_prefetch); + xdebug_info("\t\t en_bypass :%x\n", + rx_q->en_bypass); + xdebug_info("\t\t dump_immediate_data :%x\n", + rx_q->dump_immediate_data); + xdebug_info("\t\t en_bypass_prefetch :%x\n", + rx_q->en_bypass_prefetch); + + if (!(ip_type == QDMA_VERSAL_HARD_IP)) + xdebug_info("\t\t dis_overflow_check :%x\n", + rx_q->dis_overflow_check); + + xdebug_info("\t\t bypass_desc_sz :%x\n", + rx_q->bypass_desc_sz); + xdebug_info("\t\t ringszidx :%x\n", + rx_q->ringszidx); + xdebug_info("\t\t cmpt_ringszidx :%x\n", + rx_q->cmpt_ringszidx); + xdebug_info("\t\t buffszidx :%x\n", + rx_q->buffszidx); + xdebug_info("\t\t threshidx :%x\n", + rx_q->threshidx); + xdebug_info("\t\t timeridx :%x\n", + rx_q->timeridx); + xdebug_info("\t\t triggermode :%x\n", + rx_q->triggermode); + } + + return 0; +} + +static int qdma_config_read_reg_list(struct rte_eth_dev *dev, + uint16_t group_num, + uint16_t *num_regs, struct qdma_reg_data *reg_list) +{ + struct qdma_pci_dev *qdma_dev = dev->data->dev_private; + struct qdma_mbox_msg *m = qdma_mbox_msg_alloc(); + int rv; + + if (!m) + return -ENOMEM; + + qdma_mbox_compose_reg_read(qdma_dev->func_id, group_num, m->raw_data); + + rv = qdma_mbox_msg_send(dev, m, MBOX_OP_RSP_TIMEOUT); + if (rv < 0) { + if (rv != -ENODEV) + xdebug_error("reg read mbox failed with error = %d\n", + rv); + goto err_out; + } + + rv = qdma_mbox_vf_reg_list_get(m->raw_data, num_regs, reg_list); + if (rv < 0) { + xdebug_error("qdma_mbox_vf_reg_list_get failed with error = %d\n", + rv); + goto err_out; + } + +err_out: + qdma_mbox_msg_free(m); + return rv; +} + +static int qdma_config_reg_dump(uint8_t port_id) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + enum qdma_ip_type ip_type; + char *buf = NULL; + int buflen; + int ret; + struct qdma_reg_data *reg_list; + uint16_t num_regs = 0, group_num = 0; + int len = 0, rcv_len = 0, reg_len = 0; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + ip_type = (enum qdma_ip_type)qdma_dev->ip_type; + + if (qdma_dev->is_vf) { + reg_len = (QDMA_MAX_REGISTER_DUMP * + sizeof(struct qdma_reg_data)); + reg_list = (struct qdma_reg_data *)rte_zmalloc("QDMA_DUMP_REG_VF", + reg_len, RTE_CACHE_LINE_SIZE); + if (!reg_list) { + xdebug_error("Unable to allocate memory for VF dump for reglist " + "size %d\n", reg_len); + return -ENOMEM; + } + + ret = qdma_acc_reg_dump_buf_len(dev, ip_type, &buflen); + if (ret < 0) { + xdebug_error("Failed to get register dump buffer length\n"); + return ret; + } + /* allocate memory for register dump */ + buf = (char *)rte_zmalloc("QDMA_DUMP_BUF_VF", buflen, + RTE_CACHE_LINE_SIZE); + if (!buf) { + xdebug_error("Unable to allocate memory for reg dump " + "size %d\n", buflen); + rte_free(reg_list); + return -ENOMEM; + } + xdebug_info("FPGA Config Registers for port_id: %d\n--------\n", + port_id); + xdebug_info(" Offset Name " + " Value(Hex) Value(Dec)\n"); + + for (group_num = 0; group_num < QDMA_REG_READ_GROUP_3; + group_num++) { + /* Reset the reg_list with 0's */ + memset(reg_list, 0, (QDMA_MAX_REGISTER_DUMP * + sizeof(struct qdma_reg_data))); + ret = qdma_config_read_reg_list(dev, + group_num, &num_regs, reg_list); + if (ret < 0) { + xdebug_error("Failed to read config registers " + "size %d, err = %d\n", buflen, ret); + rte_free(reg_list); + rte_free(buf); + return ret; + } + + rcv_len = qdma_acc_dump_config_reg_list(dev, + ip_type, num_regs, + reg_list, buf + len, buflen - len); + if (len < 0) { + xdebug_error("Failed to dump config regs " + "size %d, err = %d\n", buflen, ret); + rte_free(reg_list); + rte_free(buf); + return ret; + } + len += rcv_len; + } + if (ret < 0) { + xdebug_error("Insufficient space to dump Config Bar register values\n"); + rte_free(reg_list); + rte_free(buf); + return qdma_get_error_code(ret); + } + xdebug_info("%s\n", buf); + rte_free(reg_list); + rte_free(buf); + } else { + ret = qdma_acc_reg_dump_buf_len(dev, + ip_type, &buflen); + if (ret < 0) { + xdebug_error("Failed to get register dump buffer length\n"); + return ret; + } + + /* allocate memory for register dump */ + buf = (char *)rte_zmalloc("QDMA_REG_DUMP", buflen, + RTE_CACHE_LINE_SIZE); + if (!buf) { + xdebug_error("Unable to allocate memory for reg dump " + "size %d\n", buflen); + return -ENOMEM; + } + xdebug_info("FPGA Config Registers for port_id: %d\n--------\n", + port_id); + xdebug_info(" Offset Name " + " Value(Hex) Value(Dec)\n"); + + ret = qdma_acc_dump_config_regs(dev, qdma_dev->is_vf, + ip_type, buf, buflen); + if (ret < 0) { + xdebug_error + ("Insufficient space to dump Config Bar register values\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + xdebug_info("%s\n", buf); + rte_free(buf); + } + + return 0; +} + +static int qdma_device_dump(uint8_t port_id) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + + xdebug_info("\n*** QDMA Device struct for port_id: %d ***\n\n", + port_id); + + xdebug_info("\t\t config BAR index :%x\n", + qdma_dev->config_bar_idx); + xdebug_info("\t\t AXI Master Lite BAR index :%x\n", + qdma_dev->user_bar_idx); + xdebug_info("\t\t AXI Bridge Master BAR index :%x\n", + qdma_dev->bypass_bar_idx); + xdebug_info("\t\t qsets enable :%x\n", + qdma_dev->qsets_en); + xdebug_info("\t\t queue base :%x\n", + qdma_dev->queue_base); + xdebug_info("\t\t pf :%x\n", + qdma_dev->func_id); + xdebug_info("\t\t cmpt desc length :%x\n", + qdma_dev->cmpt_desc_len); + xdebug_info("\t\t c2h bypass mode :%x\n", + qdma_dev->c2h_bypass_mode); + xdebug_info("\t\t h2c bypass mode :%x\n", + qdma_dev->h2c_bypass_mode); + xdebug_info("\t\t trigger mode :%x\n", + qdma_dev->trigger_mode); + xdebug_info("\t\t timer count :%x\n", + qdma_dev->timer_count); + xdebug_info("\t\t is vf :%x\n", + qdma_dev->is_vf); + xdebug_info("\t\t is master :%x\n", + qdma_dev->is_master); + xdebug_info("\t\t enable desc prefetch :%x\n", + qdma_dev->en_desc_prefetch); + xdebug_info("\t\t ip type :%x\n", + qdma_dev->ip_type); + xdebug_info("\t\t vivado release :%x\n", + qdma_dev->vivado_rel); + xdebug_info("\t\t rtl version :%x\n", + qdma_dev->rtl_version); + xdebug_info("\t\t is queue conigured :%x\n", + qdma_dev->init_q_range); + + xdebug_info("\n\t ***** Device Capabilities *****\n"); + xdebug_info("\t\t number of PFs :%x\n", + qdma_dev->dev_cap.num_pfs); + xdebug_info("\t\t number of Queues :%x\n", + qdma_dev->dev_cap.num_qs); + xdebug_info("\t\t FLR present :%x\n", + qdma_dev->dev_cap.flr_present); + xdebug_info("\t\t ST mode enable :%x\n", + qdma_dev->dev_cap.st_en); + xdebug_info("\t\t MM mode enable :%x\n", + qdma_dev->dev_cap.mm_en); + xdebug_info("\t\t MM with compt enable :%x\n", + qdma_dev->dev_cap.mm_cmpt_en); + xdebug_info("\t\t Mailbox enable :%x\n", + qdma_dev->dev_cap.mailbox_en); + xdebug_info("\t\t Num of MM channels :%x\n", + qdma_dev->dev_cap.mm_channel_max); + xdebug_info("\t\t Descriptor engine mode :%s\n", + qdma_desc_eng_mode_info[qdma_dev->dev_cap.desc_eng_mode]); + xdebug_info("\t\t Debug mode enable :%x\n", + qdma_dev->dev_cap.debug_mode); + + return 0; +} + +static int qdma_descq_context_read_vf(struct rte_eth_dev *dev, + unsigned int qid_hw, bool st_mode, + enum qdma_dev_q_type q_type, + struct qdma_descq_context *context) +{ + struct qdma_pci_dev *qdma_dev = dev->data->dev_private; + struct qdma_mbox_msg *m = qdma_mbox_msg_alloc(); + enum mbox_cmpt_ctxt_type cmpt_ctxt_type = QDMA_MBOX_CMPT_CTXT_NONE; + int rv; + + if (!m) + return -ENOMEM; + + if (!st_mode) { + if (q_type == QDMA_DEV_Q_TYPE_CMPT) + cmpt_ctxt_type = QDMA_MBOX_CMPT_CTXT_ONLY; + else + cmpt_ctxt_type = QDMA_MBOX_CMPT_CTXT_NONE; + } else { + if (q_type == QDMA_DEV_Q_TYPE_C2H) + cmpt_ctxt_type = QDMA_MBOX_CMPT_WITH_ST; + } + + qdma_mbox_compose_vf_qctxt_read(qdma_dev->func_id, + qid_hw, st_mode, q_type, cmpt_ctxt_type, m->raw_data); + + rv = qdma_mbox_msg_send(dev, m, MBOX_OP_RSP_TIMEOUT); + if (rv < 0) { + xdebug_error("%x, qid_hw 0x%x, mbox failed for vf q context %d.\n", + qdma_dev->func_id, qid_hw, rv); + goto free_msg; + } + + rv = qdma_mbox_vf_context_get(m->raw_data, context); + if (rv < 0) { + xdebug_error("%x, failed to get vf queue context info %d.\n", + qdma_dev->func_id, rv); + goto free_msg; + } + +free_msg: + qdma_mbox_msg_free(m); + return rv; +} + +static int qdma_c2h_context_dump(uint8_t port_id, uint16_t queue) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + struct qdma_descq_context queue_context; + enum qdma_dev_q_type q_type; + enum qdma_ip_type ip_type; + uint16_t qid; + uint8_t st_mode; + char *buf = NULL; + uint32_t buflen = 0; + int ret = 0; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + qid = qdma_dev->queue_base + queue; + ip_type = (enum qdma_ip_type)qdma_dev->ip_type; + st_mode = qdma_dev->q_info[qid].queue_mode; + q_type = QDMA_DEV_Q_TYPE_C2H; + + if (queue >= dev->data->nb_rx_queues) { + xdebug_info("RX queue_id=%d not configured\n", queue); + return -EINVAL; + } + + xdebug_info("\n ***** C2H Queue Contexts on port_id: %d for q_id: %d *****\n", + port_id, qid); + + ret = qdma_acc_context_buf_len(dev, ip_type, st_mode, + q_type, &buflen); + if (ret < 0) { + xdebug_error("Failed to get context buffer length,\n"); + return ret; + } + + /* allocate memory for csr dump */ + buf = (char *)rte_zmalloc("QDMA_C2H_CONTEXT_DUMP", + buflen, RTE_CACHE_LINE_SIZE); + if (!buf) { + xdebug_error("Unable to allocate memory for c2h context dump " + "size %d\n", buflen); + return -ENOMEM; + } + + if (qdma_dev->is_vf) { + ret = qdma_descq_context_read_vf(dev, qid, + st_mode, q_type, &queue_context); + if (ret < 0) { + xdebug_error("Failed to read c2h queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + + ret = qdma_acc_dump_queue_context(dev, ip_type, + st_mode, q_type, &queue_context, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to dump c2h queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + } else { + ret = qdma_acc_read_dump_queue_context(dev, ip_type, + qid, st_mode, q_type, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to read and dump c2h queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + } + + xdebug_info("%s\n", buf); + rte_free(buf); + + return 0; +} + +static int qdma_h2c_context_dump(uint8_t port_id, uint16_t queue) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + struct qdma_descq_context queue_context; + enum qdma_dev_q_type q_type; + enum qdma_ip_type ip_type; + uint32_t buflen = 0; + uint16_t qid; + uint8_t st_mode; + char *buf = NULL; + int ret = 0; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + qid = qdma_dev->queue_base + queue; + ip_type = (enum qdma_ip_type)qdma_dev->ip_type; + st_mode = qdma_dev->q_info[qid].queue_mode; + q_type = QDMA_DEV_Q_TYPE_H2C; + + if (queue >= dev->data->nb_tx_queues) { + xdebug_info("TX queue_id=%d not configured\n", queue); + return -EINVAL; + } + + xdebug_info("\n ***** H2C Queue Contexts on port_id: %d for q_id: %d *****\n", + port_id, qid); + + ret = qdma_acc_context_buf_len(dev, ip_type, st_mode, + q_type, &buflen); + if (ret < 0) { + xdebug_error("Failed to get context buffer length,\n"); + return ret; + } + + /* allocate memory for csr dump */ + buf = (char *)rte_zmalloc("QDMA_H2C_CONTEXT_DUMP", + buflen, RTE_CACHE_LINE_SIZE); + if (!buf) { + xdebug_error("Unable to allocate memory for h2c context dump " + "size %d\n", buflen); + return -ENOMEM; + } + + if (qdma_dev->is_vf) { + ret = qdma_descq_context_read_vf(dev, qid, + st_mode, q_type, &queue_context); + if (ret < 0) { + xdebug_error("Failed to read h2c queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + + ret = qdma_acc_dump_queue_context(dev, ip_type, + st_mode, q_type, &queue_context, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to dump h2c queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + } else { + ret = qdma_acc_read_dump_queue_context(dev, ip_type, + qid, st_mode, q_type, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to read and dump h2c queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + } + + xdebug_info("%s\n", buf); + rte_free(buf); + + return 0; +} + +static int qdma_cmpt_context_dump(uint8_t port_id, uint16_t queue) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + struct qdma_descq_context queue_context; + enum qdma_dev_q_type q_type; + enum qdma_ip_type ip_type; + uint32_t buflen; + uint16_t qid; + uint8_t st_mode; + char *buf = NULL; + int ret = 0; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + qid = qdma_dev->queue_base + queue; + ip_type = (enum qdma_ip_type)qdma_dev->ip_type; + st_mode = qdma_dev->q_info[qid].queue_mode; + q_type = QDMA_DEV_Q_TYPE_CMPT; + + if (queue >= dev->data->nb_rx_queues) { + xdebug_info("RX queue_id=%d not configured\n", queue); + return -EINVAL; + } + + xdebug_info("\n ***** CMPT Queue Contexts on port_id: %d for q_id: %d *****\n", + port_id, qid); + + ret = qdma_acc_context_buf_len(dev, ip_type, + st_mode, q_type, &buflen); + if (ret < 0) { + xdebug_error("Failed to get context buffer length\n"); + return ret; + } + + /* allocate memory for csr dump */ + buf = (char *)rte_zmalloc("QDMA_CMPT_CONTEXT_DUMP", + buflen, RTE_CACHE_LINE_SIZE); + if (!buf) { + xdebug_error("Unable to allocate memory for cmpt context dump " + "size %d\n", buflen); + return -ENOMEM; + } + + if (qdma_dev->is_vf) { + ret = qdma_descq_context_read_vf(dev, qid, + st_mode, q_type, &queue_context); + if (ret < 0) { + xdebug_error("Failed to read cmpt queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + + ret = qdma_acc_dump_queue_context(dev, ip_type, + st_mode, q_type, + &queue_context, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to dump cmpt queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + } else { + ret = qdma_acc_read_dump_queue_context(dev, + ip_type, qid, st_mode, + q_type, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to read and dump cmpt queue context\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + } + + xdebug_info("%s\n", buf); + rte_free(buf); + + return 0; +} + +static int qdma_queue_desc_dump(uint8_t port_id, + struct xdebug_desc_param *param) +{ + struct rte_eth_dev *dev; + struct qdma_rx_queue *rxq; + struct qdma_tx_queue *txq; + uint8_t *rx_ring_bypass = NULL; + uint8_t *tx_ring_bypass = NULL; + char str[50]; + int x; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + + switch (param->type) { + case RTE_PMD_QDMA_XDEBUG_DESC_C2H: + + if (param->queue >= dev->data->nb_rx_queues) { + xdebug_info("queue_id=%d not configured", + param->queue); + return -1; + } + + rxq = (struct qdma_rx_queue *) + dev->data->rx_queues[param->queue]; + + if (rxq == NULL) { + xdebug_info("Caught NULL pointer for queue_id: %d\n", + param->queue); + return -1; + } + + if (rxq->status != RTE_ETH_QUEUE_STATE_STARTED) { + xdebug_info("Queue_id %d is not yet started\n", + param->queue); + return -1; + } + + if (param->start < 0 || param->start > rxq->nb_rx_desc) + param->start = 0; + if (param->end <= param->start || + param->end > rxq->nb_rx_desc) + param->end = rxq->nb_rx_desc; + + if (rxq->en_bypass && rxq->bypass_desc_sz != 0) { + rx_ring_bypass = (uint8_t *)rxq->rx_ring; + + xdebug_info("\n===== C2H bypass descriptors=====\n"); + for (x = param->start; x < param->end; x++) { + uint8_t *rx_bypass = + &rx_ring_bypass[x]; + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)rx_bypass, + rxq->bypass_desc_sz); + } + } else { + if (rxq->st_mode) { + struct qdma_ul_st_c2h_desc *rx_ring_st = + (struct qdma_ul_st_c2h_desc *)rxq->rx_ring; + + xdebug_info("\n===== C2H ring descriptors=====\n"); + for (x = param->start; x < param->end; x++) { + struct qdma_ul_st_c2h_desc *rx_st = + &rx_ring_st[x]; + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)rx_st, + sizeof(struct qdma_ul_st_c2h_desc)); + } + } else { + struct qdma_ul_mm_desc *rx_ring_mm = + (struct qdma_ul_mm_desc *)rxq->rx_ring; + xdebug_info("\n====== C2H ring descriptors======\n"); + for (x = param->start; x < param->end; x++) { + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)&rx_ring_mm[x], + sizeof(struct qdma_ul_mm_desc)); + } + } + } + break; + case RTE_PMD_QDMA_XDEBUG_DESC_CMPT: + + if (param->queue >= dev->data->nb_rx_queues) { + xdebug_info("queue_id=%d not configured", + param->queue); + return -1; + } + + rxq = (struct qdma_rx_queue *) + dev->data->rx_queues[param->queue]; + + if (rxq) { + if (rxq->status != RTE_ETH_QUEUE_STATE_STARTED) { + xdebug_info("Queue_id %d is not yet started\n", + param->queue); + return -1; + } + + if (param->start < 0 || + param->start > rxq->nb_rx_cmpt_desc) + param->start = 0; + if (param->end <= param->start || + param->end > rxq->nb_rx_cmpt_desc) + param->end = rxq->nb_rx_cmpt_desc; + + if (!rxq->st_mode) { + xdebug_info("Queue_id %d is not initialized " + "in Stream mode\n", param->queue); + return -1; + } + + xdebug_info("\n===== CMPT ring descriptors=====\n"); + for (x = param->start; x < param->end; x++) { + uint32_t *cmpt_ring = (uint32_t *) + ((uint64_t)(rxq->cmpt_ring) + + ((uint64_t)x * rxq->cmpt_desc_len)); + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)cmpt_ring, + rxq->cmpt_desc_len); + } + } + break; + case RTE_PMD_QDMA_XDEBUG_DESC_H2C: + + if (param->queue >= dev->data->nb_tx_queues) { + xdebug_info("queue_id=%d not configured", + param->queue); + return -1; + } + + txq = (struct qdma_tx_queue *) + dev->data->tx_queues[param->queue]; + + if (txq == NULL) { + xdebug_info("Caught NULL pointer for queue_id: %d\n", + param->queue); + return -1; + } + + if (txq->status != RTE_ETH_QUEUE_STATE_STARTED) { + xdebug_info("Queue_id %d is not yet started\n", + param->queue); + return -1; + } + + if (param->start < 0 || param->start > txq->nb_tx_desc) + param->start = 0; + if (param->end <= param->start || + param->end > txq->nb_tx_desc) + param->end = txq->nb_tx_desc; + + if (txq->en_bypass && txq->bypass_desc_sz != 0) { + tx_ring_bypass = (uint8_t *)txq->tx_ring; + + xdebug_info("\n====== H2C bypass descriptors=====\n"); + for (x = param->start; x < param->end; x++) { + uint8_t *tx_bypass = + &tx_ring_bypass[x]; + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)tx_bypass, + txq->bypass_desc_sz); + } + } else { + if (txq->st_mode) { + struct qdma_ul_st_h2c_desc *qdma_h2c_ring = + (struct qdma_ul_st_h2c_desc *)txq->tx_ring; + xdebug_info("\n====== H2C ring descriptors=====\n"); + for (x = param->start; x < param->end; x++) { + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)&qdma_h2c_ring[x], + sizeof(struct qdma_ul_st_h2c_desc)); + } + } else { + struct qdma_ul_mm_desc *tx_ring_mm = + (struct qdma_ul_mm_desc *)txq->tx_ring; + xdebug_info("\n===== H2C ring descriptors=====\n"); + for (x = param->start; x < param->end; x++) { + snprintf(str, sizeof(str), + "\nDescriptor ID %d\t", x); + rte_hexdump(stdout, str, + (const void *)&tx_ring_mm[x], + sizeof(struct qdma_ul_mm_desc)); + } + } + } + break; + default: + xdebug_info("Invalid ring selected\n"); + break; + } + return 0; +} + +int rte_pmd_qdma_dbg_regdump(uint8_t port_id) +{ + int err; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + err = qdma_config_reg_dump(port_id); + if (err) { + xdebug_error("Error dumping Global registers\n"); + return err; + } + return 0; +} + +int rte_pmd_qdma_dbg_reg_info_dump(uint8_t port_id, + uint32_t num_regs, uint32_t reg_addr) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + enum qdma_ip_type ip_type; + char *buf = NULL; + int buflen = QDMA_MAX_BUFLEN; + int ret; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + ip_type = (enum qdma_ip_type)qdma_dev->ip_type; + + /* allocate memory for register dump */ + buf = (char *)rte_zmalloc("QDMA_DUMP_BUF_REG_INFO", buflen, + RTE_CACHE_LINE_SIZE); + if (!buf) { + xdebug_error("Unable to allocate memory for reg info dump " + "size %d\n", buflen); + return -ENOMEM; + } + + ret = qdma_acc_dump_reg_info(dev, ip_type, + reg_addr, num_regs, buf, buflen); + if (ret < 0) { + xdebug_error("Failed to dump reg field values\n"); + rte_free(buf); + return qdma_get_error_code(ret); + } + xdebug_info("%s\n", buf); + rte_free(buf); + + return 0; +} + +int rte_pmd_qdma_dbg_qdevice(uint8_t port_id) +{ + int err; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + err = qdma_device_dump(port_id); + if (err) { + xdebug_error("Error dumping QDMA device\n"); + return err; + } + return 0; +} + +int rte_pmd_qdma_dbg_qinfo(uint8_t port_id, uint16_t queue) +{ + struct rte_eth_dev *dev; + struct qdma_pci_dev *qdma_dev; + uint16_t qid; + uint8_t st_mode; + int err; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + dev = &rte_eth_devices[port_id]; + qdma_dev = dev->data->dev_private; + qid = qdma_dev->queue_base + queue; + st_mode = qdma_dev->q_info[qid].queue_mode; + + err = qdma_h2c_context_dump(port_id, queue); + if (err) { + xdebug_error("Error dumping %d: %d\n", + queue, err); + return err; + } + + err = qdma_c2h_context_dump(port_id, queue); + if (err) { + xdebug_error("Error dumping %d: %d\n", + queue, err); + return err; + } + + if (!st_mode && qdma_dev->dev_cap.mm_cmpt_en) { + err = qdma_cmpt_context_dump(port_id, queue); + if (err) { + xdebug_error("Error dumping %d: %d\n", + queue, err); + return err; + } + } + + err = qdma_h2c_struct_dump(port_id, queue); + if (err) { + xdebug_error("Error dumping %d: %d\n", + queue, err); + return err; + } + + err = qdma_c2h_struct_dump(port_id, queue); + if (err) { + xdebug_error("Error dumping %d: %d\n", + queue, err); + return err; + } + + return 0; +} + +int rte_pmd_qdma_dbg_qdesc(uint8_t port_id, uint16_t queue, int start, + int end, enum rte_pmd_qdma_xdebug_desc_type type) +{ + struct xdebug_desc_param param; + int err; + + if (port_id >= rte_eth_dev_count_avail()) { + xdebug_error("Wrong port id %d\n", port_id); + return -EINVAL; + } + + param.queue = queue; + param.start = start; + param.end = end; + param.type = type; + + err = qdma_queue_desc_dump(port_id, ¶m); + if (err) { + xdebug_error("Error dumping %d: %d\n", + queue, err); + return err; + } + return 0; +}