@@ -460,6 +460,9 @@ struct mlx5_devx_obj *
attr->vdpa.valid = !!(MLX5_GET64(cmd_hca_cap, hcattr,
general_obj_types) &
MLX5_GENERAL_OBJ_TYPES_CAP_VIRTQ_NET_Q);
+ attr->vdpa.queue_counters_valid = !!(MLX5_GET64(cmd_hca_cap, hcattr,
+ general_obj_types) &
+ MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_Q_COUNTERS);
if (attr->qos.sup) {
MLX5_SET(query_hca_cap_in, in, op_mod,
MLX5_GET_HCA_CAP_OP_MOD_QOS_CAP |
@@ -1254,6 +1257,7 @@ struct mlx5_devx_obj *
MLX5_SET(virtio_q, virtctx, umem_3_id, attr->umems[2].id);
MLX5_SET(virtio_q, virtctx, umem_3_size, attr->umems[2].size);
MLX5_SET64(virtio_q, virtctx, umem_3_offset, attr->umems[2].offset);
+ MLX5_SET(virtio_q, virtctx, counter_set_id, attr->counters_obj_id);
MLX5_SET(virtio_net_q, virtq, tisn_or_qpn, attr->tis_id);
virtq_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out,
sizeof(out));
@@ -1528,3 +1532,72 @@ struct mlx5_devx_obj *
}
return ret;
}
+
+struct mlx5_devx_obj *
+mlx5_devx_cmd_create_virtio_q_counters(void *ctx)
+{
+ uint32_t in[MLX5_ST_SZ_DW(create_virtio_q_counters_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+ struct mlx5_devx_obj *couners_obj = rte_zmalloc(__func__,
+ sizeof(*couners_obj), 0);
+ void *hdr = MLX5_ADDR_OF(create_virtio_q_counters_in, in, hdr);
+
+ if (!couners_obj) {
+ DRV_LOG(ERR, "Failed to allocate virtio queue counters data.");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode,
+ MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type,
+ MLX5_GENERAL_OBJ_TYPE_VIRTIO_Q_COUNTERS);
+ couners_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out,
+ sizeof(out));
+ if (!couners_obj->obj) {
+ rte_errno = errno;
+ DRV_LOG(ERR, "Failed to create virtio queue counters Obj using"
+ " DevX.");
+ rte_free(couners_obj);
+ return NULL;
+ }
+ couners_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+ return couners_obj;
+}
+
+int
+mlx5_devx_cmd_query_virtio_q_counters(struct mlx5_devx_obj *couners_obj,
+ struct mlx5_devx_virtio_q_couners_attr *attr)
+{
+ uint32_t in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(query_virtio_q_counters_out)] = {0};
+ void *hdr = MLX5_ADDR_OF(query_virtio_q_counters_out, in, hdr);
+ void *virtio_q_counters = MLX5_ADDR_OF(query_virtio_q_counters_out, out,
+ virtio_q_counters);
+ int ret;
+
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode,
+ MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type,
+ MLX5_GENERAL_OBJ_TYPE_VIRTIO_Q_COUNTERS);
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_id, couners_obj->id);
+ ret = mlx5_glue->devx_obj_query(couners_obj->obj, in, sizeof(in), out,
+ sizeof(out));
+ if (ret) {
+ DRV_LOG(ERR, "Failed to query virtio q counters using DevX.");
+ rte_errno = errno;
+ return -errno;
+ }
+ attr->received_desc = MLX5_GET64(virtio_q_counters, virtio_q_counters,
+ received_desc);
+ attr->completed_desc = MLX5_GET64(virtio_q_counters, virtio_q_counters,
+ completed_desc);
+ attr->error_cqes = MLX5_GET(virtio_q_counters, virtio_q_counters,
+ error_cqes);
+ attr->bad_desc_errors = MLX5_GET(virtio_q_counters, virtio_q_counters,
+ bad_desc_errors);
+ attr->exceed_max_chain = MLX5_GET(virtio_q_counters, virtio_q_counters,
+ exceed_max_chain);
+ attr->invalid_buffer = MLX5_GET(virtio_q_counters, virtio_q_counters,
+ invalid_buffer);
+ return ret;
+}
@@ -64,6 +64,7 @@ struct mlx5_hca_vdpa_attr {
uint32_t event_mode:3;
uint32_t log_doorbell_stride:5;
uint32_t log_doorbell_bar_size:5;
+ uint32_t queue_counters_valid:1;
uint32_t max_num_virtio_queues;
struct {
uint32_t a;
@@ -270,6 +271,7 @@ struct mlx5_devx_virtq_attr {
uint32_t qp_id;
uint32_t queue_index;
uint32_t tis_id;
+ uint32_t counters_obj_id;
uint64_t dirty_bitmap_addr;
uint64_t type;
uint64_t desc_addr;
@@ -298,6 +300,15 @@ struct mlx5_devx_qp_attr {
uint64_t wq_umem_offset;
};
+struct mlx5_devx_virtio_q_couners_attr {
+ uint64_t received_desc;
+ uint64_t completed_desc;
+ uint32_t error_cqes;
+ uint32_t bad_desc_errors;
+ uint32_t exceed_max_chain;
+ uint32_t invalid_buffer;
+};
+
/* mlx5_devx_cmds.c */
struct mlx5_devx_obj *mlx5_devx_cmd_flow_counter_alloc(void *ctx,
@@ -348,5 +359,37 @@ int mlx5_devx_cmd_modify_qp_state(struct mlx5_devx_obj *qp,
uint32_t qp_st_mod_op, uint32_t remote_qp_id);
int mlx5_devx_cmd_modify_rqt(struct mlx5_devx_obj *rqt,
struct mlx5_devx_rqt_attr *rqt_attr);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create virtio queue counters object DevX API.
+ *
+ * @param[in] ctx
+ * Device context.
+
+ * @return
+ * The DevX object created, NULL otherwise and rte_errno is set.
+ */
+__rte_experimental
+struct mlx5_devx_obj *mlx5_devx_cmd_create_virtio_q_counters(void *ctx);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Query virtio queue counters object using DevX API.
+ *
+ * @param[in] couners_obj
+ * Pointer to virtq object structure.
+ * @param [in/out] attr
+ * Pointer to virtio queue counters attributes structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int mlx5_devx_cmd_query_virtio_q_counters(struct mlx5_devx_obj *couners_obj,
+ struct mlx5_devx_virtio_q_couners_attr *attr);
#endif /* RTE_PMD_MLX5_DEVX_CMDS_H_ */
@@ -938,6 +938,7 @@ enum {
enum {
MLX5_GENERAL_OBJ_TYPES_CAP_VIRTQ_NET_Q = (1ULL << 0xd),
+ MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_Q_COUNTERS = (1ULL << 0x1c),
};
enum {
@@ -1994,6 +1995,7 @@ struct mlx5_ifc_create_cq_in_bits {
enum {
MLX5_GENERAL_OBJ_TYPE_VIRTQ = 0x000d,
+ MLX5_GENERAL_OBJ_TYPE_VIRTIO_Q_COUNTERS = 0x001c,
};
struct mlx5_ifc_general_obj_in_cmd_hdr_bits {
@@ -2012,6 +2014,27 @@ struct mlx5_ifc_general_obj_out_cmd_hdr_bits {
u8 reserved_at_60[0x20];
};
+struct mlx5_ifc_virtio_q_counters_bits {
+ u8 modify_field_select[0x40];
+ u8 reserved_at_40[0x40];
+ u8 received_desc[0x40];
+ u8 completed_desc[0x40];
+ u8 error_cqes[0x20];
+ u8 bad_desc_errors[0x20];
+ u8 exceed_max_chain[0x20];
+ u8 invalid_buffer[0x20];
+ u8 reserved_at_180[0x50];
+};
+
+struct mlx5_ifc_create_virtio_q_counters_in_bits {
+ struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
+ struct mlx5_ifc_virtio_q_counters_bits virtio_q_counters;
+};
+
+struct mlx5_ifc_query_virtio_q_counters_out_bits {
+ struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
+ struct mlx5_ifc_virtio_q_counters_bits virtio_q_counters;
+};
enum {
MLX5_VIRTQ_STATE_INIT = 0,
MLX5_VIRTQ_STATE_RDY = 1,
@@ -2052,7 +2075,8 @@ struct mlx5_ifc_virtio_q_bits {
u8 umem_3_id[0x20];
u8 umem_3_size[0x20];
u8 umem_3_offset[0x40];
- u8 reserved_at_300[0x100];
+ u8 counter_set_id[0x20];
+ u8 reserved_at_320[0xe0];
};
struct mlx5_ifc_virtio_net_q_bits {
@@ -49,3 +49,10 @@ DPDK_20.0.1 {
mlx5_translate_port_name;
};
+
+EXPERIMENTAL {
+ global:
+
+ mlx5_devx_cmd_create_virtio_q_counters;
+ mlx5_devx_cmd_query_virtio_q_counters;
+};
\ No newline at end of file