X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcommon%2Fmlx5%2Fmlx5_devx_cmds.c;h=fba485e72459dce6ba98db187498545c76883173;hb=4211cc0e922616f9d017504b0db6d3f91b111bcd;hp=cdc041b6e4f1fa850ec275b447c18bbd0c44dada;hpb=446c3781c46865de8fc18f738cd44b2ab9f13948;p=dpdk.git diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index cdc041b6e4..fba485e724 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -15,7 +15,7 @@ * Allocate flow counters via devx interface. * * @param[in] ctx - * ibv contexts returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param dcs * Pointer to counters properties structure to be filled by the routine. * @param bulk_n_128 @@ -26,7 +26,7 @@ * rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx, uint32_t bulk_n_128) +mlx5_devx_cmd_flow_counter_alloc(void *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}; @@ -81,7 +81,7 @@ 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, + void *cmd_comp, uint64_t async_id) { int out_len = MLX5_ST_SZ_BYTES(query_flow_counter_out) + @@ -130,7 +130,7 @@ mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_obj *dcs, * Create a new mkey. * * @param[in] ctx - * ibv contexts returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param[in] attr * Attributes of the requested mkey. * @@ -139,7 +139,7 @@ mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_obj *dcs, * is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_mkey_create(struct ibv_context *ctx, +mlx5_devx_cmd_mkey_create(void *ctx, struct mlx5_devx_mkey_attr *attr) { struct mlx5_klm *klm_array = attr->klm_array; @@ -196,6 +196,10 @@ mlx5_devx_cmd_mkey_create(struct ibv_context *ctx, 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); + if (attr->relaxed_ordering == 1) { + MLX5_SET(mkc, mkc, relaxed_ordering_write, 0x1); + MLX5_SET(mkc, mkc, relaxed_ordering_read, 0x1); + } MLX5_SET64(mkc, mkc, start_addr, attr->addr); MLX5_SET64(mkc, mkc, len, attr->size); mkey->obj = mlx5_glue->devx_obj_create(ctx, in, in_size_dw * 4, out, @@ -275,7 +279,7 @@ mlx5_devx_cmd_destroy(struct mlx5_devx_obj *obj) * 0 on success, a negative value otherwise. */ static int -mlx5_devx_cmd_query_nic_vport_context(struct ibv_context *ctx, +mlx5_devx_cmd_query_nic_vport_context(void *ctx, unsigned int vport, struct mlx5_hca_attr *attr) { @@ -317,12 +321,12 @@ error: * Query NIC vDPA attributes. * * @param[in] ctx - * ibv contexts returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param[out] vdpa_attr * vDPA Attributes structure to fill. */ static void -mlx5_devx_cmd_query_hca_vdpa_attr(struct ibv_context *ctx, +mlx5_devx_cmd_query_hca_vdpa_attr(void *ctx, struct mlx5_hca_vdpa_attr *vdpa_attr) { uint32_t in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0}; @@ -377,24 +381,18 @@ mlx5_devx_cmd_query_hca_vdpa_attr(struct ibv_context *ctx, vdpa_attr->max_num_virtio_queues = MLX5_GET(virtio_emulation_cap, hcattr, max_num_virtio_queues); - vdpa_attr->umem_1_buffer_param_a = - MLX5_GET(virtio_emulation_cap, hcattr, - umem_1_buffer_param_a); - vdpa_attr->umem_1_buffer_param_b = - MLX5_GET(virtio_emulation_cap, hcattr, - umem_1_buffer_param_b); - vdpa_attr->umem_2_buffer_param_a = - MLX5_GET(virtio_emulation_cap, hcattr, - umem_2_buffer_param_a); - vdpa_attr->umem_2_buffer_param_b = - MLX5_GET(virtio_emulation_cap, hcattr, - umem_2_buffer_param_a); - vdpa_attr->umem_3_buffer_param_a = - MLX5_GET(virtio_emulation_cap, hcattr, - umem_3_buffer_param_a); - vdpa_attr->umem_3_buffer_param_b = - MLX5_GET(virtio_emulation_cap, hcattr, - umem_3_buffer_param_b); + vdpa_attr->umems[0].a = MLX5_GET(virtio_emulation_cap, hcattr, + umem_1_buffer_param_a); + vdpa_attr->umems[0].b = MLX5_GET(virtio_emulation_cap, hcattr, + umem_1_buffer_param_b); + vdpa_attr->umems[1].a = MLX5_GET(virtio_emulation_cap, hcattr, + umem_2_buffer_param_a); + vdpa_attr->umems[1].b = MLX5_GET(virtio_emulation_cap, hcattr, + umem_2_buffer_param_b); + vdpa_attr->umems[2].a = MLX5_GET(virtio_emulation_cap, hcattr, + umem_3_buffer_param_a); + vdpa_attr->umems[2].b = MLX5_GET(virtio_emulation_cap, hcattr, + umem_3_buffer_param_b); } } @@ -404,7 +402,7 @@ mlx5_devx_cmd_query_hca_vdpa_attr(struct ibv_context *ctx, * is having the required capabilities. * * @param[in] ctx - * ibv contexts returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param[out] attr * Attributes device values. * @@ -412,7 +410,7 @@ mlx5_devx_cmd_query_hca_vdpa_attr(struct ibv_context *ctx, * 0 on success, a negative value otherwise. */ int -mlx5_devx_cmd_query_hca_attr(struct ibv_context *ctx, +mlx5_devx_cmd_query_hca_attr(void *ctx, struct mlx5_hca_attr *attr) { uint32_t in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0}; @@ -442,6 +440,8 @@ mlx5_devx_cmd_query_hca_attr(struct ibv_context *ctx, MLX5_GET(cmd_hca_cap, hcattr, flow_counter_bulk_alloc); attr->flow_counters_dump = MLX5_GET(cmd_hca_cap, hcattr, flow_counters_dump); + attr->log_max_rqt_size = MLX5_GET(cmd_hca_cap, hcattr, + log_max_rqt_size); attr->eswitch_manager = MLX5_GET(cmd_hca_cap, hcattr, eswitch_manager); attr->hairpin = MLX5_GET(cmd_hca_cap, hcattr, hairpin); attr->log_max_hairpin_queues = MLX5_GET(cmd_hca_cap, hcattr, @@ -451,6 +451,10 @@ mlx5_devx_cmd_query_hca_attr(struct ibv_context *ctx, attr->log_max_hairpin_num_packets = MLX5_GET (cmd_hca_cap, hcattr, log_min_hairpin_wq_data_sz); attr->vhca_id = MLX5_GET(cmd_hca_cap, hcattr, vhca_id); + attr->relaxed_ordering_write = MLX5_GET(cmd_hca_cap, hcattr, + relaxed_ordering_write); + attr->relaxed_ordering_read = MLX5_GET(cmd_hca_cap, hcattr, + relaxed_ordering_read); attr->eth_net_offloads = MLX5_GET(cmd_hca_cap, hcattr, eth_net_offloads); attr->eth_virt = MLX5_GET(cmd_hca_cap, hcattr, eth_virt); @@ -570,7 +574,7 @@ error: * 0 on success, a negative value otherwise. */ int -mlx5_devx_cmd_qp_query_tis_td(struct ibv_qp *qp, uint32_t tis_num, +mlx5_devx_cmd_qp_query_tis_td(void *qp, uint32_t tis_num, uint32_t *tis_td) { uint32_t in[MLX5_ST_SZ_DW(query_tis_in)] = {0}; @@ -637,7 +641,7 @@ devx_cmd_fill_wq_data(void *wq_ctx, struct mlx5_devx_wq_attr *wq_attr) * Create RQ using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param [in] rq_attr * Pointer to create RQ attributes structure. * @param [in] socket @@ -647,7 +651,7 @@ devx_cmd_fill_wq_data(void *wq_ctx, struct mlx5_devx_wq_attr *wq_attr) * The DevX object created, NULL otherwise and rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_create_rq(struct ibv_context *ctx, +mlx5_devx_cmd_create_rq(void *ctx, struct mlx5_devx_create_rq_attr *rq_attr, int socket) { @@ -746,7 +750,7 @@ mlx5_devx_cmd_modify_rq(struct mlx5_devx_obj *rq, * Create TIR using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param [in] tir_attr * Pointer to TIR attributes structure. * @@ -754,14 +758,13 @@ mlx5_devx_cmd_modify_rq(struct mlx5_devx_obj *rq, * The DevX object created, NULL otherwise and rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_create_tir(struct ibv_context *ctx, +mlx5_devx_cmd_create_tir(void *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; + void *tir_ctx, *outer, *inner, *rss_key; struct mlx5_devx_obj *tir = NULL; - int i; tir = rte_calloc(__func__, 1, sizeof(*tir), 0); if (!tir) { @@ -784,10 +787,8 @@ mlx5_devx_cmd_create_tir(struct ibv_context *ctx, 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]); - } + rss_key = MLX5_ADDR_OF(tirc, tir_ctx, rx_hash_toeplitz_key); + memcpy(rss_key, tir_attr->rx_hash_toeplitz_key, MLX5_RSS_HASH_KEY_LEN); 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); @@ -818,7 +819,7 @@ mlx5_devx_cmd_create_tir(struct ibv_context *ctx, * Create RQT using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param [in] rqt_attr * Pointer to RQT attributes structure. * @@ -826,7 +827,7 @@ mlx5_devx_cmd_create_tir(struct ibv_context *ctx, * The DevX object created, NULL otherwise and rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_create_rqt(struct ibv_context *ctx, +mlx5_devx_cmd_create_rqt(void *ctx, struct mlx5_devx_rqt_attr *rqt_attr) { uint32_t *in = NULL; @@ -852,6 +853,7 @@ mlx5_devx_cmd_create_rqt(struct ibv_context *ctx, } 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, list_q_type, rqt_attr->rq_type); 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++) @@ -868,11 +870,58 @@ mlx5_devx_cmd_create_rqt(struct ibv_context *ctx, return rqt; } +/** + * Modify RQT using DevX API. + * + * @param[in] rqt + * Pointer to RQT DevX object structure. + * @param [in] rqt_attr + * Pointer to RQT attributes structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_devx_cmd_modify_rqt(struct mlx5_devx_obj *rqt, + struct mlx5_devx_rqt_attr *rqt_attr) +{ + uint32_t inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + + rqt_attr->rqt_actual_size * sizeof(uint32_t); + uint32_t out[MLX5_ST_SZ_DW(modify_rqt_out)] = {0}; + uint32_t *in = rte_calloc(__func__, 1, inlen, 0); + void *rqt_ctx; + int i; + int ret; + + if (!in) { + DRV_LOG(ERR, "Failed to allocate RQT modify IN data."); + rte_errno = ENOMEM; + return -ENOMEM; + } + MLX5_SET(modify_rqt_in, in, opcode, MLX5_CMD_OP_MODIFY_RQT); + MLX5_SET(modify_rqt_in, in, rqtn, rqt->id); + MLX5_SET64(modify_rqt_in, in, modify_bitmask, 0x1); + rqt_ctx = MLX5_ADDR_OF(modify_rqt_in, in, rqt_context); + MLX5_SET(rqtc, rqt_ctx, list_q_type, rqt_attr->rq_type); + 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]); + ret = mlx5_glue->devx_obj_modify(rqt->obj, in, inlen, out, sizeof(out)); + rte_free(in); + if (ret) { + DRV_LOG(ERR, "Failed to modify RQT using DevX."); + rte_errno = errno; + return -rte_errno; + } + return ret; +} + /** * Create SQ using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param [in] sq_attr * Pointer to SQ attributes structure. * @param [in] socket @@ -882,7 +931,7 @@ mlx5_devx_cmd_create_rqt(struct ibv_context *ctx, * The DevX object created, NULL otherwise and rte_errno is set. **/ struct mlx5_devx_obj * -mlx5_devx_cmd_create_sq(struct ibv_context *ctx, +mlx5_devx_cmd_create_sq(void *ctx, struct mlx5_devx_create_sq_attr *sq_attr) { uint32_t in[MLX5_ST_SZ_DW(create_sq_in)] = {0}; @@ -974,7 +1023,7 @@ mlx5_devx_cmd_modify_sq(struct mlx5_devx_obj *sq, * Create TIS using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param [in] tis_attr * Pointer to TIS attributes structure. * @@ -982,7 +1031,7 @@ mlx5_devx_cmd_modify_sq(struct mlx5_devx_obj *sq, * The DevX object created, NULL otherwise and rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_create_tis(struct ibv_context *ctx, +mlx5_devx_cmd_create_tis(void *ctx, struct mlx5_devx_tis_attr *tis_attr) { uint32_t in[MLX5_ST_SZ_DW(create_tis_in)] = {0}; @@ -1021,13 +1070,12 @@ mlx5_devx_cmd_create_tis(struct ibv_context *ctx, * Create transport domain using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. - * + * Context returned from mlx5 open_device() glue function. * @return * The DevX object created, NULL otherwise and rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_create_td(struct ibv_context *ctx) +mlx5_devx_cmd_create_td(void *ctx) { uint32_t in[MLX5_ST_SZ_DW(alloc_transport_domain_in)] = {0}; uint32_t out[MLX5_ST_SZ_DW(alloc_transport_domain_out)] = {0}; @@ -1082,11 +1130,11 @@ mlx5_devx_cmd_flow_dump(void *fdb_domain __rte_unused, if (ret) return ret; } - assert(rx_domain); + MLX5_ASSERT(rx_domain); ret = mlx5_glue->dr_dump_domain(file, rx_domain); if (ret) return ret; - assert(tx_domain); + MLX5_ASSERT(tx_domain); ret = mlx5_glue->dr_dump_domain(file, tx_domain); #else ret = ENOTSUP; @@ -1098,7 +1146,7 @@ mlx5_devx_cmd_flow_dump(void *fdb_domain __rte_unused, * Create CQ using DevX API. * * @param[in] ctx - * ibv_context returned from mlx5dv_open_device. + * Context returned from mlx5 open_device() glue function. * @param [in] attr * Pointer to CQ attributes structure. * @@ -1106,7 +1154,7 @@ mlx5_devx_cmd_flow_dump(void *fdb_domain __rte_unused, * The DevX object created, NULL otherwise and rte_errno is set. */ struct mlx5_devx_obj * -mlx5_devx_cmd_create_cq(struct ibv_context *ctx, struct mlx5_devx_cq_attr *attr) +mlx5_devx_cmd_create_cq(void *ctx, struct mlx5_devx_cq_attr *attr) { uint32_t in[MLX5_ST_SZ_DW(create_cq_in)] = {0}; uint32_t out[MLX5_ST_SZ_DW(create_cq_out)] = {0}; @@ -1130,7 +1178,8 @@ mlx5_devx_cmd_create_cq(struct ibv_context *ctx, struct mlx5_devx_cq_attr *attr) 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); - MLX5_SET(cqc, cqctx, log_page_size, attr->log_page_size); + MLX5_SET(cqc, cqctx, log_page_size, attr->log_page_size - + MLX5_ADAPTER_PAGE_SHIFT); MLX5_SET(cqc, cqctx, c_eqn, attr->eqn); MLX5_SET(cqc, cqctx, uar_page, attr->uar_page_id); if (attr->q_umem_valid) { @@ -1150,3 +1199,336 @@ mlx5_devx_cmd_create_cq(struct ibv_context *ctx, struct mlx5_devx_cq_attr *attr) cq_obj->id = MLX5_GET(create_cq_out, out, cqn); return cq_obj; } + +/** + * Create VIRTQ using DevX API. + * + * @param[in] ctx + * Context returned from mlx5 open_device() glue function. + * @param [in] attr + * Pointer to VIRTQ attributes structure. + * + * @return + * The DevX object created, NULL otherwise and rte_errno is set. + */ +struct mlx5_devx_obj * +mlx5_devx_cmd_create_virtq(void *ctx, + struct mlx5_devx_virtq_attr *attr) +{ + uint32_t in[MLX5_ST_SZ_DW(create_virtq_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; + struct mlx5_devx_obj *virtq_obj = rte_zmalloc(__func__, + sizeof(*virtq_obj), 0); + void *virtq = MLX5_ADDR_OF(create_virtq_in, in, virtq); + void *hdr = MLX5_ADDR_OF(create_virtq_in, in, hdr); + void *virtctx = MLX5_ADDR_OF(virtio_net_q, virtq, virtio_q_context); + + if (!virtq_obj) { + DRV_LOG(ERR, "Failed to allocate virtq 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_VIRTQ); + MLX5_SET16(virtio_net_q, virtq, hw_available_index, + attr->hw_available_index); + MLX5_SET16(virtio_net_q, virtq, hw_used_index, attr->hw_used_index); + MLX5_SET16(virtio_net_q, virtq, tso_ipv4, attr->tso_ipv4); + MLX5_SET16(virtio_net_q, virtq, tso_ipv6, attr->tso_ipv6); + MLX5_SET16(virtio_net_q, virtq, tx_csum, attr->tx_csum); + MLX5_SET16(virtio_net_q, virtq, rx_csum, attr->rx_csum); + MLX5_SET16(virtio_q, virtctx, virtio_version_1_0, + attr->virtio_version_1_0); + MLX5_SET16(virtio_q, virtctx, event_mode, attr->event_mode); + MLX5_SET(virtio_q, virtctx, event_qpn_or_msix, attr->qp_id); + MLX5_SET64(virtio_q, virtctx, desc_addr, attr->desc_addr); + MLX5_SET64(virtio_q, virtctx, used_addr, attr->used_addr); + MLX5_SET64(virtio_q, virtctx, available_addr, attr->available_addr); + MLX5_SET16(virtio_q, virtctx, queue_index, attr->queue_index); + MLX5_SET16(virtio_q, virtctx, queue_size, attr->q_size); + MLX5_SET(virtio_q, virtctx, virtio_q_mkey, attr->mkey); + MLX5_SET(virtio_q, virtctx, umem_1_id, attr->umems[0].id); + MLX5_SET(virtio_q, virtctx, umem_1_size, attr->umems[0].size); + MLX5_SET64(virtio_q, virtctx, umem_1_offset, attr->umems[0].offset); + MLX5_SET(virtio_q, virtctx, umem_2_id, attr->umems[1].id); + MLX5_SET(virtio_q, virtctx, umem_2_size, attr->umems[1].size); + MLX5_SET64(virtio_q, virtctx, umem_2_offset, attr->umems[1].offset); + 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_net_q, virtq, tisn_or_qpn, attr->tis_id); + virtq_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, + sizeof(out)); + if (!virtq_obj->obj) { + rte_errno = errno; + DRV_LOG(ERR, "Failed to create VIRTQ Obj using DevX."); + rte_free(virtq_obj); + return NULL; + } + virtq_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); + return virtq_obj; +} + +/** + * Modify VIRTQ using DevX API. + * + * @param[in] virtq_obj + * Pointer to virtq object structure. + * @param [in] attr + * Pointer to modify virtq attributes structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_devx_cmd_modify_virtq(struct mlx5_devx_obj *virtq_obj, + struct mlx5_devx_virtq_attr *attr) +{ + uint32_t in[MLX5_ST_SZ_DW(create_virtq_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; + void *virtq = MLX5_ADDR_OF(create_virtq_in, in, virtq); + void *hdr = MLX5_ADDR_OF(create_virtq_in, in, hdr); + void *virtctx = MLX5_ADDR_OF(virtio_net_q, virtq, virtio_q_context); + int ret; + + MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, + MLX5_CMD_OP_MODIFY_GENERAL_OBJECT); + MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, + MLX5_GENERAL_OBJ_TYPE_VIRTQ); + MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_id, virtq_obj->id); + MLX5_SET64(virtio_net_q, virtq, modify_field_select, attr->type); + MLX5_SET16(virtio_q, virtctx, queue_index, attr->queue_index); + switch (attr->type) { + case MLX5_VIRTQ_MODIFY_TYPE_STATE: + MLX5_SET16(virtio_net_q, virtq, state, attr->state); + break; + case MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_PARAMS: + MLX5_SET(virtio_net_q, virtq, dirty_bitmap_mkey, + attr->dirty_bitmap_mkey); + MLX5_SET64(virtio_net_q, virtq, dirty_bitmap_addr, + attr->dirty_bitmap_addr); + MLX5_SET(virtio_net_q, virtq, dirty_bitmap_size, + attr->dirty_bitmap_size); + break; + case MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_DUMP_ENABLE: + MLX5_SET(virtio_net_q, virtq, dirty_bitmap_dump_enable, + attr->dirty_bitmap_dump_enable); + break; + default: + rte_errno = EINVAL; + return -rte_errno; + } + ret = mlx5_glue->devx_obj_modify(virtq_obj->obj, in, sizeof(in), + out, sizeof(out)); + if (ret) { + DRV_LOG(ERR, "Failed to modify VIRTQ using DevX."); + rte_errno = errno; + return -errno; + } + return ret; +} + +/** + * Query VIRTQ using DevX API. + * + * @param[in] virtq_obj + * Pointer to virtq object structure. + * @param [in/out] attr + * Pointer to virtq attributes structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_devx_cmd_query_virtq(struct mlx5_devx_obj *virtq_obj, + struct mlx5_devx_virtq_attr *attr) +{ + uint32_t in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(query_virtq_out)] = {0}; + void *hdr = MLX5_ADDR_OF(query_virtq_out, in, hdr); + void *virtq = MLX5_ADDR_OF(query_virtq_out, out, virtq); + 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_VIRTQ); + MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_id, virtq_obj->id); + ret = mlx5_glue->devx_obj_query(virtq_obj->obj, in, sizeof(in), + out, sizeof(out)); + if (ret) { + DRV_LOG(ERR, "Failed to modify VIRTQ using DevX."); + rte_errno = errno; + return -errno; + } + attr->hw_available_index = MLX5_GET16(virtio_net_q, virtq, + hw_available_index); + attr->hw_used_index = MLX5_GET16(virtio_net_q, virtq, hw_used_index); + return ret; +} + +/** + * Create QP using DevX API. + * + * @param[in] ctx + * Context returned from mlx5 open_device() glue function. + * @param [in] attr + * Pointer to QP attributes structure. + * + * @return + * The DevX object created, NULL otherwise and rte_errno is set. + */ +struct mlx5_devx_obj * +mlx5_devx_cmd_create_qp(void *ctx, + struct mlx5_devx_qp_attr *attr) +{ + uint32_t in[MLX5_ST_SZ_DW(create_qp_in)] = {0}; + uint32_t out[MLX5_ST_SZ_DW(create_qp_out)] = {0}; + struct mlx5_devx_obj *qp_obj = rte_zmalloc(__func__, sizeof(*qp_obj), + 0); + void *qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); + + if (!qp_obj) { + DRV_LOG(ERR, "Failed to allocate QP data."); + rte_errno = ENOMEM; + return NULL; + } + MLX5_SET(create_qp_in, in, opcode, MLX5_CMD_OP_CREATE_QP); + MLX5_SET(qpc, qpc, st, MLX5_QP_ST_RC); + MLX5_SET(qpc, qpc, pd, attr->pd); + if (attr->uar_index) { + MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); + MLX5_SET(qpc, qpc, uar_page, attr->uar_index); + MLX5_SET(qpc, qpc, log_page_size, attr->log_page_size - + MLX5_ADAPTER_PAGE_SHIFT); + if (attr->sq_size) { + MLX5_ASSERT(RTE_IS_POWER_OF_2(attr->sq_size)); + MLX5_SET(qpc, qpc, cqn_snd, attr->cqn); + MLX5_SET(qpc, qpc, log_sq_size, + rte_log2_u32(attr->sq_size)); + } else { + MLX5_SET(qpc, qpc, no_sq, 1); + } + if (attr->rq_size) { + MLX5_ASSERT(RTE_IS_POWER_OF_2(attr->rq_size)); + MLX5_SET(qpc, qpc, cqn_rcv, attr->cqn); + MLX5_SET(qpc, qpc, log_rq_stride, attr->log_rq_stride - + MLX5_LOG_RQ_STRIDE_SHIFT); + MLX5_SET(qpc, qpc, log_rq_size, + rte_log2_u32(attr->rq_size)); + MLX5_SET(qpc, qpc, rq_type, MLX5_NON_ZERO_RQ); + } else { + MLX5_SET(qpc, qpc, rq_type, MLX5_ZERO_LEN_RQ); + } + if (attr->dbr_umem_valid) { + MLX5_SET(qpc, qpc, dbr_umem_valid, + attr->dbr_umem_valid); + MLX5_SET(qpc, qpc, dbr_umem_id, attr->dbr_umem_id); + } + MLX5_SET64(qpc, qpc, dbr_addr, attr->dbr_address); + MLX5_SET64(create_qp_in, in, wq_umem_offset, + attr->wq_umem_offset); + MLX5_SET(create_qp_in, in, wq_umem_id, attr->wq_umem_id); + MLX5_SET(create_qp_in, in, wq_umem_valid, 1); + } else { + /* Special QP to be managed by FW - no SQ\RQ\CQ\UAR\DB rec. */ + MLX5_SET(qpc, qpc, rq_type, MLX5_ZERO_LEN_RQ); + MLX5_SET(qpc, qpc, no_sq, 1); + } + qp_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, + sizeof(out)); + if (!qp_obj->obj) { + rte_errno = errno; + DRV_LOG(ERR, "Failed to create QP Obj using DevX."); + rte_free(qp_obj); + return NULL; + } + qp_obj->id = MLX5_GET(create_qp_out, out, qpn); + return qp_obj; +} + +/** + * Modify QP using DevX API. + * Currently supports only force loop-back QP. + * + * @param[in] qp + * Pointer to QP object structure. + * @param [in] qp_st_mod_op + * The QP state modification operation. + * @param [in] remote_qp_id + * The remote QP ID for MLX5_CMD_OP_INIT2RTR_QP operation. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_devx_cmd_modify_qp_state(struct mlx5_devx_obj *qp, uint32_t qp_st_mod_op, + uint32_t remote_qp_id) +{ + union { + uint32_t rst2init[MLX5_ST_SZ_DW(rst2init_qp_in)]; + uint32_t init2rtr[MLX5_ST_SZ_DW(init2rtr_qp_in)]; + uint32_t rtr2rts[MLX5_ST_SZ_DW(rtr2rts_qp_in)]; + } in; + union { + uint32_t rst2init[MLX5_ST_SZ_DW(rst2init_qp_out)]; + uint32_t init2rtr[MLX5_ST_SZ_DW(init2rtr_qp_out)]; + uint32_t rtr2rts[MLX5_ST_SZ_DW(rtr2rts_qp_out)]; + } out; + void *qpc; + int ret; + unsigned int inlen; + unsigned int outlen; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + MLX5_SET(rst2init_qp_in, &in, opcode, qp_st_mod_op); + switch (qp_st_mod_op) { + case MLX5_CMD_OP_RST2INIT_QP: + MLX5_SET(rst2init_qp_in, &in, qpn, qp->id); + qpc = MLX5_ADDR_OF(rst2init_qp_in, &in, qpc); + MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, 1); + MLX5_SET(qpc, qpc, rre, 1); + MLX5_SET(qpc, qpc, rwe, 1); + MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); + inlen = sizeof(in.rst2init); + outlen = sizeof(out.rst2init); + break; + case MLX5_CMD_OP_INIT2RTR_QP: + MLX5_SET(init2rtr_qp_in, &in, qpn, qp->id); + qpc = MLX5_ADDR_OF(init2rtr_qp_in, &in, qpc); + MLX5_SET(qpc, qpc, primary_address_path.fl, 1); + MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, 1); + MLX5_SET(qpc, qpc, mtu, 1); + MLX5_SET(qpc, qpc, log_msg_max, 30); + MLX5_SET(qpc, qpc, remote_qpn, remote_qp_id); + MLX5_SET(qpc, qpc, min_rnr_nak, 0); + inlen = sizeof(in.init2rtr); + outlen = sizeof(out.init2rtr); + break; + case MLX5_CMD_OP_RTR2RTS_QP: + qpc = MLX5_ADDR_OF(rtr2rts_qp_in, &in, qpc); + MLX5_SET(rtr2rts_qp_in, &in, qpn, qp->id); + MLX5_SET(qpc, qpc, primary_address_path.ack_timeout, 14); + MLX5_SET(qpc, qpc, log_ack_req_freq, 0); + MLX5_SET(qpc, qpc, retry_count, 7); + MLX5_SET(qpc, qpc, rnr_retry, 7); + inlen = sizeof(in.rtr2rts); + outlen = sizeof(out.rtr2rts); + break; + default: + DRV_LOG(ERR, "Invalid or unsupported QP modify op %u.", + qp_st_mod_op); + rte_errno = EINVAL; + return -rte_errno; + } + ret = mlx5_glue->devx_obj_modify(qp->obj, &in, inlen, &out, outlen); + if (ret) { + DRV_LOG(ERR, "Failed to modify QP using DevX."); + rte_errno = errno; + return -errno; + } + return ret; +}