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