X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcommon%2Fmlx5%2Fmlx5_devx_cmds.c;h=1c88f44ac2bd1fa73983d321a80af30eda0b3d99;hb=38119ebe01d6;hp=fba485e72459dce6ba98db187498545c76883173;hpb=ffd5b302baabdc96fcd6deb58d8cd3ec39020c5c;p=dpdk.git diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index fba485e724..1c88f44ac2 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -11,6 +11,67 @@ #include "mlx5_common_utils.h" +/** + * Perform read access to the registers. Reads data from register + * and writes ones to the specified buffer. + * + * @param[in] ctx + * Context returned from mlx5 open_device() glue function. + * @param[in] reg_id + * Register identifier according to the PRM. + * @param[in] arg + * Register access auxiliary parameter according to the PRM. + * @param[out] data + * Pointer to the buffer to store read data. + * @param[in] dw_cnt + * Buffer size in double words. + * + * @return + * 0 on success, a negative value otherwise. + */ +int +mlx5_devx_cmd_register_read(void *ctx, uint16_t reg_id, uint32_t arg, + uint32_t *data, uint32_t dw_cnt) +{ + uint32_t in[MLX5_ST_SZ_DW(access_register_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(access_register_out) + + MLX5_ACCESS_REGISTER_DATA_DWORD_MAX] = {0}; + int status, rc; + + MLX5_ASSERT(data && dw_cnt); + MLX5_ASSERT(dw_cnt <= MLX5_ACCESS_REGISTER_DATA_DWORD_MAX); + if (dw_cnt > MLX5_ACCESS_REGISTER_DATA_DWORD_MAX) { + DRV_LOG(ERR, "Not enough buffer for register read data"); + return -1; + } + MLX5_SET(access_register_in, in, opcode, + MLX5_CMD_OP_ACCESS_REGISTER_USER); + MLX5_SET(access_register_in, in, op_mod, + MLX5_ACCESS_REGISTER_IN_OP_MOD_READ); + MLX5_SET(access_register_in, in, register_id, reg_id); + MLX5_SET(access_register_in, in, argument, arg); + rc = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, + MLX5_ST_SZ_DW(access_register_out) * + sizeof(uint32_t) + dw_cnt); + if (rc) + goto error; + status = MLX5_GET(access_register_out, out, status); + if (status) { + int syndrome = MLX5_GET(access_register_out, out, syndrome); + + DRV_LOG(DEBUG, "Failed to access NIC register 0x%X, " + "status %x, syndrome = %x", + reg_id, status, syndrome); + return -1; + } + memcpy(data, &out[MLX5_ST_SZ_DW(access_register_out)], + dw_cnt * sizeof(uint32_t)); + return 0; +error: + rc = (rc > 0) ? -rc : rc; + return rc; +} + /** * Allocate flow counters via devx interface. * @@ -396,6 +457,167 @@ mlx5_devx_cmd_query_hca_vdpa_attr(void *ctx, } } +int +mlx5_devx_cmd_query_parse_samples(struct mlx5_devx_obj *flex_obj, + uint32_t ids[], uint32_t num) +{ + uint32_t in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(create_flex_parser_out)] = {0}; + void *hdr = MLX5_ADDR_OF(create_flex_parser_out, in, hdr); + void *flex = MLX5_ADDR_OF(create_flex_parser_out, out, flex); + void *sample = MLX5_ADDR_OF(parse_graph_flex, flex, sample_table); + int ret; + uint32_t idx = 0; + uint32_t i; + + if (num > MLX5_GRAPH_NODE_SAMPLE_NUM) { + rte_errno = EINVAL; + DRV_LOG(ERR, "Too many sample IDs to be fetched."); + return -rte_errno; + } + 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_FLEX_PARSE_GRAPH); + MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_id, flex_obj->id); + ret = mlx5_glue->devx_obj_query(flex_obj->obj, in, sizeof(in), + out, sizeof(out)); + if (ret) { + rte_errno = ret; + DRV_LOG(ERR, "Failed to query sample IDs with object %p.", + (void *)flex_obj); + return -rte_errno; + } + for (i = 0; i < MLX5_GRAPH_NODE_SAMPLE_NUM; i++) { + void *s_off = (void *)((char *)sample + i * + MLX5_ST_SZ_BYTES(parse_graph_flow_match_sample)); + uint32_t en; + + en = MLX5_GET(parse_graph_flow_match_sample, s_off, + flow_match_sample_en); + if (!en) + continue; + ids[idx++] = MLX5_GET(parse_graph_flow_match_sample, s_off, + flow_match_sample_field_id); + } + if (num != idx) { + rte_errno = EINVAL; + DRV_LOG(ERR, "Number of sample IDs are not as expected."); + return -rte_errno; + } + return ret; +} + + +struct mlx5_devx_obj * +mlx5_devx_cmd_create_flex_parser(void *ctx, + struct mlx5_devx_graph_node_attr *data) +{ + uint32_t in[MLX5_ST_SZ_DW(create_flex_parser_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; + void *hdr = MLX5_ADDR_OF(create_flex_parser_in, in, hdr); + void *flex = MLX5_ADDR_OF(create_flex_parser_in, in, flex); + void *sample = MLX5_ADDR_OF(parse_graph_flex, flex, sample_table); + void *in_arc = MLX5_ADDR_OF(parse_graph_flex, flex, input_arc); + void *out_arc = MLX5_ADDR_OF(parse_graph_flex, flex, output_arc); + struct mlx5_devx_obj *parse_flex_obj = NULL; + uint32_t i; + + parse_flex_obj = rte_calloc(__func__, 1, sizeof(*parse_flex_obj), 0); + if (!parse_flex_obj) { + DRV_LOG(ERR, "Failed to allocate flex parser data"); + rte_errno = ENOMEM; + rte_free(in); + 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_FLEX_PARSE_GRAPH); + MLX5_SET(parse_graph_flex, flex, header_length_mode, + data->header_length_mode); + MLX5_SET(parse_graph_flex, flex, header_length_base_value, + data->header_length_base_value); + MLX5_SET(parse_graph_flex, flex, header_length_field_offset, + data->header_length_field_offset); + MLX5_SET(parse_graph_flex, flex, header_length_field_shift, + data->header_length_field_shift); + MLX5_SET(parse_graph_flex, flex, header_length_field_mask, + data->header_length_field_mask); + for (i = 0; i < MLX5_GRAPH_NODE_SAMPLE_NUM; i++) { + struct mlx5_devx_match_sample_attr *s = &data->sample[i]; + void *s_off = (void *)((char *)sample + i * + MLX5_ST_SZ_BYTES(parse_graph_flow_match_sample)); + + if (!s->flow_match_sample_en) + continue; + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_en, !!s->flow_match_sample_en); + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_field_offset, + s->flow_match_sample_field_offset); + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_offset_mode, + s->flow_match_sample_offset_mode); + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_field_offset_mask, + s->flow_match_sample_field_offset_mask); + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_field_offset_shift, + s->flow_match_sample_field_offset_shift); + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_field_base_offset, + s->flow_match_sample_field_base_offset); + MLX5_SET(parse_graph_flow_match_sample, s_off, + flow_match_sample_tunnel_mode, + s->flow_match_sample_tunnel_mode); + } + for (i = 0; i < MLX5_GRAPH_NODE_ARC_NUM; i++) { + struct mlx5_devx_graph_arc_attr *ia = &data->in[i]; + struct mlx5_devx_graph_arc_attr *oa = &data->out[i]; + void *in_off = (void *)((char *)in_arc + i * + MLX5_ST_SZ_BYTES(parse_graph_arc)); + void *out_off = (void *)((char *)out_arc + i * + MLX5_ST_SZ_BYTES(parse_graph_arc)); + + if (ia->arc_parse_graph_node != 0) { + MLX5_SET(parse_graph_arc, in_off, + compare_condition_value, + ia->compare_condition_value); + MLX5_SET(parse_graph_arc, in_off, start_inner_tunnel, + ia->start_inner_tunnel); + MLX5_SET(parse_graph_arc, in_off, arc_parse_graph_node, + ia->arc_parse_graph_node); + MLX5_SET(parse_graph_arc, in_off, + parse_graph_node_handle, + ia->parse_graph_node_handle); + } + if (oa->arc_parse_graph_node != 0) { + MLX5_SET(parse_graph_arc, out_off, + compare_condition_value, + oa->compare_condition_value); + MLX5_SET(parse_graph_arc, out_off, start_inner_tunnel, + oa->start_inner_tunnel); + MLX5_SET(parse_graph_arc, out_off, arc_parse_graph_node, + oa->arc_parse_graph_node); + MLX5_SET(parse_graph_arc, out_off, + parse_graph_node_handle, + oa->parse_graph_node_handle); + } + } + parse_flex_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), + out, sizeof(out)); + if (!parse_flex_obj->obj) { + rte_errno = errno; + DRV_LOG(ERR, "Failed to create FLEX PARSE GRAPH object " + "by using DevX."); + rte_free(parse_flex_obj); + return NULL; + } + parse_flex_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); + return parse_flex_obj; +} + /** * Query HCA attributes. * Using those attributes we can check on run time if the device @@ -416,7 +638,7 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, uint32_t in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0}; uint32_t out[MLX5_ST_SZ_DW(query_hca_cap_out)] = {0}; void *hcattr; - int status, syndrome, rc; + int status, syndrome, rc, i; MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); MLX5_SET(query_hca_cap_in, in, op_mod, @@ -464,6 +686,23 @@ 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); + attr->parse_graph_flex_node = !!(MLX5_GET64(cmd_hca_cap, hcattr, + general_obj_types) & + MLX5_GENERAL_OBJ_TYPES_CAP_PARSE_GRAPH_FLEX_NODE); + attr->wqe_index_ignore = MLX5_GET(cmd_hca_cap, hcattr, + wqe_index_ignore_cap); + attr->cross_channel = MLX5_GET(cmd_hca_cap, hcattr, cd); + attr->non_wire_sq = MLX5_GET(cmd_hca_cap, hcattr, non_wire_sq); + attr->log_max_static_sq_wq = MLX5_GET(cmd_hca_cap, hcattr, + log_max_static_sq_wq); + attr->dev_freq_khz = MLX5_GET(cmd_hca_cap, hcattr, + device_frequency_khz); + attr->regex = MLX5_GET(cmd_hca_cap, hcattr, regexp); + attr->regexp_num_of_engines = MLX5_GET(cmd_hca_cap, hcattr, + regexp_num_of_engines); if (attr->qos.sup) { MLX5_SET(query_hca_cap_in, in, op_mod, MLX5_GET_HCA_CAP_OP_MOD_QOS_CAP | @@ -484,9 +723,13 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, attr->qos.log_max_flow_meter = MLX5_GET(qos_cap, hcattr, log_max_flow_meter); attr->qos.flow_meter_reg_c_ids = - MLX5_GET(qos_cap, hcattr, flow_meter_reg_id); + MLX5_GET(qos_cap, hcattr, flow_meter_reg_id); attr->qos.flow_meter_reg_share = - MLX5_GET(qos_cap, hcattr, flow_meter_reg_share); + MLX5_GET(qos_cap, hcattr, flow_meter_reg_share); + attr->qos.packet_pacing = + MLX5_GET(qos_cap, hcattr, packet_pacing); + attr->qos.wqe_rate_pp = + MLX5_GET(qos_cap, hcattr, wqe_rate_pp); } if (attr->vdpa.valid) mlx5_devx_cmd_query_hca_vdpa_attr(ctx, &attr->vdpa); @@ -529,7 +772,7 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, attr->lro_max_msg_sz_mode = MLX5_GET (per_protocol_networking_offload_caps, hcattr, lro_max_msg_sz_mode); - for (int i = 0 ; i < MLX5_LRO_NUM_SUPP_PERIODS ; i++) { + for (i = 0 ; i < MLX5_LRO_NUM_SUPP_PERIODS ; i++) { attr->lro_timer_supported_periods[i] = MLX5_GET(per_protocol_networking_offload_caps, hcattr, lro_timer_supported_periods[i]); @@ -577,6 +820,7 @@ int mlx5_devx_cmd_qp_query_tis_td(void *qp, uint32_t tis_num, uint32_t *tis_td) { +#ifdef HAVE_IBV_FLOW_DV_SUPPORT uint32_t in[MLX5_ST_SZ_DW(query_tis_in)] = {0}; uint32_t out[MLX5_ST_SZ_DW(query_tis_out)] = {0}; int rc; @@ -592,6 +836,12 @@ mlx5_devx_cmd_qp_query_tis_td(void *qp, uint32_t tis_num, tis_ctx = MLX5_ADDR_OF(query_tis_out, out, tis_context); *tis_td = MLX5_GET(tisc, tis_ctx, transport_domain); return 0; +#else + (void)qp; + (void)tis_num; + (void)tis_td; + return -ENOTSUP; +#endif } /** @@ -961,6 +1211,8 @@ mlx5_devx_cmd_create_sq(void *ctx, MLX5_SET(sqc, sq_ctx, reg_umr, sq_attr->reg_umr); MLX5_SET(sqc, sq_ctx, allow_swp, sq_attr->allow_swp); MLX5_SET(sqc, sq_ctx, hairpin, sq_attr->hairpin); + MLX5_SET(sqc, sq_ctx, non_wire, sq_attr->non_wire); + MLX5_SET(sqc, sq_ctx, static_sq_wq, sq_attr->static_sq_wq); MLX5_SET(sqc, sq_ctx, user_index, sq_attr->user_index); MLX5_SET(sqc, sq_ctx, cqn, sq_attr->cqn); MLX5_SET(sqc, sq_ctx, packet_pacing_rate_limit_index, @@ -1014,7 +1266,7 @@ mlx5_devx_cmd_modify_sq(struct mlx5_devx_obj *sq, if (ret) { DRV_LOG(ERR, "Failed to modify SQ using DevX"); rte_errno = errno; - return -errno; + return -rte_errno; } return ret; } @@ -1175,6 +1427,7 @@ mlx5_devx_cmd_create_cq(void *ctx, struct mlx5_devx_cq_attr *attr) } else { MLX5_SET64(cqc, cqctx, dbr_addr, attr->db_addr); } + MLX5_SET(cqc, cqctx, cqe_sz, attr->cqe_size); MLX5_SET(cqc, cqctx, cc, attr->use_first_only); MLX5_SET(cqc, cqctx, oi, attr->overrun_ignore); MLX5_SET(cqc, cqctx, log_cq_size, attr->log_cq_size); @@ -1258,6 +1511,8 @@ 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_q, virtctx, pd, attr->pd); 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)); @@ -1325,7 +1580,7 @@ mlx5_devx_cmd_modify_virtq(struct mlx5_devx_obj *virtq_obj, if (ret) { DRV_LOG(ERR, "Failed to modify VIRTQ using DevX."); rte_errno = errno; - return -errno; + return -rte_errno; } return ret; } @@ -1528,7 +1783,76 @@ mlx5_devx_cmd_modify_qp_state(struct mlx5_devx_obj *qp, uint32_t qp_st_mod_op, if (ret) { DRV_LOG(ERR, "Failed to modify QP using DevX."); rte_errno = errno; + return -rte_errno; + } + 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; }