19dab4d62SMichael Baum /* SPDX-License-Identifier: BSD-3-Clause 29dab4d62SMichael Baum * Copyright 2020 Mellanox Technologies, Ltd 39dab4d62SMichael Baum */ 49dab4d62SMichael Baum #include <stdint.h> 59dab4d62SMichael Baum 69dab4d62SMichael Baum #include <rte_errno.h> 79dab4d62SMichael Baum #include <rte_common.h> 89dab4d62SMichael Baum #include <rte_eal_paging.h> 99dab4d62SMichael Baum 109dab4d62SMichael Baum #include <mlx5_glue.h> 119dab4d62SMichael Baum #include <mlx5_common_os.h> 129dab4d62SMichael Baum 139dab4d62SMichael Baum #include "mlx5_prm.h" 149dab4d62SMichael Baum #include "mlx5_devx_cmds.h" 159dab4d62SMichael Baum #include "mlx5_common_utils.h" 169dab4d62SMichael Baum #include "mlx5_malloc.h" 179dab4d62SMichael Baum #include "mlx5_common.h" 189dab4d62SMichael Baum #include "mlx5_common_devx.h" 199dab4d62SMichael Baum 209dab4d62SMichael Baum /** 219dab4d62SMichael Baum * Destroy DevX Completion Queue. 229dab4d62SMichael Baum * 239dab4d62SMichael Baum * @param[in] cq 249dab4d62SMichael Baum * DevX CQ to destroy. 259dab4d62SMichael Baum */ 269dab4d62SMichael Baum void 279dab4d62SMichael Baum mlx5_devx_cq_destroy(struct mlx5_devx_cq *cq) 289dab4d62SMichael Baum { 299dab4d62SMichael Baum if (cq->cq) 309dab4d62SMichael Baum claim_zero(mlx5_devx_cmd_destroy(cq->cq)); 319dab4d62SMichael Baum if (cq->umem_obj) 329dab4d62SMichael Baum claim_zero(mlx5_os_umem_dereg(cq->umem_obj)); 339dab4d62SMichael Baum if (cq->umem_buf) 349dab4d62SMichael Baum mlx5_free((void *)(uintptr_t)cq->umem_buf); 359dab4d62SMichael Baum } 369dab4d62SMichael Baum 379dab4d62SMichael Baum /* Mark all CQEs initially as invalid. */ 389dab4d62SMichael Baum static void 399dab4d62SMichael Baum mlx5_cq_init(struct mlx5_devx_cq *cq_obj, uint16_t cq_size) 409dab4d62SMichael Baum { 419dab4d62SMichael Baum volatile struct mlx5_cqe *cqe = cq_obj->cqes; 429dab4d62SMichael Baum uint16_t i; 439dab4d62SMichael Baum 449dab4d62SMichael Baum for (i = 0; i < cq_size; i++, cqe++) 459dab4d62SMichael Baum cqe->op_own = (MLX5_CQE_INVALID << 4) | MLX5_CQE_OWNER_MASK; 469dab4d62SMichael Baum } 479dab4d62SMichael Baum 489dab4d62SMichael Baum /** 499dab4d62SMichael Baum * Create Completion Queue using DevX API. 509dab4d62SMichael Baum * 519dab4d62SMichael Baum * Get a pointer to partially initialized attributes structure, and updates the 529dab4d62SMichael Baum * following fields: 539dab4d62SMichael Baum * q_umem_valid 549dab4d62SMichael Baum * q_umem_id 559dab4d62SMichael Baum * q_umem_offset 569dab4d62SMichael Baum * db_umem_valid 579dab4d62SMichael Baum * db_umem_id 589dab4d62SMichael Baum * db_umem_offset 599dab4d62SMichael Baum * eqn 609dab4d62SMichael Baum * log_cq_size 619dab4d62SMichael Baum * log_page_size 629dab4d62SMichael Baum * All other fields are updated by caller. 639dab4d62SMichael Baum * 649dab4d62SMichael Baum * @param[in] ctx 659dab4d62SMichael Baum * Context returned from mlx5 open_device() glue function. 669dab4d62SMichael Baum * @param[in/out] cq_obj 679dab4d62SMichael Baum * Pointer to CQ to create. 689dab4d62SMichael Baum * @param[in] log_desc_n 699dab4d62SMichael Baum * Log of number of descriptors in queue. 709dab4d62SMichael Baum * @param[in] attr 719dab4d62SMichael Baum * Pointer to CQ attributes structure. 729dab4d62SMichael Baum * @param[in] socket 739dab4d62SMichael Baum * Socket to use for allocation. 749dab4d62SMichael Baum * 759dab4d62SMichael Baum * @return 769dab4d62SMichael Baum * 0 on success, a negative errno value otherwise and rte_errno is set. 779dab4d62SMichael Baum */ 789dab4d62SMichael Baum int 799dab4d62SMichael Baum mlx5_devx_cq_create(void *ctx, struct mlx5_devx_cq *cq_obj, uint16_t log_desc_n, 809dab4d62SMichael Baum struct mlx5_devx_cq_attr *attr, int socket) 819dab4d62SMichael Baum { 829dab4d62SMichael Baum struct mlx5_devx_obj *cq = NULL; 839dab4d62SMichael Baum struct mlx5dv_devx_umem *umem_obj = NULL; 849dab4d62SMichael Baum void *umem_buf = NULL; 859dab4d62SMichael Baum size_t page_size = rte_mem_page_size(); 869dab4d62SMichael Baum size_t alignment = MLX5_CQE_BUF_ALIGNMENT; 879dab4d62SMichael Baum uint32_t umem_size, umem_dbrec; 889dab4d62SMichael Baum uint32_t eqn; 899dab4d62SMichael Baum uint16_t cq_size = 1 << log_desc_n; 909dab4d62SMichael Baum int ret; 919dab4d62SMichael Baum 929dab4d62SMichael Baum if (page_size == (size_t)-1 || alignment == (size_t)-1) { 939dab4d62SMichael Baum DRV_LOG(ERR, "Failed to get page_size."); 949dab4d62SMichael Baum rte_errno = ENOMEM; 959dab4d62SMichael Baum return -rte_errno; 969dab4d62SMichael Baum } 979dab4d62SMichael Baum /* Query first EQN. */ 989dab4d62SMichael Baum ret = mlx5_glue->devx_query_eqn(ctx, 0, &eqn); 999dab4d62SMichael Baum if (ret) { 1009dab4d62SMichael Baum rte_errno = errno; 1019dab4d62SMichael Baum DRV_LOG(ERR, "Failed to query event queue number."); 1029dab4d62SMichael Baum return -rte_errno; 1039dab4d62SMichael Baum } 1049dab4d62SMichael Baum /* Allocate memory buffer for CQEs and doorbell record. */ 1059dab4d62SMichael Baum umem_size = sizeof(struct mlx5_cqe) * cq_size; 1069dab4d62SMichael Baum umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE); 1079dab4d62SMichael Baum umem_size += MLX5_DBR_SIZE; 1089dab4d62SMichael Baum umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size, 1099dab4d62SMichael Baum alignment, socket); 1109dab4d62SMichael Baum if (!umem_buf) { 1119dab4d62SMichael Baum DRV_LOG(ERR, "Failed to allocate memory for CQ."); 1129dab4d62SMichael Baum rte_errno = ENOMEM; 1139dab4d62SMichael Baum return -rte_errno; 1149dab4d62SMichael Baum } 1159dab4d62SMichael Baum /* Register allocated buffer in user space with DevX. */ 1169dab4d62SMichael Baum umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf, umem_size, 1179dab4d62SMichael Baum IBV_ACCESS_LOCAL_WRITE); 1189dab4d62SMichael Baum if (!umem_obj) { 1199dab4d62SMichael Baum DRV_LOG(ERR, "Failed to register umem for CQ."); 1209dab4d62SMichael Baum rte_errno = errno; 1219dab4d62SMichael Baum goto error; 1229dab4d62SMichael Baum } 1239dab4d62SMichael Baum /* Fill attributes for CQ object creation. */ 1249dab4d62SMichael Baum attr->q_umem_valid = 1; 1259dab4d62SMichael Baum attr->q_umem_id = mlx5_os_get_umem_id(umem_obj); 1269dab4d62SMichael Baum attr->q_umem_offset = 0; 1279dab4d62SMichael Baum attr->db_umem_valid = 1; 1289dab4d62SMichael Baum attr->db_umem_id = attr->q_umem_id; 1299dab4d62SMichael Baum attr->db_umem_offset = umem_dbrec; 1309dab4d62SMichael Baum attr->eqn = eqn; 1319dab4d62SMichael Baum attr->log_cq_size = log_desc_n; 1329dab4d62SMichael Baum attr->log_page_size = rte_log2_u32(page_size); 1339dab4d62SMichael Baum /* Create completion queue object with DevX. */ 1349dab4d62SMichael Baum cq = mlx5_devx_cmd_create_cq(ctx, attr); 1359dab4d62SMichael Baum if (!cq) { 1369dab4d62SMichael Baum DRV_LOG(ERR, "Can't create DevX CQ object."); 1379dab4d62SMichael Baum rte_errno = ENOMEM; 1389dab4d62SMichael Baum goto error; 1399dab4d62SMichael Baum } 1409dab4d62SMichael Baum cq_obj->umem_buf = umem_buf; 1419dab4d62SMichael Baum cq_obj->umem_obj = umem_obj; 1429dab4d62SMichael Baum cq_obj->cq = cq; 1439dab4d62SMichael Baum cq_obj->db_rec = RTE_PTR_ADD(cq_obj->umem_buf, umem_dbrec); 1449dab4d62SMichael Baum /* Mark all CQEs initially as invalid. */ 1459dab4d62SMichael Baum mlx5_cq_init(cq_obj, cq_size); 1469dab4d62SMichael Baum return 0; 1479dab4d62SMichael Baum error: 1489dab4d62SMichael Baum ret = rte_errno; 1499dab4d62SMichael Baum if (umem_obj) 1509dab4d62SMichael Baum claim_zero(mlx5_os_umem_dereg(umem_obj)); 1519dab4d62SMichael Baum if (umem_buf) 1529dab4d62SMichael Baum mlx5_free((void *)(uintptr_t)umem_buf); 1539dab4d62SMichael Baum rte_errno = ret; 1549dab4d62SMichael Baum return -rte_errno; 1559dab4d62SMichael Baum } 15638f53763SMichael Baum 15738f53763SMichael Baum /** 15838f53763SMichael Baum * Destroy DevX Send Queue. 15938f53763SMichael Baum * 16038f53763SMichael Baum * @param[in] sq 16138f53763SMichael Baum * DevX SQ to destroy. 16238f53763SMichael Baum */ 16338f53763SMichael Baum void 16438f53763SMichael Baum mlx5_devx_sq_destroy(struct mlx5_devx_sq *sq) 16538f53763SMichael Baum { 16638f53763SMichael Baum if (sq->sq) 16738f53763SMichael Baum claim_zero(mlx5_devx_cmd_destroy(sq->sq)); 16838f53763SMichael Baum if (sq->umem_obj) 16938f53763SMichael Baum claim_zero(mlx5_os_umem_dereg(sq->umem_obj)); 17038f53763SMichael Baum if (sq->umem_buf) 17138f53763SMichael Baum mlx5_free((void *)(uintptr_t)sq->umem_buf); 17238f53763SMichael Baum } 17338f53763SMichael Baum 17438f53763SMichael Baum /** 17538f53763SMichael Baum * Create Send Queue using DevX API. 17638f53763SMichael Baum * 17738f53763SMichael Baum * Get a pointer to partially initialized attributes structure, and updates the 17838f53763SMichael Baum * following fields: 17938f53763SMichael Baum * wq_type 18038f53763SMichael Baum * wq_umem_valid 18138f53763SMichael Baum * wq_umem_id 18238f53763SMichael Baum * wq_umem_offset 18338f53763SMichael Baum * dbr_umem_valid 18438f53763SMichael Baum * dbr_umem_id 18538f53763SMichael Baum * dbr_addr 18638f53763SMichael Baum * log_wq_stride 18738f53763SMichael Baum * log_wq_sz 18838f53763SMichael Baum * log_wq_pg_sz 18938f53763SMichael Baum * All other fields are updated by caller. 19038f53763SMichael Baum * 19138f53763SMichael Baum * @param[in] ctx 19238f53763SMichael Baum * Context returned from mlx5 open_device() glue function. 19338f53763SMichael Baum * @param[in/out] sq_obj 19438f53763SMichael Baum * Pointer to SQ to create. 19538f53763SMichael Baum * @param[in] log_wqbb_n 19638f53763SMichael Baum * Log of number of WQBBs in queue. 19738f53763SMichael Baum * @param[in] attr 19838f53763SMichael Baum * Pointer to SQ attributes structure. 19938f53763SMichael Baum * @param[in] socket 20038f53763SMichael Baum * Socket to use for allocation. 20138f53763SMichael Baum * 20238f53763SMichael Baum * @return 20338f53763SMichael Baum * 0 on success, a negative errno value otherwise and rte_errno is set. 20438f53763SMichael Baum */ 20538f53763SMichael Baum int 20638f53763SMichael Baum mlx5_devx_sq_create(void *ctx, struct mlx5_devx_sq *sq_obj, uint16_t log_wqbb_n, 20738f53763SMichael Baum struct mlx5_devx_create_sq_attr *attr, int socket) 20838f53763SMichael Baum { 20938f53763SMichael Baum struct mlx5_devx_obj *sq = NULL; 21038f53763SMichael Baum struct mlx5dv_devx_umem *umem_obj = NULL; 21138f53763SMichael Baum void *umem_buf = NULL; 21238f53763SMichael Baum size_t alignment = MLX5_WQE_BUF_ALIGNMENT; 21338f53763SMichael Baum uint32_t umem_size, umem_dbrec; 21438f53763SMichael Baum uint16_t sq_size = 1 << log_wqbb_n; 21538f53763SMichael Baum int ret; 21638f53763SMichael Baum 21738f53763SMichael Baum if (alignment == (size_t)-1) { 21838f53763SMichael Baum DRV_LOG(ERR, "Failed to get WQE buf alignment."); 21938f53763SMichael Baum rte_errno = ENOMEM; 22038f53763SMichael Baum return -rte_errno; 22138f53763SMichael Baum } 22238f53763SMichael Baum /* Allocate memory buffer for WQEs and doorbell record. */ 22338f53763SMichael Baum umem_size = MLX5_WQE_SIZE * sq_size; 22438f53763SMichael Baum umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE); 22538f53763SMichael Baum umem_size += MLX5_DBR_SIZE; 22638f53763SMichael Baum umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size, 22738f53763SMichael Baum alignment, socket); 22838f53763SMichael Baum if (!umem_buf) { 22938f53763SMichael Baum DRV_LOG(ERR, "Failed to allocate memory for SQ."); 23038f53763SMichael Baum rte_errno = ENOMEM; 23138f53763SMichael Baum return -rte_errno; 23238f53763SMichael Baum } 23338f53763SMichael Baum /* Register allocated buffer in user space with DevX. */ 23438f53763SMichael Baum umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf, umem_size, 23538f53763SMichael Baum IBV_ACCESS_LOCAL_WRITE); 23638f53763SMichael Baum if (!umem_obj) { 23738f53763SMichael Baum DRV_LOG(ERR, "Failed to register umem for SQ."); 23838f53763SMichael Baum rte_errno = errno; 23938f53763SMichael Baum goto error; 24038f53763SMichael Baum } 24138f53763SMichael Baum /* Fill attributes for SQ object creation. */ 24238f53763SMichael Baum attr->wq_attr.wq_type = MLX5_WQ_TYPE_CYCLIC; 24338f53763SMichael Baum attr->wq_attr.wq_umem_valid = 1; 24438f53763SMichael Baum attr->wq_attr.wq_umem_id = mlx5_os_get_umem_id(umem_obj); 24538f53763SMichael Baum attr->wq_attr.wq_umem_offset = 0; 24638f53763SMichael Baum attr->wq_attr.dbr_umem_valid = 1; 24738f53763SMichael Baum attr->wq_attr.dbr_umem_id = attr->wq_attr.wq_umem_id; 24838f53763SMichael Baum attr->wq_attr.dbr_addr = umem_dbrec; 24938f53763SMichael Baum attr->wq_attr.log_wq_stride = rte_log2_u32(MLX5_WQE_SIZE); 25038f53763SMichael Baum attr->wq_attr.log_wq_sz = log_wqbb_n; 25138f53763SMichael Baum attr->wq_attr.log_wq_pg_sz = MLX5_LOG_PAGE_SIZE; 25238f53763SMichael Baum /* Create send queue object with DevX. */ 25338f53763SMichael Baum sq = mlx5_devx_cmd_create_sq(ctx, attr); 25438f53763SMichael Baum if (!sq) { 25538f53763SMichael Baum DRV_LOG(ERR, "Can't create DevX SQ object."); 25638f53763SMichael Baum rte_errno = ENOMEM; 25738f53763SMichael Baum goto error; 25838f53763SMichael Baum } 25938f53763SMichael Baum sq_obj->umem_buf = umem_buf; 26038f53763SMichael Baum sq_obj->umem_obj = umem_obj; 26138f53763SMichael Baum sq_obj->sq = sq; 26238f53763SMichael Baum sq_obj->db_rec = RTE_PTR_ADD(sq_obj->umem_buf, umem_dbrec); 26338f53763SMichael Baum return 0; 26438f53763SMichael Baum error: 26538f53763SMichael Baum ret = rte_errno; 26638f53763SMichael Baum if (umem_obj) 26738f53763SMichael Baum claim_zero(mlx5_os_umem_dereg(umem_obj)); 26838f53763SMichael Baum if (umem_buf) 26938f53763SMichael Baum mlx5_free((void *)(uintptr_t)umem_buf); 27038f53763SMichael Baum rte_errno = ret; 27138f53763SMichael Baum return -rte_errno; 27238f53763SMichael Baum } 27338f53763SMichael Baum 274*edb704daSMichael Baum /** 275*edb704daSMichael Baum * Destroy DevX Receive Queue. 276*edb704daSMichael Baum * 277*edb704daSMichael Baum * @param[in] rq 278*edb704daSMichael Baum * DevX RQ to destroy. 279*edb704daSMichael Baum */ 280*edb704daSMichael Baum void 281*edb704daSMichael Baum mlx5_devx_rq_destroy(struct mlx5_devx_rq *rq) 282*edb704daSMichael Baum { 283*edb704daSMichael Baum if (rq->rq) 284*edb704daSMichael Baum claim_zero(mlx5_devx_cmd_destroy(rq->rq)); 285*edb704daSMichael Baum if (rq->umem_obj) 286*edb704daSMichael Baum claim_zero(mlx5_os_umem_dereg(rq->umem_obj)); 287*edb704daSMichael Baum if (rq->umem_buf) 288*edb704daSMichael Baum mlx5_free((void *)(uintptr_t)rq->umem_buf); 289*edb704daSMichael Baum } 290*edb704daSMichael Baum 291*edb704daSMichael Baum /** 292*edb704daSMichael Baum * Create Receive Queue using DevX API. 293*edb704daSMichael Baum * 294*edb704daSMichael Baum * Get a pointer to partially initialized attributes structure, and updates the 295*edb704daSMichael Baum * following fields: 296*edb704daSMichael Baum * wq_umem_valid 297*edb704daSMichael Baum * wq_umem_id 298*edb704daSMichael Baum * wq_umem_offset 299*edb704daSMichael Baum * dbr_umem_valid 300*edb704daSMichael Baum * dbr_umem_id 301*edb704daSMichael Baum * dbr_addr 302*edb704daSMichael Baum * log_wq_pg_sz 303*edb704daSMichael Baum * All other fields are updated by caller. 304*edb704daSMichael Baum * 305*edb704daSMichael Baum * @param[in] ctx 306*edb704daSMichael Baum * Context returned from mlx5 open_device() glue function. 307*edb704daSMichael Baum * @param[in/out] rq_obj 308*edb704daSMichael Baum * Pointer to RQ to create. 309*edb704daSMichael Baum * @param[in] wqe_size 310*edb704daSMichael Baum * Size of WQE structure. 311*edb704daSMichael Baum * @param[in] log_wqbb_n 312*edb704daSMichael Baum * Log of number of WQBBs in queue. 313*edb704daSMichael Baum * @param[in] attr 314*edb704daSMichael Baum * Pointer to RQ attributes structure. 315*edb704daSMichael Baum * @param[in] socket 316*edb704daSMichael Baum * Socket to use for allocation. 317*edb704daSMichael Baum * 318*edb704daSMichael Baum * @return 319*edb704daSMichael Baum * 0 on success, a negative errno value otherwise and rte_errno is set. 320*edb704daSMichael Baum */ 321*edb704daSMichael Baum int 322*edb704daSMichael Baum mlx5_devx_rq_create(void *ctx, struct mlx5_devx_rq *rq_obj, uint32_t wqe_size, 323*edb704daSMichael Baum uint16_t log_wqbb_n, 324*edb704daSMichael Baum struct mlx5_devx_create_rq_attr *attr, int socket) 325*edb704daSMichael Baum { 326*edb704daSMichael Baum struct mlx5_devx_obj *rq = NULL; 327*edb704daSMichael Baum struct mlx5dv_devx_umem *umem_obj = NULL; 328*edb704daSMichael Baum void *umem_buf = NULL; 329*edb704daSMichael Baum size_t alignment = MLX5_WQE_BUF_ALIGNMENT; 330*edb704daSMichael Baum uint32_t umem_size, umem_dbrec; 331*edb704daSMichael Baum uint16_t rq_size = 1 << log_wqbb_n; 332*edb704daSMichael Baum int ret; 333*edb704daSMichael Baum 334*edb704daSMichael Baum if (alignment == (size_t)-1) { 335*edb704daSMichael Baum DRV_LOG(ERR, "Failed to get WQE buf alignment."); 336*edb704daSMichael Baum rte_errno = ENOMEM; 337*edb704daSMichael Baum return -rte_errno; 338*edb704daSMichael Baum } 339*edb704daSMichael Baum /* Allocate memory buffer for WQEs and doorbell record. */ 340*edb704daSMichael Baum umem_size = wqe_size * rq_size; 341*edb704daSMichael Baum umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE); 342*edb704daSMichael Baum umem_size += MLX5_DBR_SIZE; 343*edb704daSMichael Baum umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size, 344*edb704daSMichael Baum alignment, socket); 345*edb704daSMichael Baum if (!umem_buf) { 346*edb704daSMichael Baum DRV_LOG(ERR, "Failed to allocate memory for RQ."); 347*edb704daSMichael Baum rte_errno = ENOMEM; 348*edb704daSMichael Baum return -rte_errno; 349*edb704daSMichael Baum } 350*edb704daSMichael Baum /* Register allocated buffer in user space with DevX. */ 351*edb704daSMichael Baum umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf, 352*edb704daSMichael Baum umem_size, 0); 353*edb704daSMichael Baum if (!umem_obj) { 354*edb704daSMichael Baum DRV_LOG(ERR, "Failed to register umem for RQ."); 355*edb704daSMichael Baum rte_errno = errno; 356*edb704daSMichael Baum goto error; 357*edb704daSMichael Baum } 358*edb704daSMichael Baum /* Fill attributes for RQ object creation. */ 359*edb704daSMichael Baum attr->wq_attr.wq_umem_valid = 1; 360*edb704daSMichael Baum attr->wq_attr.wq_umem_id = mlx5_os_get_umem_id(umem_obj); 361*edb704daSMichael Baum attr->wq_attr.wq_umem_offset = 0; 362*edb704daSMichael Baum attr->wq_attr.dbr_umem_valid = 1; 363*edb704daSMichael Baum attr->wq_attr.dbr_umem_id = attr->wq_attr.wq_umem_id; 364*edb704daSMichael Baum attr->wq_attr.dbr_addr = umem_dbrec; 365*edb704daSMichael Baum attr->wq_attr.log_wq_pg_sz = MLX5_LOG_PAGE_SIZE; 366*edb704daSMichael Baum /* Create receive queue object with DevX. */ 367*edb704daSMichael Baum rq = mlx5_devx_cmd_create_rq(ctx, attr, socket); 368*edb704daSMichael Baum if (!rq) { 369*edb704daSMichael Baum DRV_LOG(ERR, "Can't create DevX RQ object."); 370*edb704daSMichael Baum rte_errno = ENOMEM; 371*edb704daSMichael Baum goto error; 372*edb704daSMichael Baum } 373*edb704daSMichael Baum rq_obj->umem_buf = umem_buf; 374*edb704daSMichael Baum rq_obj->umem_obj = umem_obj; 375*edb704daSMichael Baum rq_obj->rq = rq; 376*edb704daSMichael Baum rq_obj->db_rec = RTE_PTR_ADD(rq_obj->umem_buf, umem_dbrec); 377*edb704daSMichael Baum return 0; 378*edb704daSMichael Baum error: 379*edb704daSMichael Baum ret = rte_errno; 380*edb704daSMichael Baum if (umem_obj) 381*edb704daSMichael Baum claim_zero(mlx5_os_umem_dereg(umem_obj)); 382*edb704daSMichael Baum if (umem_buf) 383*edb704daSMichael Baum mlx5_free((void *)(uintptr_t)umem_buf); 384*edb704daSMichael Baum rte_errno = ret; 385*edb704daSMichael Baum return -rte_errno; 386*edb704daSMichael Baum } 38738f53763SMichael Baum 388