* [PATCH] net/mlx5: add queue hardware object context dump
@ 2024-06-04 21:11 Kiran Vedere
2024-06-10 5:59 ` Slava Ovsiienko
2024-06-30 7:44 ` Raslan Darawsheh
0 siblings, 2 replies; 3+ messages in thread
From: Kiran Vedere @ 2024-06-04 21:11 UTC (permalink / raw)
To: dev; +Cc: matan, rasland, viacheslavo, dsosnowski
Add debug capability to mlx5 PMD to dump SQ/RQ/CQ HW object context for
a given port/queue. The context dump can provide some real-time
information on cause of certain Tx/Rx Failures.
Signed-off-by: Kiran Vedere <kiranv@nvidia.com>
---
.mailmap | 1 +
doc/guides/nics/mlx5.rst | 11 ++
doc/guides/rel_notes/release_24_07.rst | 5 +
drivers/common/mlx5/mlx5_devx_cmds.c | 87 +++++++++++++
drivers/common/mlx5/mlx5_devx_cmds.h | 9 ++
drivers/common/mlx5/mlx5_prm.h | 30 +++++
drivers/common/mlx5/version.map | 3 +
drivers/net/mlx5/mlx5_rx.c | 82 ++++++++++++
drivers/net/mlx5/mlx5_rxtx.c | 24 ++++
drivers/net/mlx5/mlx5_rxtx.h | 2 +
drivers/net/mlx5/mlx5_testpmd.c | 174 +++++++++++++++++++++++++
drivers/net/mlx5/mlx5_tx.c | 85 ++++++++++++
drivers/net/mlx5/rte_pmd_mlx5.h | 36 +++++
drivers/net/mlx5/version.map | 2 +
14 files changed, 551 insertions(+)
diff --git a/.mailmap b/.mailmap
index 87fa24714e..a5ee56fe0c 100644
--- a/.mailmap
+++ b/.mailmap
@@ -762,6 +762,7 @@ Kiran KN <kirankn@juniper.net>
Kiran Kumar K <kirankumark@marvell.com>
Kiran Kumar <kkokkilagadda@caviumnetworks.com> <kiran.kokkilagadda@caviumnetworks.com>
Kiran Patil <kiran.patil@intel.com>
+Kiran Vedere <kiranv@nvidia.com>
Kirill Rybalchenko <kirill.rybalchenko@intel.com>
Kishore Padmanabha <kishore.padmanabha@broadcom.com>
Klaus Degner <kd@allegro-packets.com>
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index b5928d40b2..40e36de7e8 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -2601,3 +2601,14 @@ Destroy GENEVE TLV parser for specific port::
This command doesn't destroy the global list,
For releasing options, ``flush`` command should be used.
+
+Dump RQ/SQ/CQ HW Context for debug purposes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Dump RQ/CQ HW Context for a given port/queue to a file:
+
+ testpmd> mlx5 port (port_id) queue (queue_id) dump rq_context (file_name)
+
+Dump SQ/CQ HW Context for a given port/queue to a file:
+
+ testpmd> mlx5 port (port_id) queue (queue_id) dump sq_context (file_name)
diff --git a/doc/guides/rel_notes/release_24_07.rst b/doc/guides/rel_notes/release_24_07.rst
index ffbe9ce051..c18a0be469 100644
--- a/doc/guides/rel_notes/release_24_07.rst
+++ b/doc/guides/rel_notes/release_24_07.rst
@@ -81,6 +81,11 @@ New Features
* Added SSE/NEON vector datapath.
+* **Add Queue Hardware object context dump.**
+
+ * Added debug capability to mlx5 PMD to dump SQ/RQ/CQ HW object context for
+ a given port/queue. The context dump could provide useful information when
+ debugging certain Rx/Tx Failures.
Removed Items
-------------
diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c
index 9952733c90..8d8af700f2 100644
--- a/drivers/common/mlx5/mlx5_devx_cmds.c
+++ b/drivers/common/mlx5/mlx5_devx_cmds.c
@@ -1594,6 +1594,35 @@ mlx5_devx_cmd_modify_rq(struct mlx5_devx_obj *rq,
return ret;
}
+/*
+ * Query RQ using DevX API.
+ *
+ * @param[in] rq_obj
+ * RQ Devx Object
+ * @param[out] out
+ * RQ Query Output
+ * @param[in] outlen
+ * RQ Query Output Length
+ *
+ * @return
+ * 0 if Query successful, else non-zero return value from devx_obj_query API
+ */
+int
+mlx5_devx_cmd_query_rq(struct mlx5_devx_obj *rq_obj, void *out, size_t outlen)
+{
+ uint32_t in[MLX5_ST_SZ_DW(query_rq_in)] = {0};
+ int rc;
+
+ MLX5_SET(query_rq_in, in, opcode, MLX5_CMD_OP_QUERY_RQ);
+ MLX5_SET(query_rq_in, in, rqn, rq_obj->id);
+ rc = mlx5_glue->devx_obj_query(rq_obj->obj, in, sizeof(in), out, outlen);
+ if (rc || MLX5_FW_STATUS(out)) {
+ DEVX_DRV_LOG(ERR, out, "RQ query", "rq_id", rq_obj->id);
+ return MLX5_DEVX_ERR_RC(rc);
+ }
+ return 0;
+}
+
/**
* Create RMP using DevX API.
*
@@ -2001,6 +2030,35 @@ mlx5_devx_cmd_modify_sq(struct mlx5_devx_obj *sq,
return ret;
}
+/*
+ * Query SQ using DevX API.
+ *
+ * @param[in] sq_obj
+ * SQ Devx Object
+ * @param[out] out
+ * SQ Query Output
+ * @param[in] outlen
+ * SQ Query Output Length
+ *
+ * @return
+ * 0 if Query successful, else non-zero return value from devx_obj_query API
+ */
+int
+mlx5_devx_cmd_query_sq(struct mlx5_devx_obj *sq_obj, void *out, size_t outlen)
+{
+ uint32_t in[MLX5_ST_SZ_DW(query_sq_in)] = {0};
+ int rc;
+
+ MLX5_SET(query_sq_in, in, opcode, MLX5_CMD_OP_QUERY_SQ);
+ MLX5_SET(query_sq_in, in, sqn, sq_obj->id);
+ rc = mlx5_glue->devx_obj_query(sq_obj->obj, in, sizeof(in), out, outlen);
+ if (rc || MLX5_FW_STATUS(out)) {
+ DEVX_DRV_LOG(ERR, out, "SQ query", "sq_id", sq_obj->id);
+ return MLX5_DEVX_ERR_RC(rc);
+ }
+ return 0;
+}
+
/**
* Create TIS using DevX API.
*
@@ -2202,6 +2260,35 @@ mlx5_devx_cmd_create_cq(void *ctx, struct mlx5_devx_cq_attr *attr)
return cq_obj;
}
+/*
+ * Query CQ using DevX API.
+ *
+ * @param[in] cq_obj
+ * CQ Devx Object
+ * @param[out] out
+ * CQ Query Output
+ * @param[in] outlen
+ * CQ Query Output Length
+ *
+ * @return
+ * 0 if Query successful, else non-zero return value from devx_obj_query API
+ */
+int
+mlx5_devx_cmd_query_cq(struct mlx5_devx_obj *cq_obj, void *out, size_t outlen)
+{
+ uint32_t in[MLX5_ST_SZ_DW(query_cq_in)] = {0};
+ int rc;
+
+ MLX5_SET(query_cq_in, in, opcode, MLX5_CMD_OP_QUERY_CQ);
+ MLX5_SET(query_cq_in, in, cqn, cq_obj->id);
+ rc = mlx5_glue->devx_obj_query(cq_obj->obj, in, sizeof(in), out, outlen);
+ if (rc || MLX5_FW_STATUS(out)) {
+ DEVX_DRV_LOG(ERR, out, "CQ query", "cq_id", cq_obj->id);
+ return MLX5_DEVX_ERR_RC(rc);
+ }
+ return 0;
+}
+
/**
* Create VIRTQ using DevX API.
*
diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h
index c79f8dc48d..540f002088 100644
--- a/drivers/common/mlx5/mlx5_devx_cmds.h
+++ b/drivers/common/mlx5/mlx5_devx_cmds.h
@@ -735,6 +735,15 @@ struct mlx5_devx_obj *mlx5_devx_cmd_create_sq(void *ctx,
__rte_internal
int mlx5_devx_cmd_modify_sq(struct mlx5_devx_obj *sq,
struct mlx5_devx_modify_sq_attr *sq_attr);
+__rte_internal
+int mlx5_devx_cmd_query_sq(struct mlx5_devx_obj *sq, void *out, size_t outlen);
+
+__rte_internal
+int mlx5_devx_cmd_query_cq(struct mlx5_devx_obj *cq, void *out, size_t outlen);
+
+__rte_internal
+int mlx5_devx_cmd_query_rq(struct mlx5_devx_obj *rq, void *out, size_t outlen);
+
__rte_internal
struct mlx5_devx_obj *mlx5_devx_cmd_create_tis(void *ctx,
struct mlx5_devx_tis_attr *tis_attr);
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 178a18a978..359f02f17c 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -1215,6 +1215,7 @@ enum {
MLX5_CMD_OP_QUERY_HCA_CAP = 0x100,
MLX5_CMD_OP_CREATE_MKEY = 0x200,
MLX5_CMD_OP_CREATE_CQ = 0x400,
+ MLX5_CMD_OP_QUERY_CQ = 0x402,
MLX5_CMD_OP_CREATE_QP = 0x500,
MLX5_CMD_OP_RST2INIT_QP = 0x502,
MLX5_CMD_OP_INIT2RTR_QP = 0x503,
@@ -1240,6 +1241,7 @@ enum {
MLX5_CMD_OP_MODIFY_TIR = 0x901,
MLX5_CMD_OP_CREATE_SQ = 0X904,
MLX5_CMD_OP_MODIFY_SQ = 0X905,
+ MLX5_CMD_OP_QUERY_SQ = 0x907,
MLX5_CMD_OP_CREATE_RQ = 0x908,
MLX5_CMD_OP_MODIFY_RQ = 0x909,
MLX5_CMD_OP_QUERY_RQ = 0x90b,
@@ -3140,6 +3142,14 @@ struct mlx5_ifc_sqc_bits {
struct mlx5_ifc_wq_bits wq;
};
+struct mlx5_ifc_query_sq_out_bits {
+ u8 status[0x8];
+ u8 reserved_at_8[0x18];
+ u8 syndrome[0x20];
+ u8 reserved_at_40[0xc0];
+ struct mlx5_ifc_sqc_bits sq_context;
+};
+
struct mlx5_ifc_query_sq_in_bits {
u8 opcode[0x10];
u8 reserved_at_10[0x10];
@@ -3361,6 +3371,26 @@ struct mlx5_ifc_create_cq_in_bits {
u8 pas[];
};
+struct mlx5_ifc_query_cq_out_bits {
+ u8 status[0x8];
+ u8 reserved_at_8[0x18];
+ u8 syndrome[0x20];
+ u8 reserved_at_40[0x40];
+ struct mlx5_ifc_cqc_bits cq_context;
+ u8 reserved_at_280[0x600];
+ u8 pas[][0x40];
+};
+
+struct mlx5_ifc_query_cq_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_at_10[0x10];
+ u8 reserved_at_20[0x10];
+ u8 op_mod[0x10];
+ u8 reserved_at_40[0x8];
+ u8 cqn[0x18];
+ u8 reserved_at_60[0x20];
+};
+
enum {
MLX5_GENERAL_OBJ_TYPE_GENEVE_TLV_OPT = 0x000b,
MLX5_GENERAL_OBJ_TYPE_DEK = 0x000c,
diff --git a/drivers/common/mlx5/version.map b/drivers/common/mlx5/version.map
index 589a450145..a2f72ef46a 100644
--- a/drivers/common/mlx5/version.map
+++ b/drivers/common/mlx5/version.map
@@ -51,6 +51,9 @@ INTERNAL {
mlx5_devx_cmd_modify_rq;
mlx5_devx_cmd_modify_rqt;
mlx5_devx_cmd_modify_sq;
+ mlx5_devx_cmd_query_sq;
+ mlx5_devx_cmd_query_rq;
+ mlx5_devx_cmd_query_cq;
mlx5_devx_cmd_modify_tir;
mlx5_devx_cmd_modify_virtq;
mlx5_devx_cmd_qp_query_tis_td;
diff --git a/drivers/net/mlx5/mlx5_rx.c b/drivers/net/mlx5/mlx5_rx.c
index cc087348a4..f241809e08 100644
--- a/drivers/net/mlx5/mlx5_rx.c
+++ b/drivers/net/mlx5/mlx5_rx.c
@@ -1586,3 +1586,85 @@ int rte_pmd_mlx5_host_shaper_config(int port_id, uint8_t rate,
return mlxreg_host_shaper_config(dev, priv->sh->lwm_triggered,
priv->sh->host_shaper_rate);
}
+
+/**
+ * Dump RQ/CQ Context to a file.
+ *
+ * @param[in] port_id
+ * Port ID
+ * @param[in] queue_id
+ * Queue ID
+ * @param[in] filename
+ * Name of file to dump the Rx Queue Context
+ *
+ * @return
+ * 0 for Success, non-zero value depending on failure type
+ */
+int rte_pmd_mlx5_rxq_dump_contexts(uint16_t port_id, uint16_t queue_id, const char *filename)
+{
+ struct rte_eth_dev *dev;
+ struct mlx5_rxq_priv *rxq;
+ struct mlx5_rxq_ctrl *rxq_ctrl;
+ struct mlx5_rxq_obj *rxq_obj;
+ struct mlx5_devx_rq *rq;
+ struct mlx5_devx_cq *cq;
+ struct mlx5_devx_obj *rq_devx_obj;
+ struct mlx5_devx_obj *cq_devx_obj;
+
+ uint32_t rq_out[MLX5_ST_SZ_DW(query_rq_out)] = {0};
+ uint32_t cq_out[MLX5_ST_SZ_DW(query_cq_out)] = {0};
+
+ int ret;
+ FILE *fd;
+ MKSTR(path, "./%s", filename);
+
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -ENODEV;
+
+ if (rte_eth_rx_queue_is_valid(port_id, queue_id))
+ return -EINVAL;
+
+ fd = fopen(path, "w");
+ if (!fd) {
+ rte_errno = errno;
+ return -EIO;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ rxq = mlx5_rxq_ref(dev, queue_id);
+ rxq_ctrl = rxq->ctrl;
+ rxq_obj = rxq_ctrl->obj;
+ rq = &rxq->devx_rq;
+ cq = &rxq_obj->cq_obj;
+ rq_devx_obj = rq->rq;
+ cq_devx_obj = cq->cq;
+
+ do {
+ ret = mlx5_devx_cmd_query_rq(rq_devx_obj, rq_out, sizeof(rq_out));
+ if (ret)
+ break;
+
+ /* Dump rq query output to file */
+ MKSTR(rq_headline, "RQ DevX ID = %u Port = %u Queue index = %u ",
+ rq_devx_obj->id, port_id, queue_id);
+ mlx5_dump_to_file(fd, NULL, rq_headline, 0);
+ mlx5_dump_to_file(fd, "Query RQ Dump:",
+ (const void *)((uintptr_t)rq_out),
+ sizeof(rq_out));
+
+ ret = mlx5_devx_cmd_query_cq(cq_devx_obj, cq_out, sizeof(cq_out));
+ if (ret)
+ break;
+
+ /* Dump cq query output to file */
+ MKSTR(cq_headline, "CQ DevX ID = %u Port = %u Queue index = %u ",
+ cq_devx_obj->id, port_id, queue_id);
+ mlx5_dump_to_file(fd, NULL, cq_headline, 0);
+ mlx5_dump_to_file(fd, "Query CQ Dump:",
+ (const void *)((uintptr_t)cq_out),
+ sizeof(cq_out));
+ } while (false);
+
+ fclose(fd);
+ return ret;
+}
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index d3d4470acd..eadadcdffb 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -353,6 +353,30 @@ mlx5_dump_debug_information(const char *fname, const char *hex_title,
fclose(fd);
}
+/**
+ * Dump information to a logfile
+ *
+ * @param fd
+ * File descriptor to logfile. File descriptor open/close is managed by caller.
+ * @param title
+ * If not NULL this string is printed as a header to the output
+ * and the output will be in hexadecimal view.
+ * @param buf
+ * This is the buffer address to print out.
+ * @param len
+ * The number of bytes to dump out.
+ */
+void
+mlx5_dump_to_file(FILE *fd, const char *title,
+ const void *buf, unsigned int len)
+{
+ if (title)
+ rte_hexdump(fd, title, buf, len);
+ else
+ fprintf(fd, "%s", (const char *)buf);
+ fprintf(fd, "\n\n\n");
+}
+
/**
* Modify a Verbs/DevX queue state.
* This must be called from the primary process.
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index b109d50758..3fa9245769 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -38,6 +38,8 @@ void mlx5_set_cksum_table(void);
void mlx5_set_swp_types_table(void);
void mlx5_dump_debug_information(const char *path, const char *title,
const void *buf, unsigned int len);
+void mlx5_dump_to_file(FILE *fd, const char *title,
+ const void *buf, unsigned int len);
int mlx5_queue_state_modify_primary(struct rte_eth_dev *dev,
const struct mlx5_mp_arg_queue_state_modify *sm);
int mlx5_queue_state_modify(struct rte_eth_dev *dev,
diff --git a/drivers/net/mlx5/mlx5_testpmd.c b/drivers/net/mlx5/mlx5_testpmd.c
index 5bc4dd0551..1bb5a89559 100644
--- a/drivers/net/mlx5/mlx5_testpmd.c
+++ b/drivers/net/mlx5/mlx5_testpmd.c
@@ -1201,6 +1201,170 @@ cmdline_parse_inst_t mlx5_cmd_destroy_tlv_options = {
}
};
+/* Dump SQ Context for a given port/queue*/
+struct mlx5_cmd_dump_sq_context_options {
+ cmdline_fixed_string_t mlx5;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t queue;
+ queueid_t queue_id;
+ cmdline_fixed_string_t dump;
+ cmdline_fixed_string_t sq_context;
+ cmdline_fixed_string_t file_name;
+};
+
+cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_mlx5 =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, mlx5,
+ "mlx5");
+cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_port =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, port,
+ "port");
+cmdline_parse_token_num_t mlx5_cmd_dump_sq_context_options_port_id =
+ TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, port_id,
+ RTE_UINT16);
+cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_queue =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, queue,
+ "queue");
+cmdline_parse_token_num_t mlx5_cmd_dump_sq_context_options_queue_id =
+ TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, queue_id,
+ RTE_UINT16);
+cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_dump =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, dump,
+ "dump");
+cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_sq_context =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, sq_context,
+ "sq_context");
+cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_file_name =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, file_name,
+ NULL);
+
+static void
+mlx5_cmd_dump_sq_context_options_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct mlx5_cmd_dump_sq_context_options *res = parsed_result;
+ int ret;
+
+ ret = rte_pmd_mlx5_txq_dump_contexts(res->port_id, res->queue_id, res->file_name);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ fprintf(stderr, "invalid queue index (%u), out of range\n",
+ res->queue_id);
+ break;
+ case -ENODEV:
+ fprintf(stderr, "invalid port_id %u\n", res->port_id);
+ break;
+ case -EIO:
+ fprintf(stderr, "File Access Error (%s)\n", strerror(rte_errno));
+ break;
+ default:
+ fprintf(stderr, "Unable to dump SQ/CQ HW Context (%s)\n", strerror(rte_errno));
+ }
+}
+
+cmdline_parse_inst_t mlx5_cmd_dump_sq_context_options = {
+ .f = mlx5_cmd_dump_sq_context_options_parsed,
+ .data = NULL,
+ .help_str = "mlx5 port <port_id> queue <queue_id> dump sq_context <file_name>",
+ .tokens = {
+ (void *)&mlx5_cmd_dump_sq_context_options_mlx5,
+ (void *)&mlx5_cmd_dump_sq_context_options_port,
+ (void *)&mlx5_cmd_dump_sq_context_options_port_id,
+ (void *)&mlx5_cmd_dump_sq_context_options_queue,
+ (void *)&mlx5_cmd_dump_sq_context_options_queue_id,
+ (void *)&mlx5_cmd_dump_sq_context_options_dump,
+ (void *)&mlx5_cmd_dump_sq_context_options_sq_context,
+ (void *)&mlx5_cmd_dump_sq_context_options_file_name,
+ NULL,
+ }
+};
+
+/* Dump RQ Context for a given port/queue*/
+struct mlx5_cmd_dump_rq_context_options {
+ cmdline_fixed_string_t mlx5;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t queue;
+ queueid_t queue_id;
+ cmdline_fixed_string_t dump;
+ cmdline_fixed_string_t rq_context;
+ cmdline_fixed_string_t file_name;
+};
+
+cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_mlx5 =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, mlx5,
+ "mlx5");
+cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_port =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, port,
+ "port");
+cmdline_parse_token_num_t mlx5_cmd_dump_rq_context_options_port_id =
+ TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, port_id,
+ RTE_UINT16);
+cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_queue =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, queue,
+ "queue");
+cmdline_parse_token_num_t mlx5_cmd_dump_rq_context_options_queue_id =
+ TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, queue_id,
+ RTE_UINT16);
+cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_dump =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, dump,
+ "dump");
+cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_rq_context =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, rq_context,
+ "rq_context");
+cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_file_name =
+ TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, file_name,
+ NULL);
+
+static void
+mlx5_cmd_dump_rq_context_options_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct mlx5_cmd_dump_rq_context_options *res = parsed_result;
+ int ret;
+
+ ret = rte_pmd_mlx5_rxq_dump_contexts(res->port_id, res->queue_id, res->file_name);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ fprintf(stderr, "invalid queue index (%u), out of range\n",
+ res->queue_id);
+ break;
+ case -ENODEV:
+ fprintf(stderr, "invalid port_id %u\n", res->port_id);
+ break;
+ case -EIO:
+ fprintf(stderr, "File Access Error (%s)\n", strerror(rte_errno));
+ break;
+ default:
+ fprintf(stderr, "Unable to dump RQ/CQ HW Context (%s)\n", strerror(rte_errno));
+ }
+}
+
+cmdline_parse_inst_t mlx5_cmd_dump_rq_context_options = {
+ .f = mlx5_cmd_dump_rq_context_options_parsed,
+ .data = NULL,
+ .help_str = "mlx5 port <port_id> queue <queue_id> dump rq_context <file_name>",
+ .tokens = {
+ (void *)&mlx5_cmd_dump_rq_context_options_mlx5,
+ (void *)&mlx5_cmd_dump_rq_context_options_port,
+ (void *)&mlx5_cmd_dump_rq_context_options_port_id,
+ (void *)&mlx5_cmd_dump_rq_context_options_queue,
+ (void *)&mlx5_cmd_dump_rq_context_options_queue_id,
+ (void *)&mlx5_cmd_dump_rq_context_options_dump,
+ (void *)&mlx5_cmd_dump_rq_context_options_rq_context,
+ (void *)&mlx5_cmd_dump_rq_context_options_file_name,
+ NULL,
+ }
+};
+
static struct testpmd_driver_commands mlx5_driver_cmds = {
.commands = {
{
@@ -1266,6 +1430,16 @@ static struct testpmd_driver_commands mlx5_driver_cmds = {
.help = "mlx5 port (port_id) destroy tlv_options\n"
" Destroy GENEVE TLV parser\n\n",
},
+ {
+ .ctx = &mlx5_cmd_dump_sq_context_options,
+ .help = "mlx5 port (port_id) queue (queue_id) dump sq_context (file_name)\n"
+ " Dump mlx5 SQ Context\n\n",
+ },
+ {
+ .ctx = &mlx5_cmd_dump_rq_context_options,
+ .help = "mlx5 port (port_id) queue (queue_id) dump rq_context (file_name)\n"
+ " Dump mlx5 RQ Context\n\n",
+ },
{
.ctx = NULL,
},
diff --git a/drivers/net/mlx5/mlx5_tx.c b/drivers/net/mlx5/mlx5_tx.c
index 1fe9521dfc..04f80bb9bd 100644
--- a/drivers/net/mlx5/mlx5_tx.c
+++ b/drivers/net/mlx5/mlx5_tx.c
@@ -761,3 +761,88 @@ mlx5_tx_burst_mode_get(struct rte_eth_dev *dev,
}
return -EINVAL;
}
+
+/**
+ * Dump SQ/CQ Context to a file.
+ *
+ * @param[in] port_id
+ * Port ID
+ * @param[in] queue_id
+ * Queue ID
+ * @param[in] filename
+ * Name of file to dump the Tx Queue Context
+ *
+ * @return
+ * 0 for success, non-zero value depending on failure.
+ *
+ */
+int rte_pmd_mlx5_txq_dump_contexts(uint16_t port_id, uint16_t queue_id, const char *filename)
+{
+ struct rte_eth_dev *dev;
+ struct mlx5_priv *priv;
+ struct mlx5_txq_data *txq_data;
+ struct mlx5_txq_ctrl *txq_ctrl;
+ struct mlx5_txq_obj *txq_obj;
+ struct mlx5_devx_sq *sq;
+ struct mlx5_devx_cq *cq;
+ struct mlx5_devx_obj *sq_devx_obj;
+ struct mlx5_devx_obj *cq_devx_obj;
+
+ uint32_t sq_out[MLX5_ST_SZ_DW(query_sq_out)] = {0};
+ uint32_t cq_out[MLX5_ST_SZ_DW(query_cq_out)] = {0};
+
+ int ret;
+ FILE *fd;
+ MKSTR(path, "./%s", filename);
+
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -ENODEV;
+
+ if (rte_eth_tx_queue_is_valid(port_id, queue_id))
+ return -EINVAL;
+
+ fd = fopen(path, "w");
+ if (!fd) {
+ rte_errno = errno;
+ return -EIO;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ priv = dev->data->dev_private;
+ txq_data = (*priv->txqs)[queue_id];
+ txq_ctrl = container_of(txq_data, struct mlx5_txq_ctrl, txq);
+ txq_obj = txq_ctrl->obj;
+ sq = &txq_obj->sq_obj;
+ cq = &txq_obj->cq_obj;
+ sq_devx_obj = sq->sq;
+ cq_devx_obj = cq->cq;
+
+ do {
+ ret = mlx5_devx_cmd_query_sq(sq_devx_obj, sq_out, sizeof(sq_out));
+ if (ret)
+ break;
+
+ /* Dump sq query output to file */
+ MKSTR(sq_headline, "SQ DevX ID = %u Port = %u Queue index = %u ",
+ sq_devx_obj->id, port_id, queue_id);
+ mlx5_dump_to_file(fd, NULL, sq_headline, 0);
+ mlx5_dump_to_file(fd, "Query SQ Dump:",
+ (const void *)((uintptr_t)sq_out),
+ sizeof(sq_out));
+
+ ret = mlx5_devx_cmd_query_cq(cq_devx_obj, cq_out, sizeof(cq_out));
+ if (ret)
+ break;
+
+ /* Dump cq query output to file */
+ MKSTR(cq_headline, "CQ DevX ID = %u Port = %u Queue index = %u ",
+ cq_devx_obj->id, port_id, queue_id);
+ mlx5_dump_to_file(fd, NULL, cq_headline, 0);
+ mlx5_dump_to_file(fd, "Query CQ Dump:",
+ (const void *)((uintptr_t)cq_out),
+ sizeof(cq_out));
+ } while (false);
+
+ fclose(fd);
+ return ret;
+}
diff --git a/drivers/net/mlx5/rte_pmd_mlx5.h b/drivers/net/mlx5/rte_pmd_mlx5.h
index 004be0eea1..c823280717 100644
--- a/drivers/net/mlx5/rte_pmd_mlx5.h
+++ b/drivers/net/mlx5/rte_pmd_mlx5.h
@@ -331,6 +331,42 @@ __rte_experimental
int
rte_pmd_mlx5_destroy_geneve_tlv_parser(void *handle);
+/**
+ * Dump Rx Queue Context for a given port/queue
+ *
+ * @param[in] port_id
+ * Port ID
+ * @param[in] queue_id
+ * Queue ID
+ * @param[in] filename
+ * Name of file to dump the Rx Queue Context
+ *
+ * @return
+ * 0 for success, non-zero value depending on failure type
+ */
+
+__rte_experimental
+int
+rte_pmd_mlx5_rxq_dump_contexts(uint16_t port_id, uint16_t queue_id, const char *filename);
+
+/**
+ * Dump Tx Queue Context for a given port/queue
+ *
+ * @param[in] port_id
+ * Port ID
+ * @param[in] queue_id
+ * Queue ID
+ * @param[in] filename
+ * Name of file to dump the Tx Queue Context
+ *
+ * @return
+ * 0 for success, non-zero value depending on failure type
+ */
+
+__rte_experimental
+int
+rte_pmd_mlx5_txq_dump_contexts(uint16_t port_id, uint16_t queue_id, const char *filename);
+
#ifdef __cplusplus
}
#endif
diff --git a/drivers/net/mlx5/version.map b/drivers/net/mlx5/version.map
index 8fb0e07303..f76b7ec18f 100644
--- a/drivers/net/mlx5/version.map
+++ b/drivers/net/mlx5/version.map
@@ -20,4 +20,6 @@ EXPERIMENTAL {
# added in 24.03
rte_pmd_mlx5_create_geneve_tlv_parser;
rte_pmd_mlx5_destroy_geneve_tlv_parser;
+ rte_pmd_mlx5_txq_dump_contexts;
+ rte_pmd_mlx5_rxq_dump_contexts;
};
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [PATCH] net/mlx5: add queue hardware object context dump
2024-06-04 21:11 [PATCH] net/mlx5: add queue hardware object context dump Kiran Vedere
@ 2024-06-10 5:59 ` Slava Ovsiienko
2024-06-30 7:44 ` Raslan Darawsheh
1 sibling, 0 replies; 3+ messages in thread
From: Slava Ovsiienko @ 2024-06-10 5:59 UTC (permalink / raw)
To: Kiran Vedere, dev; +Cc: Matan Azrad, Raslan Darawsheh, Dariusz Sosnowski
> -----Original Message-----
> From: Kiran Vedere <kiranv@nvidia.com>
> Sent: Wednesday, June 5, 2024 12:12 AM
> To: dev@dpdk.org
> Cc: Matan Azrad <matan@nvidia.com>; Raslan Darawsheh
> <rasland@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Dariusz
> Sosnowski <dsosnowski@nvidia.com>
> Subject: [PATCH] net/mlx5: add queue hardware object context dump
>
> Add debug capability to mlx5 PMD to dump SQ/RQ/CQ HW object context for a
> given port/queue. The context dump can provide some real-time information on
> cause of certain Tx/Rx Failures.
>
> Signed-off-by: Kiran Vedere <kiranv@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net/mlx5: add queue hardware object context dump
2024-06-04 21:11 [PATCH] net/mlx5: add queue hardware object context dump Kiran Vedere
2024-06-10 5:59 ` Slava Ovsiienko
@ 2024-06-30 7:44 ` Raslan Darawsheh
1 sibling, 0 replies; 3+ messages in thread
From: Raslan Darawsheh @ 2024-06-30 7:44 UTC (permalink / raw)
To: Kiran Vedere, dev; +Cc: Matan Azrad, Slava Ovsiienko, Dariusz Sosnowski
Hi,
From: Kiran Vedere <kiranv@nvidia.com>
Sent: Wednesday, June 5, 2024 12:11 AM
To: dev@dpdk.org
Cc: Matan Azrad; Raslan Darawsheh; Slava Ovsiienko; Dariusz Sosnowski
Subject: [PATCH] net/mlx5: add queue hardware object context dump
Add debug capability to mlx5 PMD to dump SQ/RQ/CQ HW object context for
a given port/queue. The context dump can provide some real-time
information on cause of certain Tx/Rx Failures.
Signed-off-by: Kiran Vedere <kiranv@nvidia.com>
Patch applied to next-net-mlx,
Kindest regards,
Raslan Darawsheh
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-06-30 7:44 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-04 21:11 [PATCH] net/mlx5: add queue hardware object context dump Kiran Vedere
2024-06-10 5:59 ` Slava Ovsiienko
2024-06-30 7:44 ` Raslan Darawsheh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).