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