Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2020 Mellanox Technologies, Ltd
3 : : */
4 : : #include <stdint.h>
5 : :
6 : : #include <eal_export.h>
7 : : #include <rte_errno.h>
8 : : #include <rte_common.h>
9 : : #include <rte_eal_paging.h>
10 : :
11 : : #include <mlx5_glue.h>
12 : : #include <mlx5_common_os.h>
13 : :
14 : : #include "mlx5_prm.h"
15 : : #include "mlx5_devx_cmds.h"
16 : : #include "mlx5_common_log.h"
17 : : #include "mlx5_malloc.h"
18 : : #include "mlx5_common.h"
19 : : #include "mlx5_common_devx.h"
20 : :
21 : : /**
22 : : * Destroy DevX Completion Queue.
23 : : *
24 : : * @param[in] cq
25 : : * DevX CQ to destroy.
26 : : */
27 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_cq_destroy)
28 : : void
29 : 0 : mlx5_devx_cq_destroy(struct mlx5_devx_cq *cq)
30 : : {
31 [ # # ]: 0 : if (cq->cq)
32 : 0 : claim_zero(mlx5_devx_cmd_destroy(cq->cq));
33 [ # # ]: 0 : if (cq->umem_obj)
34 : : claim_zero(mlx5_os_umem_dereg(cq->umem_obj));
35 [ # # ]: 0 : if (cq->umem_buf)
36 : 0 : mlx5_free((void *)(uintptr_t)cq->umem_buf);
37 : 0 : }
38 : :
39 : : /* Mark all CQEs initially as invalid. */
40 : : static void
41 : : mlx5_cq_init(struct mlx5_devx_cq *cq_obj, uint16_t cq_size)
42 : : {
43 : : volatile struct mlx5_cqe *cqe = cq_obj->cqes;
44 : : uint16_t i;
45 : :
46 [ # # ]: 0 : for (i = 0; i < cq_size; i++, cqe++) {
47 : 0 : cqe->op_own = (MLX5_CQE_INVALID << 4) | MLX5_CQE_OWNER_MASK;
48 : 0 : cqe->validity_iteration_count = MLX5_CQE_VIC_INIT;
49 : : }
50 : : }
51 : :
52 : : /**
53 : : * Create Completion Queue using DevX API.
54 : : *
55 : : * Get a pointer to partially initialized attributes structure, and updates the
56 : : * following fields:
57 : : * q_umem_valid
58 : : * q_umem_id
59 : : * q_umem_offset
60 : : * db_umem_valid
61 : : * db_umem_id
62 : : * db_umem_offset
63 : : * eqn
64 : : * log_cq_size
65 : : * log_page_size
66 : : * All other fields are updated by caller.
67 : : *
68 : : * @param[in] ctx
69 : : * Context returned from mlx5 open_device() glue function.
70 : : * @param[in/out] cq_obj
71 : : * Pointer to CQ to create.
72 : : * @param[in] log_desc_n
73 : : * Log of number of descriptors in queue.
74 : : * @param[in] attr
75 : : * Pointer to CQ attributes structure.
76 : : * @param[in] socket
77 : : * Socket to use for allocation.
78 : : *
79 : : * @return
80 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
81 : : */
82 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_cq_create)
83 : : int
84 : 0 : mlx5_devx_cq_create(void *ctx, struct mlx5_devx_cq *cq_obj, uint16_t log_desc_n,
85 : : struct mlx5_devx_cq_attr *attr, int socket)
86 : : {
87 : : struct mlx5_devx_obj *cq = NULL;
88 : : struct mlx5dv_devx_umem *umem_obj = NULL;
89 : : void *umem_buf = NULL;
90 : 0 : size_t page_size = rte_mem_page_size();
91 : 0 : size_t alignment = MLX5_CQE_BUF_ALIGNMENT;
92 : : uint32_t umem_size, umem_dbrec;
93 : : uint32_t eqn;
94 : 0 : uint32_t num_of_cqes = RTE_BIT32(log_desc_n);
95 : : int ret;
96 : :
97 [ # # ]: 0 : if (page_size == (size_t)-1 || alignment == (size_t)-1) {
98 : 0 : DRV_LOG(ERR, "Failed to get page_size.");
99 : 0 : rte_errno = ENOMEM;
100 : 0 : return -rte_errno;
101 : : }
102 : : /* Query first EQN. */
103 : 0 : ret = mlx5_glue->devx_query_eqn(ctx, 0, &eqn);
104 [ # # ]: 0 : if (ret) {
105 : 0 : rte_errno = errno;
106 : 0 : DRV_LOG(ERR, "Failed to query event queue number.");
107 : 0 : return -rte_errno;
108 : : }
109 : : /* Allocate memory buffer for CQEs and doorbell record. */
110 : 0 : umem_size = sizeof(struct mlx5_cqe) * num_of_cqes;
111 : 0 : umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE);
112 : 0 : umem_size += MLX5_DBR_SIZE;
113 : 0 : umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size,
114 : : alignment, socket);
115 [ # # ]: 0 : if (!umem_buf) {
116 : 0 : DRV_LOG(ERR, "Failed to allocate memory for CQ.");
117 : 0 : rte_errno = ENOMEM;
118 : 0 : return -rte_errno;
119 : : }
120 : : /* Register allocated buffer in user space with DevX. */
121 : : umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf, umem_size,
122 : : IBV_ACCESS_LOCAL_WRITE);
123 [ # # ]: 0 : if (!umem_obj) {
124 : 0 : DRV_LOG(ERR, "Failed to register umem for CQ.");
125 : 0 : rte_errno = errno;
126 : 0 : goto error;
127 : : }
128 : : /* Fill attributes for CQ object creation. */
129 [ # # ]: 0 : attr->q_umem_valid = 1;
130 : 0 : attr->q_umem_id = mlx5_os_get_umem_id(umem_obj);
131 : 0 : attr->q_umem_offset = 0;
132 : 0 : attr->db_umem_valid = 1;
133 : 0 : attr->db_umem_id = attr->q_umem_id;
134 : 0 : attr->db_umem_offset = umem_dbrec;
135 : 0 : attr->eqn = eqn;
136 : 0 : attr->log_cq_size = log_desc_n;
137 [ # # ]: 0 : attr->log_page_size = rte_log2_u32(page_size);
138 : : /* Create completion queue object with DevX. */
139 : 0 : cq = mlx5_devx_cmd_create_cq(ctx, attr);
140 [ # # ]: 0 : if (!cq) {
141 : 0 : DRV_LOG(ERR, "Can't create DevX CQ object.");
142 : 0 : rte_errno = ENOMEM;
143 : 0 : goto error;
144 : : }
145 : 0 : cq_obj->umem_buf = umem_buf;
146 : 0 : cq_obj->umem_obj = umem_obj;
147 : 0 : cq_obj->cq = cq;
148 : 0 : cq_obj->db_rec = RTE_PTR_ADD(cq_obj->umem_buf, umem_dbrec);
149 : : /* Mark all CQEs initially as invalid. */
150 : 0 : mlx5_cq_init(cq_obj, num_of_cqes);
151 : : return 0;
152 : 0 : error:
153 : 0 : ret = rte_errno;
154 [ # # ]: 0 : if (umem_obj)
155 : : claim_zero(mlx5_os_umem_dereg(umem_obj));
156 : : if (umem_buf)
157 : 0 : mlx5_free((void *)(uintptr_t)umem_buf);
158 : 0 : rte_errno = ret;
159 : 0 : return -rte_errno;
160 : : }
161 : :
162 : : /**
163 : : * Destroy DevX Send Queue.
164 : : *
165 : : * @param[in] sq
166 : : * DevX SQ to destroy.
167 : : */
168 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_sq_destroy)
169 : : void
170 : 0 : mlx5_devx_sq_destroy(struct mlx5_devx_sq *sq)
171 : : {
172 [ # # ]: 0 : if (sq->sq)
173 : 0 : claim_zero(mlx5_devx_cmd_destroy(sq->sq));
174 [ # # ]: 0 : if (sq->umem_obj)
175 : : claim_zero(mlx5_os_umem_dereg(sq->umem_obj));
176 [ # # ]: 0 : if (sq->umem_buf)
177 : 0 : mlx5_free((void *)(uintptr_t)sq->umem_buf);
178 : 0 : }
179 : :
180 : : /**
181 : : * Create Send Queue using DevX API.
182 : : *
183 : : * Get a pointer to partially initialized attributes structure, and updates the
184 : : * following fields:
185 : : * wq_type
186 : : * wq_umem_valid
187 : : * wq_umem_id
188 : : * wq_umem_offset
189 : : * dbr_umem_valid
190 : : * dbr_umem_id
191 : : * dbr_addr
192 : : * log_wq_stride
193 : : * log_wq_sz
194 : : * log_wq_pg_sz
195 : : * All other fields are updated by caller.
196 : : *
197 : : * @param[in] ctx
198 : : * Context returned from mlx5 open_device() glue function.
199 : : * @param[in/out] sq_obj
200 : : * Pointer to SQ to create.
201 : : * @param[in] log_wqbb_n
202 : : * Log of number of WQBBs in queue.
203 : : * @param[in] attr
204 : : * Pointer to SQ attributes structure.
205 : : * @param[in] socket
206 : : * Socket to use for allocation.
207 : : *
208 : : * @return
209 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
210 : : */
211 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_sq_create)
212 : : int
213 : 0 : mlx5_devx_sq_create(void *ctx, struct mlx5_devx_sq *sq_obj, uint16_t log_wqbb_n,
214 : : struct mlx5_devx_create_sq_attr *attr, int socket)
215 : : {
216 : : struct mlx5_devx_obj *sq = NULL;
217 : : struct mlx5dv_devx_umem *umem_obj = NULL;
218 : : void *umem_buf = NULL;
219 : 0 : size_t alignment = MLX5_WQE_BUF_ALIGNMENT;
220 : : uint32_t umem_size, umem_dbrec;
221 : 0 : uint32_t num_of_wqbbs = RTE_BIT32(log_wqbb_n);
222 : : int ret;
223 : :
224 [ # # ]: 0 : if (alignment == (size_t)-1) {
225 : 0 : DRV_LOG(ERR, "Failed to get WQE buf alignment.");
226 : 0 : rte_errno = ENOMEM;
227 : 0 : return -rte_errno;
228 : : }
229 : : /* Allocate memory buffer for WQEs and doorbell record. */
230 : 0 : umem_size = MLX5_WQE_SIZE * num_of_wqbbs;
231 : 0 : umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE);
232 : 0 : umem_size += MLX5_DBR_SIZE;
233 : 0 : umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size,
234 : : alignment, socket);
235 [ # # ]: 0 : if (!umem_buf) {
236 : 0 : DRV_LOG(ERR, "Failed to allocate memory for SQ.");
237 : 0 : rte_errno = ENOMEM;
238 : 0 : return -rte_errno;
239 : : }
240 : : /* Register allocated buffer in user space with DevX. */
241 : : umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf, umem_size,
242 : : IBV_ACCESS_LOCAL_WRITE);
243 [ # # ]: 0 : if (!umem_obj) {
244 : 0 : DRV_LOG(ERR, "Failed to register umem for SQ.");
245 : 0 : rte_errno = errno;
246 : 0 : goto error;
247 : : }
248 : : /* Fill attributes for SQ object creation. */
249 : 0 : attr->wq_attr.wq_type = MLX5_WQ_TYPE_CYCLIC;
250 : 0 : attr->wq_attr.wq_umem_valid = 1;
251 : 0 : attr->wq_attr.wq_umem_id = mlx5_os_get_umem_id(umem_obj);
252 : 0 : attr->wq_attr.wq_umem_offset = 0;
253 : 0 : attr->wq_attr.dbr_umem_valid = 1;
254 : 0 : attr->wq_attr.dbr_umem_id = attr->wq_attr.wq_umem_id;
255 : 0 : attr->wq_attr.dbr_addr = umem_dbrec;
256 : 0 : attr->wq_attr.log_wq_stride = rte_log2_u32(MLX5_WQE_SIZE);
257 : 0 : attr->wq_attr.log_wq_sz = log_wqbb_n;
258 : 0 : attr->wq_attr.log_wq_pg_sz = MLX5_LOG_PAGE_SIZE;
259 : : /* Create send queue object with DevX. */
260 : 0 : sq = mlx5_devx_cmd_create_sq(ctx, attr);
261 [ # # ]: 0 : if (!sq) {
262 : 0 : DRV_LOG(ERR, "Can't create DevX SQ object.");
263 : 0 : rte_errno = ENOMEM;
264 : 0 : goto error;
265 : : }
266 : 0 : sq_obj->umem_buf = umem_buf;
267 : 0 : sq_obj->umem_obj = umem_obj;
268 : 0 : sq_obj->sq = sq;
269 : 0 : sq_obj->db_rec = RTE_PTR_ADD(sq_obj->umem_buf, umem_dbrec);
270 : 0 : return 0;
271 : 0 : error:
272 : 0 : ret = rte_errno;
273 [ # # ]: 0 : if (umem_obj)
274 : : claim_zero(mlx5_os_umem_dereg(umem_obj));
275 : : if (umem_buf)
276 : 0 : mlx5_free((void *)(uintptr_t)umem_buf);
277 : 0 : rte_errno = ret;
278 : 0 : return -rte_errno;
279 : : }
280 : :
281 : : /**
282 : : * Destroy DevX Receive Queue resources.
283 : : *
284 : : * @param[in] rq_res
285 : : * DevX RQ resource to destroy.
286 : : */
287 : : static void
288 : 0 : mlx5_devx_wq_res_destroy(struct mlx5_devx_wq_res *rq_res)
289 : : {
290 [ # # ]: 0 : if (rq_res->umem_obj)
291 : : claim_zero(mlx5_os_umem_dereg(rq_res->umem_obj));
292 [ # # ]: 0 : if (rq_res->umem_buf)
293 : 0 : mlx5_free((void *)(uintptr_t)rq_res->umem_buf);
294 : : memset(rq_res, 0, sizeof(*rq_res));
295 : 0 : }
296 : :
297 : : /**
298 : : * Destroy DevX Receive Memory Pool.
299 : : *
300 : : * @param[in] rmp
301 : : * DevX RMP to destroy.
302 : : */
303 : : static void
304 : 0 : mlx5_devx_rmp_destroy(struct mlx5_devx_rmp *rmp)
305 : : {
306 : : MLX5_ASSERT(rmp->ref_cnt == 0);
307 [ # # ]: 0 : if (rmp->rmp) {
308 : 0 : claim_zero(mlx5_devx_cmd_destroy(rmp->rmp));
309 : 0 : rmp->rmp = NULL;
310 : : }
311 : 0 : mlx5_devx_wq_res_destroy(&rmp->wq);
312 : 0 : }
313 : :
314 : : /**
315 : : * Destroy DevX Queue Pair.
316 : : *
317 : : * @param[in] qp
318 : : * DevX QP to destroy.
319 : : */
320 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_qp_destroy)
321 : : void
322 : 0 : mlx5_devx_qp_destroy(struct mlx5_devx_qp *qp)
323 : : {
324 [ # # ]: 0 : if (qp->qp)
325 : 0 : claim_zero(mlx5_devx_cmd_destroy(qp->qp));
326 [ # # ]: 0 : if (qp->umem_obj)
327 : : claim_zero(mlx5_os_umem_dereg(qp->umem_obj));
328 [ # # ]: 0 : if (qp->umem_buf)
329 : 0 : mlx5_free((void *)(uintptr_t)qp->umem_buf);
330 : 0 : }
331 : :
332 : : /**
333 : : * Create Queue Pair using DevX API.
334 : : *
335 : : * Get a pointer to partially initialized attributes structure, and updates the
336 : : * following fields:
337 : : * wq_umem_id
338 : : * wq_umem_offset
339 : : * dbr_umem_valid
340 : : * dbr_umem_id
341 : : * dbr_address
342 : : * log_page_size
343 : : * All other fields are updated by caller.
344 : : *
345 : : * @param[in] ctx
346 : : * Context returned from mlx5 open_device() glue function.
347 : : * @param[in/out] qp_obj
348 : : * Pointer to QP to create.
349 : : * @param[in] queue_size
350 : : * Size of queue to create.
351 : : * @param[in] attr
352 : : * Pointer to QP attributes structure.
353 : : * @param[in] socket
354 : : * Socket to use for allocation.
355 : : *
356 : : * @return
357 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
358 : : */
359 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_qp_create)
360 : : int
361 : 0 : mlx5_devx_qp_create(void *ctx, struct mlx5_devx_qp *qp_obj, uint32_t queue_size,
362 : : struct mlx5_devx_qp_attr *attr, int socket)
363 : : {
364 : : struct mlx5_devx_obj *qp = NULL;
365 : : struct mlx5dv_devx_umem *umem_obj = NULL;
366 : : void *umem_buf = NULL;
367 : 0 : size_t alignment = MLX5_WQE_BUF_ALIGNMENT;
368 : : uint32_t umem_size, umem_dbrec;
369 : : int ret;
370 : :
371 [ # # ]: 0 : if (alignment == (size_t)-1) {
372 : 0 : DRV_LOG(ERR, "Failed to get WQE buf alignment.");
373 : 0 : rte_errno = ENOMEM;
374 : 0 : return -rte_errno;
375 : : }
376 : : /* Allocate memory buffer for WQEs and doorbell record. */
377 : : umem_size = queue_size;
378 : 0 : umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE);
379 : 0 : umem_size += MLX5_DBR_SIZE;
380 : 0 : umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size,
381 : : alignment, socket);
382 [ # # ]: 0 : if (!umem_buf) {
383 : 0 : DRV_LOG(ERR, "Failed to allocate memory for QP.");
384 : 0 : rte_errno = ENOMEM;
385 : 0 : return -rte_errno;
386 : : }
387 : : /* Register allocated buffer in user space with DevX. */
388 : : umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf, umem_size,
389 : : IBV_ACCESS_LOCAL_WRITE);
390 [ # # ]: 0 : if (!umem_obj) {
391 : 0 : DRV_LOG(ERR, "Failed to register umem for QP.");
392 : 0 : rte_errno = errno;
393 : 0 : goto error;
394 : : }
395 : : /* Fill attributes for SQ object creation. */
396 : 0 : attr->wq_umem_id = mlx5_os_get_umem_id(umem_obj);
397 : 0 : attr->wq_umem_offset = 0;
398 : 0 : attr->dbr_umem_valid = 1;
399 : 0 : attr->dbr_umem_id = attr->wq_umem_id;
400 : 0 : attr->dbr_address = umem_dbrec;
401 : 0 : attr->log_page_size = MLX5_LOG_PAGE_SIZE;
402 : : /* Create send queue object with DevX. */
403 : 0 : qp = mlx5_devx_cmd_create_qp(ctx, attr);
404 [ # # ]: 0 : if (!qp) {
405 : 0 : DRV_LOG(ERR, "Can't create DevX QP object.");
406 : 0 : rte_errno = ENOMEM;
407 : 0 : goto error;
408 : : }
409 : 0 : qp_obj->umem_buf = umem_buf;
410 : 0 : qp_obj->umem_obj = umem_obj;
411 : 0 : qp_obj->qp = qp;
412 : 0 : qp_obj->db_rec = RTE_PTR_ADD(qp_obj->umem_buf, umem_dbrec);
413 : 0 : return 0;
414 : 0 : error:
415 : 0 : ret = rte_errno;
416 [ # # ]: 0 : if (umem_obj)
417 : : claim_zero(mlx5_os_umem_dereg(umem_obj));
418 : : if (umem_buf)
419 : 0 : mlx5_free((void *)(uintptr_t)umem_buf);
420 : 0 : rte_errno = ret;
421 : 0 : return -rte_errno;
422 : : }
423 : :
424 : : /**
425 : : * Destroy DevX Receive Queue.
426 : : *
427 : : * @param[in] rq
428 : : * DevX RQ to destroy.
429 : : */
430 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_rq_destroy)
431 : : void
432 : 0 : mlx5_devx_rq_destroy(struct mlx5_devx_rq *rq)
433 : : {
434 [ # # ]: 0 : if (rq->rq) {
435 : 0 : claim_zero(mlx5_devx_cmd_destroy(rq->rq));
436 : 0 : rq->rq = NULL;
437 [ # # ]: 0 : if (rq->rmp)
438 : 0 : rq->rmp->ref_cnt--;
439 : : }
440 [ # # ]: 0 : if (rq->rmp == NULL) {
441 : 0 : mlx5_devx_wq_res_destroy(&rq->wq);
442 : : } else {
443 [ # # ]: 0 : if (rq->rmp->ref_cnt == 0)
444 : 0 : mlx5_devx_rmp_destroy(rq->rmp);
445 : : }
446 : 0 : }
447 : :
448 : : /**
449 : : * Create WQ resources using DevX API.
450 : : *
451 : : * @param[in] ctx
452 : : * Context returned from mlx5 open_device() glue function.
453 : : * @param[in] wqe_size
454 : : * Size of WQE structure.
455 : : * @param[in] log_wqbb_n
456 : : * Log of number of WQBBs in queue.
457 : : * @param[in] socket
458 : : * Socket to use for allocation.
459 : : * @param[out] wq_attr
460 : : * Pointer to WQ attributes structure.
461 : : * @param[out] wq_res
462 : : * Pointer to WQ resource to create.
463 : : *
464 : : * @return
465 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
466 : : */
467 : : static int
468 : 0 : mlx5_devx_wq_init(void *ctx, uint32_t wqe_size, uint16_t log_wqbb_n, int socket,
469 : : struct mlx5_devx_wq_attr *wq_attr,
470 : : struct mlx5_devx_wq_res *wq_res)
471 : : {
472 : : struct mlx5dv_devx_umem *umem_obj = NULL;
473 : : void *umem_buf = NULL;
474 : 0 : size_t alignment = MLX5_WQE_BUF_ALIGNMENT;
475 : : uint32_t umem_size, umem_dbrec;
476 : : int ret;
477 : :
478 [ # # ]: 0 : if (alignment == (size_t)-1) {
479 : 0 : DRV_LOG(ERR, "Failed to get WQE buf alignment.");
480 : 0 : rte_errno = ENOMEM;
481 : 0 : return -rte_errno;
482 : : }
483 : : /* Allocate memory buffer for WQEs and doorbell record. */
484 : 0 : umem_size = wqe_size * (1 << log_wqbb_n);
485 : 0 : umem_dbrec = RTE_ALIGN(umem_size, MLX5_DBR_SIZE);
486 : 0 : umem_size += MLX5_DBR_SIZE;
487 : 0 : umem_buf = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, umem_size,
488 : : alignment, socket);
489 [ # # ]: 0 : if (!umem_buf) {
490 : 0 : DRV_LOG(ERR, "Failed to allocate memory for RQ.");
491 : 0 : rte_errno = ENOMEM;
492 : 0 : return -rte_errno;
493 : : }
494 : : /* Register allocated buffer in user space with DevX. */
495 : : umem_obj = mlx5_os_umem_reg(ctx, (void *)(uintptr_t)umem_buf,
496 : : umem_size, 0);
497 [ # # ]: 0 : if (!umem_obj) {
498 : 0 : DRV_LOG(ERR, "Failed to register umem for RQ.");
499 : 0 : rte_errno = errno;
500 : 0 : goto error;
501 : : }
502 : : /* Fill WQ attributes for RQ/RMP object creation. */
503 : 0 : wq_attr->wq_umem_valid = 1;
504 : 0 : wq_attr->wq_umem_id = mlx5_os_get_umem_id(umem_obj);
505 : 0 : wq_attr->wq_umem_offset = 0;
506 : 0 : wq_attr->dbr_umem_valid = 1;
507 : 0 : wq_attr->dbr_umem_id = wq_attr->wq_umem_id;
508 : 0 : wq_attr->dbr_addr = umem_dbrec;
509 : 0 : wq_attr->log_wq_pg_sz = MLX5_LOG_PAGE_SIZE;
510 : : /* Fill attributes for RQ object creation. */
511 : 0 : wq_res->umem_buf = umem_buf;
512 : 0 : wq_res->umem_obj = umem_obj;
513 : 0 : wq_res->db_rec = RTE_PTR_ADD(umem_buf, umem_dbrec);
514 : 0 : return 0;
515 : : error:
516 : : ret = rte_errno;
517 : : if (umem_obj)
518 : : claim_zero(mlx5_os_umem_dereg(umem_obj));
519 : : if (umem_buf)
520 : 0 : mlx5_free((void *)(uintptr_t)umem_buf);
521 : 0 : rte_errno = ret;
522 : 0 : return -rte_errno;
523 : : }
524 : :
525 : : /**
526 : : * Create standalone Receive Queue using DevX API.
527 : : *
528 : : * @param[in] ctx
529 : : * Context returned from mlx5 open_device() glue function.
530 : : * @param[in/out] rq_obj
531 : : * Pointer to RQ to create.
532 : : * @param[in] wqe_size
533 : : * Size of WQE structure.
534 : : * @param[in] log_wqbb_n
535 : : * Log of number of WQBBs in queue.
536 : : * @param[in] attr
537 : : * Pointer to RQ attributes structure.
538 : : * @param[in] socket
539 : : * Socket to use for allocation.
540 : : *
541 : : * @return
542 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
543 : : */
544 : : static int
545 : 0 : mlx5_devx_rq_std_create(void *ctx, struct mlx5_devx_rq *rq_obj,
546 : : uint32_t wqe_size, uint16_t log_wqbb_n,
547 : : struct mlx5_devx_create_rq_attr *attr, int socket)
548 : : {
549 : : struct mlx5_devx_obj *rq;
550 : : int ret;
551 : :
552 : 0 : ret = mlx5_devx_wq_init(ctx, wqe_size, log_wqbb_n, socket,
553 : : &attr->wq_attr, &rq_obj->wq);
554 [ # # ]: 0 : if (ret != 0)
555 : : return ret;
556 : : /* Create receive queue object with DevX. */
557 : 0 : rq = mlx5_devx_cmd_create_rq(ctx, attr, socket);
558 [ # # ]: 0 : if (!rq) {
559 : 0 : DRV_LOG(ERR, "Can't create DevX RQ object.");
560 : 0 : rte_errno = ENOMEM;
561 : 0 : goto error;
562 : : }
563 : 0 : rq_obj->rq = rq;
564 : 0 : return 0;
565 : : error:
566 : : ret = rte_errno;
567 : 0 : mlx5_devx_wq_res_destroy(&rq_obj->wq);
568 : 0 : rte_errno = ret;
569 : 0 : return -rte_errno;
570 : : }
571 : :
572 : : /**
573 : : * Create Receive Memory Pool using DevX API.
574 : : *
575 : : * @param[in] ctx
576 : : * Context returned from mlx5 open_device() glue function.
577 : : * @param[in/out] rq_obj
578 : : * Pointer to RQ to create.
579 : : * @param[in] wqe_size
580 : : * Size of WQE structure.
581 : : * @param[in] log_wqbb_n
582 : : * Log of number of WQBBs in queue.
583 : : * @param[in] attr
584 : : * Pointer to RQ attributes structure.
585 : : * @param[in] socket
586 : : * Socket to use for allocation.
587 : : *
588 : : * @return
589 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
590 : : */
591 : : static int
592 : 0 : mlx5_devx_rmp_create(void *ctx, struct mlx5_devx_rmp *rmp_obj,
593 : : uint32_t wqe_size, uint16_t log_wqbb_n,
594 : : struct mlx5_devx_wq_attr *wq_attr, int socket)
595 : : {
596 : 0 : struct mlx5_devx_create_rmp_attr rmp_attr = { 0 };
597 : : int ret;
598 : :
599 [ # # ]: 0 : if (rmp_obj->rmp != NULL)
600 : : return 0;
601 : 0 : rmp_attr.wq_attr = *wq_attr;
602 : 0 : ret = mlx5_devx_wq_init(ctx, wqe_size, log_wqbb_n, socket,
603 : : &rmp_attr.wq_attr, &rmp_obj->wq);
604 [ # # ]: 0 : if (ret != 0)
605 : : return ret;
606 : 0 : rmp_attr.state = MLX5_RMPC_STATE_RDY;
607 : 0 : rmp_attr.basic_cyclic_rcv_wqe =
608 : 0 : wq_attr->wq_type != MLX5_WQ_TYPE_CYCLIC_STRIDING_RQ;
609 : : /* Create receive memory pool object with DevX. */
610 : 0 : rmp_obj->rmp = mlx5_devx_cmd_create_rmp(ctx, &rmp_attr, socket);
611 [ # # ]: 0 : if (rmp_obj->rmp == NULL) {
612 : 0 : DRV_LOG(ERR, "Can't create DevX RMP object.");
613 : 0 : rte_errno = ENOMEM;
614 : 0 : goto error;
615 : : }
616 : : return 0;
617 : : error:
618 : : ret = rte_errno;
619 : 0 : mlx5_devx_wq_res_destroy(&rmp_obj->wq);
620 : 0 : rte_errno = ret;
621 : 0 : return -rte_errno;
622 : : }
623 : :
624 : : /**
625 : : * Create Shared Receive Queue based on RMP using DevX API.
626 : : *
627 : : * @param[in] ctx
628 : : * Context returned from mlx5 open_device() glue function.
629 : : * @param[in/out] rq_obj
630 : : * Pointer to RQ to create.
631 : : * @param[in] wqe_size
632 : : * Size of WQE structure.
633 : : * @param[in] log_wqbb_n
634 : : * Log of number of WQBBs in queue.
635 : : * @param[in] attr
636 : : * Pointer to RQ attributes structure.
637 : : * @param[in] socket
638 : : * Socket to use for allocation.
639 : : *
640 : : * @return
641 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
642 : : */
643 : : static int
644 : 0 : mlx5_devx_rq_shared_create(void *ctx, struct mlx5_devx_rq *rq_obj,
645 : : uint32_t wqe_size, uint16_t log_wqbb_n,
646 : : struct mlx5_devx_create_rq_attr *attr, int socket)
647 : : {
648 : : struct mlx5_devx_obj *rq;
649 : : int ret;
650 : :
651 : 0 : ret = mlx5_devx_rmp_create(ctx, rq_obj->rmp, wqe_size, log_wqbb_n,
652 : : &attr->wq_attr, socket);
653 [ # # ]: 0 : if (ret != 0)
654 : : return ret;
655 : 0 : attr->mem_rq_type = MLX5_RQC_MEM_RQ_TYPE_MEMORY_RQ_RMP;
656 : 0 : attr->rmpn = rq_obj->rmp->rmp->id;
657 : 0 : attr->flush_in_error_en = 0;
658 : : memset(&attr->wq_attr, 0, sizeof(attr->wq_attr));
659 : : /* Create receive queue object with DevX. */
660 : 0 : rq = mlx5_devx_cmd_create_rq(ctx, attr, socket);
661 [ # # ]: 0 : if (!rq) {
662 : 0 : DRV_LOG(ERR, "Can't create DevX RMP RQ object.");
663 : 0 : rte_errno = ENOMEM;
664 : 0 : goto error;
665 : : }
666 : 0 : rq_obj->rq = rq;
667 : 0 : rq_obj->rmp->ref_cnt++;
668 : 0 : return 0;
669 : : error:
670 : : ret = rte_errno;
671 : 0 : mlx5_devx_rq_destroy(rq_obj);
672 : 0 : rte_errno = ret;
673 : 0 : return -rte_errno;
674 : : }
675 : :
676 : : /**
677 : : * Create Receive Queue using DevX API. Shared RQ is created only if rmp set.
678 : : *
679 : : * Get a pointer to partially initialized attributes structure, and updates the
680 : : * following fields:
681 : : * wq_umem_valid
682 : : * wq_umem_id
683 : : * wq_umem_offset
684 : : * dbr_umem_valid
685 : : * dbr_umem_id
686 : : * dbr_addr
687 : : * log_wq_pg_sz
688 : : * All other fields are updated by caller.
689 : : *
690 : : * @param[in] ctx
691 : : * Context returned from mlx5 open_device() glue function.
692 : : * @param[in/out] rq_obj
693 : : * Pointer to RQ to create.
694 : : * @param[in] wqe_size
695 : : * Size of WQE structure.
696 : : * @param[in] log_wqbb_n
697 : : * Log of number of WQBBs in queue.
698 : : * @param[in] attr
699 : : * Pointer to RQ attributes structure.
700 : : * @param[in] socket
701 : : * Socket to use for allocation.
702 : : *
703 : : * @return
704 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
705 : : */
706 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_rq_create)
707 : : int
708 : 0 : mlx5_devx_rq_create(void *ctx, struct mlx5_devx_rq *rq_obj,
709 : : uint32_t wqe_size, uint16_t log_wqbb_n,
710 : : struct mlx5_devx_create_rq_attr *attr, int socket)
711 : : {
712 [ # # ]: 0 : if (rq_obj->rmp == NULL)
713 : 0 : return mlx5_devx_rq_std_create(ctx, rq_obj, wqe_size,
714 : : log_wqbb_n, attr, socket);
715 : 0 : return mlx5_devx_rq_shared_create(ctx, rq_obj, wqe_size,
716 : : log_wqbb_n, attr, socket);
717 : : }
718 : :
719 : : /**
720 : : * Change QP state to RTS.
721 : : *
722 : : * @param[in] qp
723 : : * DevX QP to change.
724 : : * @param[in] remote_qp_id
725 : : * The remote QP ID for MLX5_CMD_OP_INIT2RTR_QP operation.
726 : : *
727 : : * @return
728 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
729 : : */
730 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_devx_qp2rts)
731 : : int
732 : 0 : mlx5_devx_qp2rts(struct mlx5_devx_qp *qp, uint32_t remote_qp_id)
733 : : {
734 [ # # ]: 0 : if (mlx5_devx_cmd_modify_qp_state(qp->qp, MLX5_CMD_OP_RST2INIT_QP,
735 : : remote_qp_id)) {
736 : 0 : DRV_LOG(ERR, "Failed to modify QP to INIT state(%u).",
737 : : rte_errno);
738 : 0 : return -1;
739 : : }
740 [ # # ]: 0 : if (mlx5_devx_cmd_modify_qp_state(qp->qp, MLX5_CMD_OP_INIT2RTR_QP,
741 : : remote_qp_id)) {
742 : 0 : DRV_LOG(ERR, "Failed to modify QP to RTR state(%u).",
743 : : rte_errno);
744 : 0 : return -1;
745 : : }
746 [ # # ]: 0 : if (mlx5_devx_cmd_modify_qp_state(qp->qp, MLX5_CMD_OP_RTR2RTS_QP,
747 : : remote_qp_id)) {
748 : 0 : DRV_LOG(ERR, "Failed to modify QP to RTS state(%u).",
749 : : rte_errno);
750 : 0 : return -1;
751 : : }
752 : : return 0;
753 : : }
|