X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_devx_cmds.c;h=acfe1dea13909809478cd528eeffebe4a9c13f51;hb=62e3ccc2b94c625d4b3ce55044b135c4ab0793db;hp=e5776c4e3ce2b9643a25b165e3c93587694aaf70;hpb=e2b4925ef7c11c4271b2c8fb46154d347cba26e2;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_devx_cmds.c b/drivers/net/mlx5/mlx5_devx_cmds.c index e5776c4e3c..acfe1dea13 100644 --- a/drivers/net/mlx5/mlx5_devx_cmds.c +++ b/drivers/net/mlx5/mlx5_devx_cmds.c @@ -2,6 +2,8 @@ /* Copyright 2018 Mellanox Technologies, Ltd */ #include +#include +#include #include "mlx5.h" #include "mlx5_glue.h" @@ -14,47 +16,37 @@ * ibv contexts returned from mlx5dv_open_device. * @param dcs * Pointer to counters properties structure to be filled by the routine. + * @param bulk_n_128 + * Bulk counter numbers in 128 counters units. * * @return - * 0 on success, a negative value otherwise. + * Pointer to counter object on success, a negative value otherwise and + * rte_errno is set. */ -int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx, - struct mlx5_devx_counter_set *dcs) +struct mlx5_devx_obj * +mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx, uint32_t bulk_n_128) { + struct mlx5_devx_obj *dcs = rte_zmalloc("dcs", sizeof(*dcs), 0); uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {0}; uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0}; - int status, syndrome; + if (!dcs) { + rte_errno = ENOMEM; + return NULL; + } MLX5_SET(alloc_flow_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_FLOW_COUNTER); + MLX5_SET(alloc_flow_counter_in, in, flow_counter_bulk, bulk_n_128); dcs->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); - if (!dcs->obj) - return -errno; - status = MLX5_GET(query_flow_counter_out, out, status); - syndrome = MLX5_GET(query_flow_counter_out, out, syndrome); - if (status) { - DRV_LOG(DEBUG, "Failed to create devx counters, " - "status %x, syndrome %x", status, syndrome); - return -1; + if (!dcs->obj) { + DRV_LOG(ERR, "Can't allocate counters - error %d\n", errno); + rte_errno = errno; + rte_free(dcs); + return NULL; } - dcs->id = MLX5_GET(alloc_flow_counter_out, - out, flow_counter_id); - return 0; -} - -/** - * Free flow counters obtained via devx interface. - * - * @param[in] obj - * devx object that was obtained from mlx5_devx_cmd_fc_alloc. - * - * @return - * 0 on success, a negative value otherwise. - */ -int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj) -{ - return mlx5_glue->devx_obj_destroy(obj); + dcs->id = MLX5_GET(alloc_flow_counter_out, out, flow_counter_id); + return dcs; } /** @@ -64,46 +56,230 @@ int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj) * devx object that was obtained from mlx5_devx_cmd_fc_alloc. * @param[in] clear * Whether hardware should clear the counters after the query or not. + * @param[in] n_counters + * 0 in case of 1 counter to read, otherwise the counter number to read. * @param pkts * The number of packets that matched the flow. * @param bytes * The number of bytes that matched the flow. + * @param mkey + * The mkey key for batch query. + * @param addr + * The address in the mkey range for batch query. + * @param cmd_comp + * The completion object for asynchronous batch query. + * @param async_id + * The ID to be returned in the asynchronous batch query response. * * @return * 0 on success, a negative value otherwise. */ int -mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs, - int clear __rte_unused, - uint64_t *pkts, uint64_t *bytes) +mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_obj *dcs, + int clear, uint32_t n_counters, + uint64_t *pkts, uint64_t *bytes, + uint32_t mkey, void *addr, + struct mlx5dv_devx_cmd_comp *cmd_comp, + uint64_t async_id) { - uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) + - MLX5_ST_SZ_BYTES(traffic_counter)] = {0}; + int out_len = MLX5_ST_SZ_BYTES(query_flow_counter_out) + + MLX5_ST_SZ_BYTES(traffic_counter); + uint32_t out[out_len]; uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0}; void *stats; - int status, syndrome, rc; + int rc; MLX5_SET(query_flow_counter_in, in, opcode, MLX5_CMD_OP_QUERY_FLOW_COUNTER); MLX5_SET(query_flow_counter_in, in, op_mod, 0); MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id); - rc = mlx5_glue->devx_obj_query(dcs->obj, - in, sizeof(in), out, sizeof(out)); - if (rc) - return rc; + MLX5_SET(query_flow_counter_in, in, clear, !!clear); + + if (n_counters) { + MLX5_SET(query_flow_counter_in, in, num_of_counters, + n_counters); + MLX5_SET(query_flow_counter_in, in, dump_to_memory, 1); + MLX5_SET(query_flow_counter_in, in, mkey, mkey); + MLX5_SET64(query_flow_counter_in, in, address, + (uint64_t)(uintptr_t)addr); + } + if (!cmd_comp) + rc = mlx5_glue->devx_obj_query(dcs->obj, in, sizeof(in), out, + out_len); + else + rc = mlx5_glue->devx_obj_query_async(dcs->obj, in, sizeof(in), + out_len, async_id, + cmd_comp); + if (rc) { + DRV_LOG(ERR, "Failed to query devx counters with rc %d\n ", rc); + rte_errno = rc; + return -rc; + } + if (!n_counters) { + stats = MLX5_ADDR_OF(query_flow_counter_out, + out, flow_statistics); + *pkts = MLX5_GET64(traffic_counter, stats, packets); + *bytes = MLX5_GET64(traffic_counter, stats, octets); + } + return 0; +} + +/** + * Create a new mkey. + * + * @param[in] ctx + * ibv contexts returned from mlx5dv_open_device. + * @param[in] attr + * Attributes of the requested mkey. + * + * @return + * Pointer to Devx mkey on success, a negative value otherwise and rte_errno + * is set. + */ +struct mlx5_devx_obj * +mlx5_devx_cmd_mkey_create(struct ibv_context *ctx, + struct mlx5_devx_mkey_attr *attr) +{ + uint32_t in[MLX5_ST_SZ_DW(create_mkey_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(create_mkey_out)] = {0}; + void *mkc; + struct mlx5_devx_obj *mkey = rte_zmalloc("mkey", sizeof(*mkey), 0); + size_t pgsize; + uint32_t translation_size; + + if (!mkey) { + rte_errno = ENOMEM; + return NULL; + } + pgsize = sysconf(_SC_PAGESIZE); + translation_size = (RTE_ALIGN(attr->size, pgsize) * 8) / 16; + MLX5_SET(create_mkey_in, in, opcode, MLX5_CMD_OP_CREATE_MKEY); + MLX5_SET(create_mkey_in, in, translations_octword_actual_size, + translation_size); + MLX5_SET(create_mkey_in, in, mkey_umem_id, attr->umem_id); + mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); + MLX5_SET(mkc, mkc, lw, 0x1); + MLX5_SET(mkc, mkc, lr, 0x1); + MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_MTT); + MLX5_SET(mkc, mkc, qpn, 0xffffff); + MLX5_SET(mkc, mkc, pd, attr->pd); + MLX5_SET(mkc, mkc, mkey_7_0, attr->umem_id & 0xFF); + MLX5_SET(mkc, mkc, translations_octword_size, translation_size); + MLX5_SET64(mkc, mkc, start_addr, attr->addr); + MLX5_SET64(mkc, mkc, len, attr->size); + MLX5_SET(mkc, mkc, log_page_size, rte_log2_u32(pgsize)); + mkey->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, + sizeof(out)); + if (!mkey->obj) { + DRV_LOG(ERR, "Can't create mkey - error %d\n", errno); + rte_errno = errno; + rte_free(mkey); + return NULL; + } + mkey->id = MLX5_GET(create_mkey_out, out, mkey_index); + mkey->id = (mkey->id << 8) | (attr->umem_id & 0xFF); + return mkey; +} + +/** + * Get status of devx command response. + * Mainly used for asynchronous commands. + * + * @param[in] out + * The out response buffer. + * + * @return + * 0 on success, non-zero value otherwise. + */ +int +mlx5_devx_get_out_command_status(void *out) +{ + int status; + + if (!out) + return -EINVAL; status = MLX5_GET(query_flow_counter_out, out, status); - syndrome = MLX5_GET(query_flow_counter_out, out, syndrome); if (status) { - DRV_LOG(DEBUG, "Failed to query devx counters, " - "id %d, status %x, syndrome = %x", - status, syndrome, dcs->id); + int syndrome = MLX5_GET(query_flow_counter_out, out, syndrome); + + DRV_LOG(ERR, "Bad devX status %x, syndrome = %x\n", status, + syndrome); + } + return status; +} + +/** + * Destroy any object allocated by a Devx API. + * + * @param[in] obj + * Pointer to a general object. + * + * @return + * 0 on success, a negative value otherwise. + */ +int +mlx5_devx_cmd_destroy(struct mlx5_devx_obj *obj) +{ + int ret; + + if (!obj) + return 0; + ret = mlx5_glue->devx_obj_destroy(obj->obj); + rte_free(obj); + return ret; +} + +/** + * Query NIC vport context. + * Fills minimal inline attribute. + * + * @param[in] ctx + * ibv contexts returned from mlx5dv_open_device. + * @param[in] vport + * vport index + * @param[out] attr + * Attributes device values. + * + * @return + * 0 on success, a negative value otherwise. + */ +static int +mlx5_devx_cmd_query_nic_vport_context(struct ibv_context *ctx, + unsigned int vport, + struct mlx5_hca_attr *attr) +{ + uint32_t in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {0}; + void *vctx; + int status, syndrome, rc; + + /* Query NIC vport context to determine inline mode. */ + MLX5_SET(query_nic_vport_context_in, in, opcode, + MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); + MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); + if (vport) + MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); + rc = mlx5_glue->devx_general_cmd(ctx, + in, sizeof(in), + out, sizeof(out)); + if (rc) + goto error; + status = MLX5_GET(query_nic_vport_context_out, out, status); + syndrome = MLX5_GET(query_nic_vport_context_out, out, syndrome); + if (status) { + DRV_LOG(DEBUG, "Failed to query NIC vport context, " + "status %x, syndrome = %x", + status, syndrome); return -1; } - stats = MLX5_ADDR_OF(query_flow_counter_out, - out, flow_statistics); - *pkts = MLX5_GET64(traffic_counter, stats, packets); - *bytes = MLX5_GET64(traffic_counter, stats, octets); + vctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, + nic_vport_context); + attr->vport_inline_mode = MLX5_GET(nic_vport_context, vctx, + min_wqe_inline_mode); return 0; +error: + rc = (rc > 0) ? -rc : rc; + return rc; } /** @@ -136,7 +312,7 @@ mlx5_devx_cmd_query_hca_attr(struct ibv_context *ctx, rc = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); if (rc) - return rc; + goto error; status = MLX5_GET(query_hca_cap_out, out, status); syndrome = MLX5_GET(query_hca_cap_out, out, syndrome); if (status) { @@ -146,6 +322,383 @@ mlx5_devx_cmd_query_hca_attr(struct ibv_context *ctx, return -1; } hcattr = MLX5_ADDR_OF(query_hca_cap_out, out, capability); + attr->flow_counter_bulk_alloc_bitmap = + MLX5_GET(cmd_hca_cap, hcattr, flow_counter_bulk_alloc); + attr->flow_counters_dump = MLX5_GET(cmd_hca_cap, hcattr, + flow_counters_dump); attr->eswitch_manager = MLX5_GET(cmd_hca_cap, hcattr, eswitch_manager); + attr->eth_net_offloads = MLX5_GET(cmd_hca_cap, hcattr, + eth_net_offloads); + attr->eth_virt = MLX5_GET(cmd_hca_cap, hcattr, eth_virt); + if (!attr->eth_net_offloads) + return 0; + + /* Query HCA offloads for Ethernet protocol. */ + memset(in, 0, sizeof(in)); + memset(out, 0, sizeof(out)); + MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); + MLX5_SET(query_hca_cap_in, in, op_mod, + MLX5_GET_HCA_CAP_OP_MOD_ETHERNET_OFFLOAD_CAPS | + MLX5_HCA_CAP_OPMOD_GET_CUR); + + rc = mlx5_glue->devx_general_cmd(ctx, + in, sizeof(in), + out, sizeof(out)); + if (rc) { + attr->eth_net_offloads = 0; + goto error; + } + status = MLX5_GET(query_hca_cap_out, out, status); + syndrome = MLX5_GET(query_hca_cap_out, out, syndrome); + if (status) { + DRV_LOG(DEBUG, "Failed to query devx HCA capabilities, " + "status %x, syndrome = %x", + status, syndrome); + attr->eth_net_offloads = 0; + return -1; + } + hcattr = MLX5_ADDR_OF(query_hca_cap_out, out, capability); + attr->wqe_vlan_insert = MLX5_GET(per_protocol_networking_offload_caps, + hcattr, wqe_vlan_insert); + attr->lro_cap = MLX5_GET(per_protocol_networking_offload_caps, hcattr, + lro_cap); + attr->tunnel_lro_gre = MLX5_GET(per_protocol_networking_offload_caps, + hcattr, tunnel_lro_gre); + attr->tunnel_lro_vxlan = MLX5_GET(per_protocol_networking_offload_caps, + hcattr, tunnel_lro_vxlan); + 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++) { + attr->lro_timer_supported_periods[i] = + MLX5_GET(per_protocol_networking_offload_caps, hcattr, + lro_timer_supported_periods[i]); + } + attr->wqe_inline_mode = MLX5_GET(per_protocol_networking_offload_caps, + hcattr, wqe_inline_mode); + if (attr->wqe_inline_mode != MLX5_CAP_INLINE_MODE_VPORT_CONTEXT) + return 0; + if (attr->eth_virt) { + rc = mlx5_devx_cmd_query_nic_vport_context(ctx, 0, attr); + if (rc) { + attr->eth_virt = 0; + goto error; + } + } + return 0; +error: + rc = (rc > 0) ? -rc : rc; + return rc; +} + +/** + * Query TIS transport domain from QP verbs object using DevX API. + * + * @param[in] qp + * Pointer to verbs QP returned by ibv_create_qp . + * @param[in] tis_num + * TIS number of TIS to query. + * @param[out] tis_td + * Pointer to TIS transport domain variable, to be set by the routine. + * + * @return + * 0 on success, a negative value otherwise. + */ +int +mlx5_devx_cmd_qp_query_tis_td(struct ibv_qp *qp, uint32_t tis_num, + uint32_t *tis_td) +{ + uint32_t in[MLX5_ST_SZ_DW(query_tis_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(query_tis_out)] = {0}; + int rc; + void *tis_ctx; + + MLX5_SET(query_tis_in, in, opcode, MLX5_CMD_OP_QUERY_TIS); + MLX5_SET(query_tis_in, in, tisn, tis_num); + rc = mlx5_glue->devx_qp_query(qp, in, sizeof(in), out, sizeof(out)); + if (rc) { + DRV_LOG(ERR, "Failed to query QP using DevX"); + return -rc; + }; + tis_ctx = MLX5_ADDR_OF(query_tis_out, out, tis_context); + *tis_td = MLX5_GET(tisc, tis_ctx, transport_domain); return 0; } + +/** + * Fill WQ data for DevX API command. + * Utility function for use when creating DevX objects containing a WQ. + * + * @param[in] wq_ctx + * Pointer to WQ context to fill with data. + * @param [in] wq_attr + * Pointer to WQ attributes structure to fill in WQ context. + */ +static void +devx_cmd_fill_wq_data(void *wq_ctx, struct mlx5_devx_wq_attr *wq_attr) +{ + MLX5_SET(wq, wq_ctx, wq_type, wq_attr->wq_type); + MLX5_SET(wq, wq_ctx, wq_signature, wq_attr->wq_signature); + MLX5_SET(wq, wq_ctx, end_padding_mode, wq_attr->end_padding_mode); + MLX5_SET(wq, wq_ctx, cd_slave, wq_attr->cd_slave); + MLX5_SET(wq, wq_ctx, hds_skip_first_sge, wq_attr->hds_skip_first_sge); + MLX5_SET(wq, wq_ctx, log2_hds_buf_size, wq_attr->log2_hds_buf_size); + MLX5_SET(wq, wq_ctx, page_offset, wq_attr->page_offset); + MLX5_SET(wq, wq_ctx, lwm, wq_attr->lwm); + MLX5_SET(wq, wq_ctx, pd, wq_attr->pd); + MLX5_SET(wq, wq_ctx, uar_page, wq_attr->uar_page); + MLX5_SET64(wq, wq_ctx, dbr_addr, wq_attr->dbr_addr); + MLX5_SET(wq, wq_ctx, hw_counter, wq_attr->hw_counter); + MLX5_SET(wq, wq_ctx, sw_counter, wq_attr->sw_counter); + MLX5_SET(wq, wq_ctx, log_wq_stride, wq_attr->log_wq_stride); + MLX5_SET(wq, wq_ctx, log_wq_pg_sz, wq_attr->log_wq_pg_sz); + MLX5_SET(wq, wq_ctx, log_wq_sz, wq_attr->log_wq_sz); + MLX5_SET(wq, wq_ctx, dbr_umem_valid, wq_attr->dbr_umem_valid); + MLX5_SET(wq, wq_ctx, wq_umem_valid, wq_attr->wq_umem_valid); + MLX5_SET(wq, wq_ctx, log_hairpin_num_packets, + wq_attr->log_hairpin_num_packets); + MLX5_SET(wq, wq_ctx, log_hairpin_data_sz, wq_attr->log_hairpin_data_sz); + MLX5_SET(wq, wq_ctx, single_wqe_log_num_of_strides, + wq_attr->single_wqe_log_num_of_strides); + MLX5_SET(wq, wq_ctx, two_byte_shift_en, wq_attr->two_byte_shift_en); + MLX5_SET(wq, wq_ctx, single_stride_log_num_of_bytes, + wq_attr->single_stride_log_num_of_bytes); + MLX5_SET(wq, wq_ctx, dbr_umem_id, wq_attr->dbr_umem_id); + MLX5_SET(wq, wq_ctx, wq_umem_id, wq_attr->wq_umem_id); + MLX5_SET64(wq, wq_ctx, wq_umem_offset, wq_attr->wq_umem_offset); +} + +/** + * Create RQ using DevX API. + * + * @param[in] ctx + * ibv_context returned from mlx5dv_open_device. + * @param [in] rq_attr + * Pointer to create RQ attributes structure. + * @param [in] socket + * CPU socket ID for allocations. + * + * @return + * The DevX object created, NULL otherwise and rte_errno is set. + */ +struct mlx5_devx_obj * +mlx5_devx_cmd_create_rq(struct ibv_context *ctx, + struct mlx5_devx_create_rq_attr *rq_attr, + int socket) +{ + uint32_t in[MLX5_ST_SZ_DW(create_rq_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(create_rq_out)] = {0}; + void *rq_ctx, *wq_ctx; + struct mlx5_devx_wq_attr *wq_attr; + struct mlx5_devx_obj *rq = NULL; + + rq = rte_calloc_socket(__func__, 1, sizeof(*rq), 0, socket); + if (!rq) { + DRV_LOG(ERR, "Failed to allocate RQ data"); + rte_errno = ENOMEM; + return NULL; + } + MLX5_SET(create_rq_in, in, opcode, MLX5_CMD_OP_CREATE_RQ); + rq_ctx = MLX5_ADDR_OF(create_rq_in, in, ctx); + MLX5_SET(rqc, rq_ctx, rlky, rq_attr->rlky); + MLX5_SET(rqc, rq_ctx, delay_drop_en, rq_attr->delay_drop_en); + MLX5_SET(rqc, rq_ctx, scatter_fcs, rq_attr->scatter_fcs); + MLX5_SET(rqc, rq_ctx, vsd, rq_attr->vsd); + MLX5_SET(rqc, rq_ctx, mem_rq_type, rq_attr->mem_rq_type); + MLX5_SET(rqc, rq_ctx, state, rq_attr->state); + MLX5_SET(rqc, rq_ctx, flush_in_error_en, rq_attr->flush_in_error_en); + MLX5_SET(rqc, rq_ctx, hairpin, rq_attr->hairpin); + MLX5_SET(rqc, rq_ctx, user_index, rq_attr->user_index); + MLX5_SET(rqc, rq_ctx, cqn, rq_attr->cqn); + MLX5_SET(rqc, rq_ctx, counter_set_id, rq_attr->counter_set_id); + MLX5_SET(rqc, rq_ctx, rmpn, rq_attr->rmpn); + wq_ctx = MLX5_ADDR_OF(rqc, rq_ctx, wq); + wq_attr = &rq_attr->wq_attr; + devx_cmd_fill_wq_data(wq_ctx, wq_attr); + rq->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), + out, sizeof(out)); + if (!rq->obj) { + DRV_LOG(ERR, "Failed to create RQ using DevX"); + rte_errno = errno; + rte_free(rq); + return NULL; + } + rq->id = MLX5_GET(create_rq_out, out, rqn); + return rq; +} + +/** + * Modify RQ using DevX API. + * + * @param[in] rq + * Pointer to RQ object structure. + * @param [in] rq_attr + * Pointer to modify RQ attributes structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_devx_cmd_modify_rq(struct mlx5_devx_obj *rq, + struct mlx5_devx_modify_rq_attr *rq_attr) +{ + uint32_t in[MLX5_ST_SZ_DW(modify_rq_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(modify_rq_out)] = {0}; + void *rq_ctx, *wq_ctx; + int ret; + + MLX5_SET(modify_rq_in, in, opcode, MLX5_CMD_OP_MODIFY_RQ); + MLX5_SET(modify_rq_in, in, rq_state, rq_attr->rq_state); + MLX5_SET(modify_rq_in, in, rqn, rq->id); + MLX5_SET64(modify_rq_in, in, modify_bitmask, rq_attr->modify_bitmask); + rq_ctx = MLX5_ADDR_OF(modify_rq_in, in, ctx); + MLX5_SET(rqc, rq_ctx, state, rq_attr->state); + if (rq_attr->modify_bitmask & + MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_SCATTER_FCS) + MLX5_SET(rqc, rq_ctx, scatter_fcs, rq_attr->scatter_fcs); + if (rq_attr->modify_bitmask & MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_VSD) + MLX5_SET(rqc, rq_ctx, vsd, rq_attr->vsd); + if (rq_attr->modify_bitmask & + MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_RQ_COUNTER_SET_ID) + MLX5_SET(rqc, rq_ctx, counter_set_id, rq_attr->counter_set_id); + MLX5_SET(rqc, rq_ctx, hairpin_peer_sq, rq_attr->hairpin_peer_sq); + MLX5_SET(rqc, rq_ctx, hairpin_peer_vhca, rq_attr->hairpin_peer_vhca); + if (rq_attr->modify_bitmask & MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_WQ_LWM) { + wq_ctx = MLX5_ADDR_OF(rqc, rq_ctx, wq); + MLX5_SET(wq, wq_ctx, lwm, rq_attr->lwm); + } + ret = mlx5_glue->devx_obj_modify(rq->obj, in, sizeof(in), + out, sizeof(out)); + if (ret) { + DRV_LOG(ERR, "Failed to modify RQ using DevX"); + rte_errno = errno; + return -errno; + } + return ret; +} + +/** + * Create TIR using DevX API. + * + * @param[in] ctx + * ibv_context returned from mlx5dv_open_device. + * @param [in] tir_attr + * Pointer to TIR attributes structure. + * + * @return + * The DevX object created, NULL otherwise and rte_errno is set. + */ +struct mlx5_devx_obj * +mlx5_devx_cmd_create_tir(struct ibv_context *ctx, + struct mlx5_devx_tir_attr *tir_attr) +{ + uint32_t in[MLX5_ST_SZ_DW(create_tir_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(create_tir_out)] = {0}; + void *tir_ctx, *outer, *inner; + struct mlx5_devx_obj *tir = NULL; + int i; + + tir = rte_calloc(__func__, 1, sizeof(*tir), 0); + if (!tir) { + DRV_LOG(ERR, "Failed to allocate TIR data"); + rte_errno = ENOMEM; + return NULL; + } + MLX5_SET(create_tir_in, in, opcode, MLX5_CMD_OP_CREATE_TIR); + tir_ctx = MLX5_ADDR_OF(create_tir_in, in, ctx); + MLX5_SET(tirc, tir_ctx, disp_type, tir_attr->disp_type); + MLX5_SET(tirc, tir_ctx, lro_timeout_period_usecs, + tir_attr->lro_timeout_period_usecs); + MLX5_SET(tirc, tir_ctx, lro_enable_mask, tir_attr->lro_enable_mask); + MLX5_SET(tirc, tir_ctx, lro_max_msg_sz, tir_attr->lro_max_msg_sz); + MLX5_SET(tirc, tir_ctx, inline_rqn, tir_attr->inline_rqn); + MLX5_SET(tirc, tir_ctx, rx_hash_symmetric, tir_attr->rx_hash_symmetric); + MLX5_SET(tirc, tir_ctx, tunneled_offload_en, + tir_attr->tunneled_offload_en); + MLX5_SET(tirc, tir_ctx, indirect_table, tir_attr->indirect_table); + MLX5_SET(tirc, tir_ctx, rx_hash_fn, tir_attr->rx_hash_fn); + MLX5_SET(tirc, tir_ctx, self_lb_block, tir_attr->self_lb_block); + MLX5_SET(tirc, tir_ctx, transport_domain, tir_attr->transport_domain); + for (i = 0; i < 10; i++) { + MLX5_SET(tirc, tir_ctx, rx_hash_toeplitz_key[i], + tir_attr->rx_hash_toeplitz_key[i]); + } + outer = MLX5_ADDR_OF(tirc, tir_ctx, rx_hash_field_selector_outer); + MLX5_SET(rx_hash_field_select, outer, l3_prot_type, + tir_attr->rx_hash_field_selector_outer.l3_prot_type); + MLX5_SET(rx_hash_field_select, outer, l4_prot_type, + tir_attr->rx_hash_field_selector_outer.l4_prot_type); + MLX5_SET(rx_hash_field_select, outer, selected_fields, + tir_attr->rx_hash_field_selector_outer.selected_fields); + inner = MLX5_ADDR_OF(tirc, tir_ctx, rx_hash_field_selector_inner); + MLX5_SET(rx_hash_field_select, inner, l3_prot_type, + tir_attr->rx_hash_field_selector_inner.l3_prot_type); + MLX5_SET(rx_hash_field_select, inner, l4_prot_type, + tir_attr->rx_hash_field_selector_inner.l4_prot_type); + MLX5_SET(rx_hash_field_select, inner, selected_fields, + tir_attr->rx_hash_field_selector_inner.selected_fields); + tir->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), + out, sizeof(out)); + if (!tir->obj) { + DRV_LOG(ERR, "Failed to create TIR using DevX"); + rte_errno = errno; + rte_free(tir); + return NULL; + } + tir->id = MLX5_GET(create_tir_out, out, tirn); + return tir; +} + +/** + * Create RQT using DevX API. + * + * @param[in] ctx + * ibv_context returned from mlx5dv_open_device. + * @param [in] rqt_attr + * Pointer to RQT attributes structure. + * + * @return + * The DevX object created, NULL otherwise and rte_errno is set. + */ +struct mlx5_devx_obj * +mlx5_devx_cmd_create_rqt(struct ibv_context *ctx, + struct mlx5_devx_rqt_attr *rqt_attr) +{ + uint32_t *in = NULL; + uint32_t inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + + rqt_attr->rqt_actual_size * sizeof(uint32_t); + uint32_t out[MLX5_ST_SZ_DW(create_rqt_out)] = {0}; + void *rqt_ctx; + struct mlx5_devx_obj *rqt = NULL; + int i; + + in = rte_calloc(__func__, 1, inlen, 0); + if (!in) { + DRV_LOG(ERR, "Failed to allocate RQT IN data"); + rte_errno = ENOMEM; + return NULL; + } + rqt = rte_calloc(__func__, 1, sizeof(*rqt), 0); + if (!rqt) { + DRV_LOG(ERR, "Failed to allocate RQT data"); + rte_errno = ENOMEM; + rte_free(in); + return NULL; + } + MLX5_SET(create_rqt_in, in, opcode, MLX5_CMD_OP_CREATE_RQT); + rqt_ctx = MLX5_ADDR_OF(create_rqt_in, in, rqt_context); + MLX5_SET(rqtc, rqt_ctx, rqt_max_size, rqt_attr->rqt_max_size); + MLX5_SET(rqtc, rqt_ctx, rqt_actual_size, rqt_attr->rqt_actual_size); + for (i = 0; i < rqt_attr->rqt_actual_size; i++) + MLX5_SET(rqtc, rqt_ctx, rq_num[i], rqt_attr->rq_list[i]); + rqt->obj = mlx5_glue->devx_obj_create(ctx, in, inlen, out, sizeof(out)); + rte_free(in); + if (!rqt->obj) { + DRV_LOG(ERR, "Failed to create RQT using DevX"); + rte_errno = errno; + rte_free(rqt); + return NULL; + } + rqt->id = MLX5_GET(create_rqt_out, out, rqtn); + return rqt; +}