From 796ae7bb6a41fd87c2a975763f26775c2fe7d8b3 Mon Sep 17 00:00:00 2001 From: Matan Azrad Date: Thu, 18 Jun 2020 18:59:42 +0000 Subject: [PATCH] common/mlx5: support DevX virtq stats operations Add DevX API to create and query virtio queue statistics from the HW. The next counters are supported by the HW per virtio queue: received_desc. completed_desc. error_cqes. bad_desc_errors. exceed_max_chain. invalid_buffer. Signed-off-by: Matan Azrad Acked-by: Viacheslav Ovsiienko Reviewed-by: Maxime Coquelin --- drivers/common/mlx5/mlx5_devx_cmds.c | 73 +++++++++++++++++++ drivers/common/mlx5/mlx5_devx_cmds.h | 38 ++++++++++ drivers/common/mlx5/mlx5_prm.h | 26 ++++++- .../common/mlx5/rte_common_mlx5_version.map | 2 + 4 files changed, 138 insertions(+), 1 deletion(-) diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index 091a825ab5..c5dba299e8 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -464,6 +464,9 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, 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 | @@ -1265,6 +1268,7 @@ mlx5_devx_cmd_create_virtq(void *ctx, 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)); @@ -1539,3 +1543,72 @@ mlx5_devx_cmd_modify_qp_state(struct mlx5_devx_obj *qp, uint32_t qp_st_mod_op, } 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; +} diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h index 49b174a75a..59a70a0e04 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.h +++ b/drivers/common/mlx5/mlx5_devx_cmds.h @@ -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; @@ -272,6 +273,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; @@ -300,6 +302,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 */ __rte_internal @@ -374,4 +385,31 @@ __rte_internal int mlx5_devx_cmd_modify_rqt(struct mlx5_devx_obj *rqt, struct mlx5_devx_rqt_attr *rqt_attr); +/** + * 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_internal +struct mlx5_devx_obj *mlx5_devx_cmd_create_virtio_q_counters(void *ctx); + +/** + * 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_internal +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_ */ diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h index e4ef2acd35..5fc10d688a 100644 --- a/drivers/common/mlx5/mlx5_prm.h +++ b/drivers/common/mlx5/mlx5_prm.h @@ -949,6 +949,7 @@ enum { enum { MLX5_GENERAL_OBJ_TYPES_CAP_VIRTQ_NET_Q = (1ULL << 0xd), + MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_Q_COUNTERS = (1ULL << 0x1c), }; enum { @@ -2006,6 +2007,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 { @@ -2024,6 +2026,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, @@ -2064,7 +2087,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 { diff --git a/drivers/common/mlx5/rte_common_mlx5_version.map b/drivers/common/mlx5/rte_common_mlx5_version.map index 68f1207125..3f62400e57 100644 --- a/drivers/common/mlx5/rte_common_mlx5_version.map +++ b/drivers/common/mlx5/rte_common_mlx5_version.map @@ -18,6 +18,7 @@ INTERNAL { mlx5_devx_cmd_create_tir; mlx5_devx_cmd_create_td; mlx5_devx_cmd_create_tis; + mlx5_devx_cmd_create_virtio_q_counters; mlx5_devx_cmd_create_virtq; mlx5_devx_cmd_destroy; mlx5_devx_cmd_flow_counter_alloc; @@ -31,6 +32,7 @@ INTERNAL { mlx5_devx_cmd_modify_virtq; mlx5_devx_cmd_qp_query_tis_td; mlx5_devx_cmd_query_hca_attr; + mlx5_devx_cmd_query_virtio_q_counters; mlx5_devx_cmd_query_virtq; mlx5_devx_get_out_command_status;