5adb4dc887bf4a1b36efc6cb2a027a7c864da5d1
[dpdk.git] / drivers / net / mlx5 / mlx5_txq.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2015 6WIND S.A.
3  * Copyright 2015 Mellanox Technologies, Ltd
4  */
5
6 #include <stddef.h>
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <stdint.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <inttypes.h>
14
15 /* Verbs header. */
16 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
17 #ifdef PEDANTIC
18 #pragma GCC diagnostic ignored "-Wpedantic"
19 #endif
20 #include <infiniband/verbs.h>
21 #include <infiniband/mlx5dv.h>
22 #ifdef PEDANTIC
23 #pragma GCC diagnostic error "-Wpedantic"
24 #endif
25
26 #include <rte_mbuf.h>
27 #include <rte_malloc.h>
28 #include <rte_ethdev_driver.h>
29 #include <rte_common.h>
30
31 #include "mlx5_utils.h"
32 #include "mlx5_defs.h"
33 #include "mlx5.h"
34 #include "mlx5_rxtx.h"
35 #include "mlx5_autoconf.h"
36 #include "mlx5_glue.h"
37 #include "mlx5_devx_cmds.h"
38
39 /**
40  * Allocate TX queue elements.
41  *
42  * @param txq_ctrl
43  *   Pointer to TX queue structure.
44  */
45 void
46 txq_alloc_elts(struct mlx5_txq_ctrl *txq_ctrl)
47 {
48         const unsigned int elts_n = 1 << txq_ctrl->txq.elts_n;
49         unsigned int i;
50
51         for (i = 0; (i != elts_n); ++i)
52                 txq_ctrl->txq.elts[i] = NULL;
53         DRV_LOG(DEBUG, "port %u Tx queue %u allocated and configured %u WRs",
54                 PORT_ID(txq_ctrl->priv), txq_ctrl->txq.idx, elts_n);
55         txq_ctrl->txq.elts_head = 0;
56         txq_ctrl->txq.elts_tail = 0;
57         txq_ctrl->txq.elts_comp = 0;
58 }
59
60 /**
61  * Free TX queue elements.
62  *
63  * @param txq_ctrl
64  *   Pointer to TX queue structure.
65  */
66 void
67 txq_free_elts(struct mlx5_txq_ctrl *txq_ctrl)
68 {
69         const uint16_t elts_n = 1 << txq_ctrl->txq.elts_n;
70         const uint16_t elts_m = elts_n - 1;
71         uint16_t elts_head = txq_ctrl->txq.elts_head;
72         uint16_t elts_tail = txq_ctrl->txq.elts_tail;
73         struct rte_mbuf *(*elts)[elts_n] = &txq_ctrl->txq.elts;
74
75         DRV_LOG(DEBUG, "port %u Tx queue %u freeing WRs",
76                 PORT_ID(txq_ctrl->priv), txq_ctrl->txq.idx);
77         txq_ctrl->txq.elts_head = 0;
78         txq_ctrl->txq.elts_tail = 0;
79         txq_ctrl->txq.elts_comp = 0;
80
81         while (elts_tail != elts_head) {
82                 struct rte_mbuf *elt = (*elts)[elts_tail & elts_m];
83
84                 assert(elt != NULL);
85                 rte_pktmbuf_free_seg(elt);
86 #ifndef NDEBUG
87                 /* Poisoning. */
88                 memset(&(*elts)[elts_tail & elts_m],
89                        0x77,
90                        sizeof((*elts)[elts_tail & elts_m]));
91 #endif
92                 ++elts_tail;
93         }
94 }
95
96 /**
97  * Returns the per-port supported offloads.
98  *
99  * @param dev
100  *   Pointer to Ethernet device.
101  *
102  * @return
103  *   Supported Tx offloads.
104  */
105 uint64_t
106 mlx5_get_tx_port_offloads(struct rte_eth_dev *dev)
107 {
108         struct mlx5_priv *priv = dev->data->dev_private;
109         uint64_t offloads = (DEV_TX_OFFLOAD_MULTI_SEGS |
110                              DEV_TX_OFFLOAD_VLAN_INSERT);
111         struct mlx5_dev_config *config = &priv->config;
112
113         if (config->hw_csum)
114                 offloads |= (DEV_TX_OFFLOAD_IPV4_CKSUM |
115                              DEV_TX_OFFLOAD_UDP_CKSUM |
116                              DEV_TX_OFFLOAD_TCP_CKSUM);
117         if (config->tso)
118                 offloads |= DEV_TX_OFFLOAD_TCP_TSO;
119         if (config->swp) {
120                 if (config->hw_csum)
121                         offloads |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM;
122                 if (config->tso)
123                         offloads |= (DEV_TX_OFFLOAD_IP_TNL_TSO |
124                                      DEV_TX_OFFLOAD_UDP_TNL_TSO);
125         }
126         if (config->tunnel_en) {
127                 if (config->hw_csum)
128                         offloads |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM;
129                 if (config->tso)
130                         offloads |= (DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
131                                      DEV_TX_OFFLOAD_GRE_TNL_TSO |
132                                      DEV_TX_OFFLOAD_GENEVE_TNL_TSO);
133         }
134         return offloads;
135 }
136
137 /**
138  * Tx queue presetup checks.
139  *
140  * @param dev
141  *   Pointer to Ethernet device structure.
142  * @param idx
143  *   Tx queue index.
144  * @param desc
145  *   Number of descriptors to configure in queue.
146  *
147  * @return
148  *   0 on success, a negative errno value otherwise and rte_errno is set.
149  */
150 static int
151 mlx5_tx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc)
152 {
153         struct mlx5_priv *priv = dev->data->dev_private;
154
155         if (desc <= MLX5_TX_COMP_THRESH) {
156                 DRV_LOG(WARNING,
157                         "port %u number of descriptors requested for Tx queue"
158                         " %u must be higher than MLX5_TX_COMP_THRESH, using %u"
159                         " instead of %u",
160                         dev->data->port_id, idx, MLX5_TX_COMP_THRESH + 1, desc);
161                 desc = MLX5_TX_COMP_THRESH + 1;
162         }
163         if (!rte_is_power_of_2(desc)) {
164                 desc = 1 << log2above(desc);
165                 DRV_LOG(WARNING,
166                         "port %u increased number of descriptors in Tx queue"
167                         " %u to the next power of two (%d)",
168                         dev->data->port_id, idx, desc);
169         }
170         DRV_LOG(DEBUG, "port %u configuring queue %u for %u descriptors",
171                 dev->data->port_id, idx, desc);
172         if (idx >= priv->txqs_n) {
173                 DRV_LOG(ERR, "port %u Tx queue index out of range (%u >= %u)",
174                         dev->data->port_id, idx, priv->txqs_n);
175                 rte_errno = EOVERFLOW;
176                 return -rte_errno;
177         }
178         if (!mlx5_txq_releasable(dev, idx)) {
179                 rte_errno = EBUSY;
180                 DRV_LOG(ERR, "port %u unable to release queue index %u",
181                         dev->data->port_id, idx);
182                 return -rte_errno;
183         }
184         mlx5_txq_release(dev, idx);
185         return 0;
186 }
187 /**
188  * DPDK callback to configure a TX queue.
189  *
190  * @param dev
191  *   Pointer to Ethernet device structure.
192  * @param idx
193  *   TX queue index.
194  * @param desc
195  *   Number of descriptors to configure in queue.
196  * @param socket
197  *   NUMA socket on which memory must be allocated.
198  * @param[in] conf
199  *   Thresholds parameters.
200  *
201  * @return
202  *   0 on success, a negative errno value otherwise and rte_errno is set.
203  */
204 int
205 mlx5_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
206                     unsigned int socket, const struct rte_eth_txconf *conf)
207 {
208         struct mlx5_priv *priv = dev->data->dev_private;
209         struct mlx5_txq_data *txq = (*priv->txqs)[idx];
210         struct mlx5_txq_ctrl *txq_ctrl =
211                 container_of(txq, struct mlx5_txq_ctrl, txq);
212         int res;
213
214         res = mlx5_tx_queue_pre_setup(dev, idx, desc);
215         if (res)
216                 return res;
217         txq_ctrl = mlx5_txq_new(dev, idx, desc, socket, conf);
218         if (!txq_ctrl) {
219                 DRV_LOG(ERR, "port %u unable to allocate queue index %u",
220                         dev->data->port_id, idx);
221                 return -rte_errno;
222         }
223         DRV_LOG(DEBUG, "port %u adding Tx queue %u to list",
224                 dev->data->port_id, idx);
225         (*priv->txqs)[idx] = &txq_ctrl->txq;
226         return 0;
227 }
228
229 /**
230  * DPDK callback to configure a TX hairpin queue.
231  *
232  * @param dev
233  *   Pointer to Ethernet device structure.
234  * @param idx
235  *   TX queue index.
236  * @param desc
237  *   Number of descriptors to configure in queue.
238  * @param[in] hairpin_conf
239  *   The hairpin binding configuration.
240  *
241  * @return
242  *   0 on success, a negative errno value otherwise and rte_errno is set.
243  */
244 int
245 mlx5_tx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
246                             uint16_t desc,
247                             const struct rte_eth_hairpin_conf *hairpin_conf)
248 {
249         struct mlx5_priv *priv = dev->data->dev_private;
250         struct mlx5_txq_data *txq = (*priv->txqs)[idx];
251         struct mlx5_txq_ctrl *txq_ctrl =
252                 container_of(txq, struct mlx5_txq_ctrl, txq);
253         int res;
254
255         res = mlx5_tx_queue_pre_setup(dev, idx, desc);
256         if (res)
257                 return res;
258         if (hairpin_conf->peer_count != 1 ||
259             hairpin_conf->peers[0].port != dev->data->port_id ||
260             hairpin_conf->peers[0].queue >= priv->rxqs_n) {
261                 DRV_LOG(ERR, "port %u unable to setup hairpin queue index %u "
262                         " invalid hairpind configuration", dev->data->port_id,
263                         idx);
264                 rte_errno = EINVAL;
265                 return -rte_errno;
266         }
267         txq_ctrl = mlx5_txq_hairpin_new(dev, idx, desc, hairpin_conf);
268         if (!txq_ctrl) {
269                 DRV_LOG(ERR, "port %u unable to allocate queue index %u",
270                         dev->data->port_id, idx);
271                 return -rte_errno;
272         }
273         DRV_LOG(DEBUG, "port %u adding Tx queue %u to list",
274                 dev->data->port_id, idx);
275         (*priv->txqs)[idx] = &txq_ctrl->txq;
276         return 0;
277 }
278
279 /**
280  * DPDK callback to release a TX queue.
281  *
282  * @param dpdk_txq
283  *   Generic TX queue pointer.
284  */
285 void
286 mlx5_tx_queue_release(void *dpdk_txq)
287 {
288         struct mlx5_txq_data *txq = (struct mlx5_txq_data *)dpdk_txq;
289         struct mlx5_txq_ctrl *txq_ctrl;
290         struct mlx5_priv *priv;
291         unsigned int i;
292
293         if (txq == NULL)
294                 return;
295         txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq);
296         priv = txq_ctrl->priv;
297         for (i = 0; (i != priv->txqs_n); ++i)
298                 if ((*priv->txqs)[i] == txq) {
299                         mlx5_txq_release(ETH_DEV(priv), i);
300                         DRV_LOG(DEBUG, "port %u removing Tx queue %u from list",
301                                 PORT_ID(priv), txq->idx);
302                         break;
303                 }
304 }
305
306 /**
307  * Configure the doorbell register non-cached attribute.
308  *
309  * @param txq_ctrl
310  *   Pointer to Tx queue control structure.
311  * @param page_size
312  *   Systme page size
313  */
314 static void
315 txq_uar_ncattr_init(struct mlx5_txq_ctrl *txq_ctrl, size_t page_size)
316 {
317         struct mlx5_priv *priv = txq_ctrl->priv;
318         off_t cmd;
319
320         txq_ctrl->txq.db_heu = priv->config.dbnc == MLX5_TXDB_HEURISTIC;
321         txq_ctrl->txq.db_nc = 0;
322         /* Check the doorbell register mapping type. */
323         cmd = txq_ctrl->uar_mmap_offset / page_size;
324         cmd >>= MLX5_UAR_MMAP_CMD_SHIFT;
325         cmd &= MLX5_UAR_MMAP_CMD_MASK;
326         if (cmd == MLX5_MMAP_GET_NC_PAGES_CMD)
327                 txq_ctrl->txq.db_nc = 1;
328 }
329
330 /**
331  * Initialize Tx UAR registers for primary process.
332  *
333  * @param txq_ctrl
334  *   Pointer to Tx queue control structure.
335  */
336 static void
337 txq_uar_init(struct mlx5_txq_ctrl *txq_ctrl)
338 {
339         struct mlx5_priv *priv = txq_ctrl->priv;
340         struct mlx5_proc_priv *ppriv = MLX5_PROC_PRIV(PORT_ID(priv));
341         const size_t page_size = sysconf(_SC_PAGESIZE);
342 #ifndef RTE_ARCH_64
343         unsigned int lock_idx;
344 #endif
345
346         if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
347                 return;
348         assert(rte_eal_process_type() == RTE_PROC_PRIMARY);
349         assert(ppriv);
350         ppriv->uar_table[txq_ctrl->txq.idx] = txq_ctrl->bf_reg;
351         txq_uar_ncattr_init(txq_ctrl, page_size);
352 #ifndef RTE_ARCH_64
353         /* Assign an UAR lock according to UAR page number */
354         lock_idx = (txq_ctrl->uar_mmap_offset / page_size) &
355                    MLX5_UAR_PAGE_NUM_MASK;
356         txq_ctrl->txq.uar_lock = &priv->uar_lock[lock_idx];
357 #endif
358 }
359
360 /**
361  * Remap UAR register of a Tx queue for secondary process.
362  *
363  * Remapped address is stored at the table in the process private structure of
364  * the device, indexed by queue index.
365  *
366  * @param txq_ctrl
367  *   Pointer to Tx queue control structure.
368  * @param fd
369  *   Verbs file descriptor to map UAR pages.
370  *
371  * @return
372  *   0 on success, a negative errno value otherwise and rte_errno is set.
373  */
374 static int
375 txq_uar_init_secondary(struct mlx5_txq_ctrl *txq_ctrl, int fd)
376 {
377         struct mlx5_priv *priv = txq_ctrl->priv;
378         struct mlx5_proc_priv *ppriv = MLX5_PROC_PRIV(PORT_ID(priv));
379         struct mlx5_txq_data *txq = &txq_ctrl->txq;
380         void *addr;
381         uintptr_t uar_va;
382         uintptr_t offset;
383         const size_t page_size = sysconf(_SC_PAGESIZE);
384
385         if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
386                 return 0;
387         assert(ppriv);
388         /*
389          * As rdma-core, UARs are mapped in size of OS page
390          * size. Ref to libmlx5 function: mlx5_init_context()
391          */
392         uar_va = (uintptr_t)txq_ctrl->bf_reg;
393         offset = uar_va & (page_size - 1); /* Offset in page. */
394         addr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, fd,
395                         txq_ctrl->uar_mmap_offset);
396         if (addr == MAP_FAILED) {
397                 DRV_LOG(ERR,
398                         "port %u mmap failed for BF reg of txq %u",
399                         txq->port_id, txq->idx);
400                 rte_errno = ENXIO;
401                 return -rte_errno;
402         }
403         addr = RTE_PTR_ADD(addr, offset);
404         ppriv->uar_table[txq->idx] = addr;
405         txq_uar_ncattr_init(txq_ctrl, page_size);
406         return 0;
407 }
408
409 /**
410  * Unmap UAR register of a Tx queue for secondary process.
411  *
412  * @param txq_ctrl
413  *   Pointer to Tx queue control structure.
414  */
415 static void
416 txq_uar_uninit_secondary(struct mlx5_txq_ctrl *txq_ctrl)
417 {
418         struct mlx5_proc_priv *ppriv = MLX5_PROC_PRIV(PORT_ID(txq_ctrl->priv));
419         const size_t page_size = sysconf(_SC_PAGESIZE);
420         void *addr;
421
422         if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
423                 return;
424         addr = ppriv->uar_table[txq_ctrl->txq.idx];
425         munmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
426 }
427
428 /**
429  * Initialize Tx UAR registers for secondary process.
430  *
431  * @param dev
432  *   Pointer to Ethernet device.
433  * @param fd
434  *   Verbs file descriptor to map UAR pages.
435  *
436  * @return
437  *   0 on success, a negative errno value otherwise and rte_errno is set.
438  */
439 int
440 mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd)
441 {
442         struct mlx5_priv *priv = dev->data->dev_private;
443         struct mlx5_txq_data *txq;
444         struct mlx5_txq_ctrl *txq_ctrl;
445         unsigned int i;
446         int ret;
447
448         assert(rte_eal_process_type() == RTE_PROC_SECONDARY);
449         for (i = 0; i != priv->txqs_n; ++i) {
450                 if (!(*priv->txqs)[i])
451                         continue;
452                 txq = (*priv->txqs)[i];
453                 txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq);
454                 if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
455                         continue;
456                 assert(txq->idx == (uint16_t)i);
457                 ret = txq_uar_init_secondary(txq_ctrl, fd);
458                 if (ret)
459                         goto error;
460         }
461         return 0;
462 error:
463         /* Rollback. */
464         do {
465                 if (!(*priv->txqs)[i])
466                         continue;
467                 txq = (*priv->txqs)[i];
468                 txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq);
469                 txq_uar_uninit_secondary(txq_ctrl);
470         } while (i--);
471         return -rte_errno;
472 }
473
474 /**
475  * Create the Tx hairpin queue object.
476  *
477  * @param dev
478  *   Pointer to Ethernet device.
479  * @param idx
480  *   Queue index in DPDK Tx queue array
481  *
482  * @return
483  *   The hairpin DevX object initialised, NULL otherwise and rte_errno is set.
484  */
485 static struct mlx5_txq_obj *
486 mlx5_txq_obj_hairpin_new(struct rte_eth_dev *dev, uint16_t idx)
487 {
488         struct mlx5_priv *priv = dev->data->dev_private;
489         struct mlx5_txq_data *txq_data = (*priv->txqs)[idx];
490         struct mlx5_txq_ctrl *txq_ctrl =
491                 container_of(txq_data, struct mlx5_txq_ctrl, txq);
492         struct mlx5_devx_create_sq_attr attr = { 0 };
493         struct mlx5_txq_obj *tmpl = NULL;
494         int ret = 0;
495
496         assert(txq_data);
497         assert(!txq_ctrl->obj);
498         tmpl = rte_calloc_socket(__func__, 1, sizeof(*tmpl), 0,
499                                  txq_ctrl->socket);
500         if (!tmpl) {
501                 DRV_LOG(ERR,
502                         "port %u Tx queue %u cannot allocate memory resources",
503                         dev->data->port_id, txq_data->idx);
504                 rte_errno = ENOMEM;
505                 goto error;
506         }
507         tmpl->type = MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN;
508         tmpl->txq_ctrl = txq_ctrl;
509         attr.hairpin = 1;
510         attr.tis_lst_sz = 1;
511         /* Workaround for hairpin startup */
512         attr.wq_attr.log_hairpin_num_packets = log2above(32);
513         /* Workaround for packets larger than 1KB */
514         attr.wq_attr.log_hairpin_data_sz =
515                         priv->config.hca_attr.log_max_hairpin_wq_data_sz;
516         attr.tis_num = priv->sh->tis->id;
517         tmpl->sq = mlx5_devx_cmd_create_sq(priv->sh->ctx, &attr);
518         if (!tmpl->sq) {
519                 DRV_LOG(ERR,
520                         "port %u tx hairpin queue %u can't create sq object",
521                         dev->data->port_id, idx);
522                 rte_errno = errno;
523                 goto error;
524         }
525         DRV_LOG(DEBUG, "port %u sxq %u updated with %p", dev->data->port_id,
526                 idx, (void *)&tmpl);
527         rte_atomic32_inc(&tmpl->refcnt);
528         LIST_INSERT_HEAD(&priv->txqsobj, tmpl, next);
529         return tmpl;
530 error:
531         ret = rte_errno; /* Save rte_errno before cleanup. */
532         if (tmpl->tis)
533                 mlx5_devx_cmd_destroy(tmpl->tis);
534         if (tmpl->sq)
535                 mlx5_devx_cmd_destroy(tmpl->sq);
536         rte_errno = ret; /* Restore rte_errno. */
537         return NULL;
538 }
539
540 /**
541  * Create the Tx queue Verbs object.
542  *
543  * @param dev
544  *   Pointer to Ethernet device.
545  * @param idx
546  *   Queue index in DPDK Tx queue array.
547  * @param type
548  *   Type of the Tx queue object to create.
549  *
550  * @return
551  *   The Verbs object initialised, NULL otherwise and rte_errno is set.
552  */
553 struct mlx5_txq_obj *
554 mlx5_txq_obj_new(struct rte_eth_dev *dev, uint16_t idx,
555                  enum mlx5_txq_obj_type type)
556 {
557         struct mlx5_priv *priv = dev->data->dev_private;
558         struct mlx5_txq_data *txq_data = (*priv->txqs)[idx];
559         struct mlx5_txq_ctrl *txq_ctrl =
560                 container_of(txq_data, struct mlx5_txq_ctrl, txq);
561         struct mlx5_txq_obj tmpl;
562         struct mlx5_txq_obj *txq_obj = NULL;
563         union {
564                 struct ibv_qp_init_attr_ex init;
565                 struct ibv_cq_init_attr_ex cq;
566                 struct ibv_qp_attr mod;
567         } attr;
568         unsigned int cqe_n;
569         struct mlx5dv_qp qp = { .comp_mask = MLX5DV_QP_MASK_UAR_MMAP_OFFSET };
570         struct mlx5dv_cq cq_info;
571         struct mlx5dv_obj obj;
572         const int desc = 1 << txq_data->elts_n;
573         int ret = 0;
574
575         if (type == MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN)
576                 return mlx5_txq_obj_hairpin_new(dev, idx);
577 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
578         /* If using DevX, need additional mask to read tisn value. */
579         if (priv->config.devx && !priv->sh->tdn)
580                 qp.comp_mask |= MLX5DV_QP_MASK_RAW_QP_HANDLES;
581 #endif
582         assert(txq_data);
583         priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_TX_QUEUE;
584         priv->verbs_alloc_ctx.obj = txq_ctrl;
585         if (mlx5_getenv_int("MLX5_ENABLE_CQE_COMPRESSION")) {
586                 DRV_LOG(ERR,
587                         "port %u MLX5_ENABLE_CQE_COMPRESSION must never be set",
588                         dev->data->port_id);
589                 rte_errno = EINVAL;
590                 return NULL;
591         }
592         memset(&tmpl, 0, sizeof(struct mlx5_txq_obj));
593         attr.cq = (struct ibv_cq_init_attr_ex){
594                 .comp_mask = 0,
595         };
596         cqe_n = desc / MLX5_TX_COMP_THRESH +
597                 1 + MLX5_TX_COMP_THRESH_INLINE_DIV;
598         tmpl.cq = mlx5_glue->create_cq(priv->sh->ctx, cqe_n, NULL, NULL, 0);
599         if (tmpl.cq == NULL) {
600                 DRV_LOG(ERR, "port %u Tx queue %u CQ creation failure",
601                         dev->data->port_id, idx);
602                 rte_errno = errno;
603                 goto error;
604         }
605         attr.init = (struct ibv_qp_init_attr_ex){
606                 /* CQ to be associated with the send queue. */
607                 .send_cq = tmpl.cq,
608                 /* CQ to be associated with the receive queue. */
609                 .recv_cq = tmpl.cq,
610                 .cap = {
611                         /* Max number of outstanding WRs. */
612                         .max_send_wr =
613                                 ((priv->sh->device_attr.orig_attr.max_qp_wr <
614                                   desc) ?
615                                  priv->sh->device_attr.orig_attr.max_qp_wr :
616                                  desc),
617                         /*
618                          * Max number of scatter/gather elements in a WR,
619                          * must be 1 to prevent libmlx5 from trying to affect
620                          * too much memory. TX gather is not impacted by the
621                          * device_attr.max_sge limit and will still work
622                          * properly.
623                          */
624                         .max_send_sge = 1,
625                 },
626                 .qp_type = IBV_QPT_RAW_PACKET,
627                 /*
628                  * Do *NOT* enable this, completions events are managed per
629                  * Tx burst.
630                  */
631                 .sq_sig_all = 0,
632                 .pd = priv->sh->pd,
633                 .comp_mask = IBV_QP_INIT_ATTR_PD,
634         };
635         if (txq_data->inlen_send)
636                 attr.init.cap.max_inline_data = txq_ctrl->max_inline_data;
637         if (txq_data->tso_en) {
638                 attr.init.max_tso_header = txq_ctrl->max_tso_header;
639                 attr.init.comp_mask |= IBV_QP_INIT_ATTR_MAX_TSO_HEADER;
640         }
641         tmpl.qp = mlx5_glue->create_qp_ex(priv->sh->ctx, &attr.init);
642         if (tmpl.qp == NULL) {
643                 DRV_LOG(ERR, "port %u Tx queue %u QP creation failure",
644                         dev->data->port_id, idx);
645                 rte_errno = errno;
646                 goto error;
647         }
648         attr.mod = (struct ibv_qp_attr){
649                 /* Move the QP to this state. */
650                 .qp_state = IBV_QPS_INIT,
651                 /* IB device port number. */
652                 .port_num = (uint8_t)priv->ibv_port,
653         };
654         ret = mlx5_glue->modify_qp(tmpl.qp, &attr.mod,
655                                    (IBV_QP_STATE | IBV_QP_PORT));
656         if (ret) {
657                 DRV_LOG(ERR,
658                         "port %u Tx queue %u QP state to IBV_QPS_INIT failed",
659                         dev->data->port_id, idx);
660                 rte_errno = errno;
661                 goto error;
662         }
663         attr.mod = (struct ibv_qp_attr){
664                 .qp_state = IBV_QPS_RTR
665         };
666         ret = mlx5_glue->modify_qp(tmpl.qp, &attr.mod, IBV_QP_STATE);
667         if (ret) {
668                 DRV_LOG(ERR,
669                         "port %u Tx queue %u QP state to IBV_QPS_RTR failed",
670                         dev->data->port_id, idx);
671                 rte_errno = errno;
672                 goto error;
673         }
674         attr.mod.qp_state = IBV_QPS_RTS;
675         ret = mlx5_glue->modify_qp(tmpl.qp, &attr.mod, IBV_QP_STATE);
676         if (ret) {
677                 DRV_LOG(ERR,
678                         "port %u Tx queue %u QP state to IBV_QPS_RTS failed",
679                         dev->data->port_id, idx);
680                 rte_errno = errno;
681                 goto error;
682         }
683         txq_obj = rte_calloc_socket(__func__, 1, sizeof(struct mlx5_txq_obj), 0,
684                                     txq_ctrl->socket);
685         if (!txq_obj) {
686                 DRV_LOG(ERR, "port %u Tx queue %u cannot allocate memory",
687                         dev->data->port_id, idx);
688                 rte_errno = ENOMEM;
689                 goto error;
690         }
691         obj.cq.in = tmpl.cq;
692         obj.cq.out = &cq_info;
693         obj.qp.in = tmpl.qp;
694         obj.qp.out = &qp;
695         ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_CQ | MLX5DV_OBJ_QP);
696         if (ret != 0) {
697                 rte_errno = errno;
698                 goto error;
699         }
700         if (cq_info.cqe_size != RTE_CACHE_LINE_SIZE) {
701                 DRV_LOG(ERR,
702                         "port %u wrong MLX5_CQE_SIZE environment variable"
703                         " value: it should be set to %u",
704                         dev->data->port_id, RTE_CACHE_LINE_SIZE);
705                 rte_errno = EINVAL;
706                 goto error;
707         }
708         txq_data->cqe_n = log2above(cq_info.cqe_cnt);
709         txq_data->cqe_s = 1 << txq_data->cqe_n;
710         txq_data->cqe_m = txq_data->cqe_s - 1;
711         txq_data->qp_num_8s = tmpl.qp->qp_num << 8;
712         txq_data->wqes = qp.sq.buf;
713         txq_data->wqe_n = log2above(qp.sq.wqe_cnt);
714         txq_data->wqe_s = 1 << txq_data->wqe_n;
715         txq_data->wqe_m = txq_data->wqe_s - 1;
716         txq_data->wqes_end = txq_data->wqes + txq_data->wqe_s;
717         txq_data->qp_db = &qp.dbrec[MLX5_SND_DBR];
718         txq_data->cq_db = cq_info.dbrec;
719         txq_data->cqes = (volatile struct mlx5_cqe *)cq_info.buf;
720         txq_data->cq_ci = 0;
721         txq_data->cq_pi = 0;
722         txq_data->wqe_ci = 0;
723         txq_data->wqe_pi = 0;
724         txq_data->wqe_comp = 0;
725         txq_data->wqe_thres = txq_data->wqe_s / MLX5_TX_COMP_THRESH_INLINE_DIV;
726         txq_data->fcqs = rte_calloc_socket(__func__,
727                                            txq_data->cqe_s,
728                                            sizeof(*txq_data->fcqs),
729                                            RTE_CACHE_LINE_SIZE,
730                                            txq_ctrl->socket);
731         if (!txq_data->fcqs) {
732                 DRV_LOG(ERR, "port %u Tx queue %u cannot allocate memory (FCQ)",
733                         dev->data->port_id, idx);
734                 rte_errno = ENOMEM;
735                 goto error;
736         }
737 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
738         /*
739          * If using DevX need to query and store TIS transport domain value.
740          * This is done once per port.
741          * Will use this value on Rx, when creating matching TIR.
742          */
743         if (priv->config.devx && !priv->sh->tdn) {
744                 ret = mlx5_devx_cmd_qp_query_tis_td(tmpl.qp, qp.tisn,
745                                                     &priv->sh->tdn);
746                 if (ret) {
747                         DRV_LOG(ERR, "Fail to query port %u Tx queue %u QP TIS "
748                                 "transport domain", dev->data->port_id, idx);
749                         rte_errno = EINVAL;
750                         goto error;
751                 } else {
752                         DRV_LOG(DEBUG, "port %u Tx queue %u TIS number %d "
753                                 "transport domain %d", dev->data->port_id,
754                                 idx, qp.tisn, priv->sh->tdn);
755                 }
756         }
757 #endif
758         txq_obj->qp = tmpl.qp;
759         txq_obj->cq = tmpl.cq;
760         rte_atomic32_inc(&txq_obj->refcnt);
761         txq_ctrl->bf_reg = qp.bf.reg;
762         if (qp.comp_mask & MLX5DV_QP_MASK_UAR_MMAP_OFFSET) {
763                 txq_ctrl->uar_mmap_offset = qp.uar_mmap_offset;
764                 DRV_LOG(DEBUG, "port %u: uar_mmap_offset 0x%"PRIx64,
765                         dev->data->port_id, txq_ctrl->uar_mmap_offset);
766         } else {
767                 DRV_LOG(ERR,
768                         "port %u failed to retrieve UAR info, invalid"
769                         " libmlx5.so",
770                         dev->data->port_id);
771                 rte_errno = EINVAL;
772                 goto error;
773         }
774         txq_uar_init(txq_ctrl);
775         LIST_INSERT_HEAD(&priv->txqsobj, txq_obj, next);
776         txq_obj->txq_ctrl = txq_ctrl;
777         priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;
778         return txq_obj;
779 error:
780         ret = rte_errno; /* Save rte_errno before cleanup. */
781         if (tmpl.cq)
782                 claim_zero(mlx5_glue->destroy_cq(tmpl.cq));
783         if (tmpl.qp)
784                 claim_zero(mlx5_glue->destroy_qp(tmpl.qp));
785         if (txq_data && txq_data->fcqs)
786                 rte_free(txq_data->fcqs);
787         if (txq_obj)
788                 rte_free(txq_obj);
789         priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;
790         rte_errno = ret; /* Restore rte_errno. */
791         return NULL;
792 }
793
794 /**
795  * Get an Tx queue Verbs object.
796  *
797  * @param dev
798  *   Pointer to Ethernet device.
799  * @param idx
800  *   Queue index in DPDK Tx queue array.
801  *
802  * @return
803  *   The Verbs object if it exists.
804  */
805 struct mlx5_txq_obj *
806 mlx5_txq_obj_get(struct rte_eth_dev *dev, uint16_t idx)
807 {
808         struct mlx5_priv *priv = dev->data->dev_private;
809         struct mlx5_txq_ctrl *txq_ctrl;
810
811         if (idx >= priv->txqs_n)
812                 return NULL;
813         if (!(*priv->txqs)[idx])
814                 return NULL;
815         txq_ctrl = container_of((*priv->txqs)[idx], struct mlx5_txq_ctrl, txq);
816         if (txq_ctrl->obj)
817                 rte_atomic32_inc(&txq_ctrl->obj->refcnt);
818         return txq_ctrl->obj;
819 }
820
821 /**
822  * Release an Tx verbs queue object.
823  *
824  * @param txq_obj
825  *   Verbs Tx queue object.
826  *
827  * @return
828  *   1 while a reference on it exists, 0 when freed.
829  */
830 int
831 mlx5_txq_obj_release(struct mlx5_txq_obj *txq_obj)
832 {
833         assert(txq_obj);
834         if (rte_atomic32_dec_and_test(&txq_obj->refcnt)) {
835                 if (txq_obj->type == MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN) {
836                         if (txq_obj->tis)
837                                 claim_zero(mlx5_devx_cmd_destroy(txq_obj->tis));
838                 } else {
839                         claim_zero(mlx5_glue->destroy_qp(txq_obj->qp));
840                         claim_zero(mlx5_glue->destroy_cq(txq_obj->cq));
841                                 if (txq_obj->txq_ctrl->txq.fcqs)
842                                         rte_free(txq_obj->txq_ctrl->txq.fcqs);
843                 }
844                 LIST_REMOVE(txq_obj, next);
845                 rte_free(txq_obj);
846                 return 0;
847         }
848         return 1;
849 }
850
851 /**
852  * Verify the Verbs Tx queue list is empty
853  *
854  * @param dev
855  *   Pointer to Ethernet device.
856  *
857  * @return
858  *   The number of object not released.
859  */
860 int
861 mlx5_txq_obj_verify(struct rte_eth_dev *dev)
862 {
863         struct mlx5_priv *priv = dev->data->dev_private;
864         int ret = 0;
865         struct mlx5_txq_obj *txq_obj;
866
867         LIST_FOREACH(txq_obj, &priv->txqsobj, next) {
868                 DRV_LOG(DEBUG, "port %u Verbs Tx queue %u still referenced",
869                         dev->data->port_id, txq_obj->txq_ctrl->txq.idx);
870                 ++ret;
871         }
872         return ret;
873 }
874
875 /**
876  * Calculate the total number of WQEBB for Tx queue.
877  *
878  * Simplified version of calc_sq_size() in rdma-core.
879  *
880  * @param txq_ctrl
881  *   Pointer to Tx queue control structure.
882  *
883  * @return
884  *   The number of WQEBB.
885  */
886 static int
887 txq_calc_wqebb_cnt(struct mlx5_txq_ctrl *txq_ctrl)
888 {
889         unsigned int wqe_size;
890         const unsigned int desc = 1 << txq_ctrl->txq.elts_n;
891
892         wqe_size = MLX5_WQE_CSEG_SIZE +
893                    MLX5_WQE_ESEG_SIZE +
894                    MLX5_WSEG_SIZE -
895                    MLX5_ESEG_MIN_INLINE_SIZE +
896                    txq_ctrl->max_inline_data;
897         return rte_align32pow2(wqe_size * desc) / MLX5_WQE_SIZE;
898 }
899
900 /**
901  * Calculate the maximal inline data size for Tx queue.
902  *
903  * @param txq_ctrl
904  *   Pointer to Tx queue control structure.
905  *
906  * @return
907  *   The maximal inline data size.
908  */
909 static unsigned int
910 txq_calc_inline_max(struct mlx5_txq_ctrl *txq_ctrl)
911 {
912         const unsigned int desc = 1 << txq_ctrl->txq.elts_n;
913         struct mlx5_priv *priv = txq_ctrl->priv;
914         unsigned int wqe_size;
915
916         wqe_size = priv->sh->device_attr.orig_attr.max_qp_wr / desc;
917         if (!wqe_size)
918                 return 0;
919         /*
920          * This calculation is derived from tthe source of
921          * mlx5_calc_send_wqe() in rdma_core library.
922          */
923         wqe_size = wqe_size * MLX5_WQE_SIZE -
924                    MLX5_WQE_CSEG_SIZE -
925                    MLX5_WQE_ESEG_SIZE -
926                    MLX5_WSEG_SIZE -
927                    MLX5_WSEG_SIZE +
928                    MLX5_DSEG_MIN_INLINE_SIZE;
929         return wqe_size;
930 }
931
932 /**
933  * Set Tx queue parameters from device configuration.
934  *
935  * @param txq_ctrl
936  *   Pointer to Tx queue control structure.
937  */
938 static void
939 txq_set_params(struct mlx5_txq_ctrl *txq_ctrl)
940 {
941         struct mlx5_priv *priv = txq_ctrl->priv;
942         struct mlx5_dev_config *config = &priv->config;
943         unsigned int inlen_send; /* Inline data for ordinary SEND.*/
944         unsigned int inlen_empw; /* Inline data for enhanced MPW. */
945         unsigned int inlen_mode; /* Minimal required Inline data. */
946         unsigned int txqs_inline; /* Min Tx queues to enable inline. */
947         uint64_t dev_txoff = priv->dev_data->dev_conf.txmode.offloads;
948         bool tso = txq_ctrl->txq.offloads & (DEV_TX_OFFLOAD_TCP_TSO |
949                                             DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
950                                             DEV_TX_OFFLOAD_GRE_TNL_TSO |
951                                             DEV_TX_OFFLOAD_IP_TNL_TSO |
952                                             DEV_TX_OFFLOAD_UDP_TNL_TSO);
953         bool vlan_inline;
954         unsigned int temp;
955
956         if (config->txqs_inline == MLX5_ARG_UNSET)
957                 txqs_inline =
958 #if defined(RTE_ARCH_ARM64)
959                 (priv->pci_dev->id.device_id ==
960                         PCI_DEVICE_ID_MELLANOX_CONNECTX5BF) ?
961                         MLX5_INLINE_MAX_TXQS_BLUEFIELD :
962 #endif
963                         MLX5_INLINE_MAX_TXQS;
964         else
965                 txqs_inline = (unsigned int)config->txqs_inline;
966         inlen_send = (config->txq_inline_max == MLX5_ARG_UNSET) ?
967                      MLX5_SEND_DEF_INLINE_LEN :
968                      (unsigned int)config->txq_inline_max;
969         inlen_empw = (config->txq_inline_mpw == MLX5_ARG_UNSET) ?
970                      MLX5_EMPW_DEF_INLINE_LEN :
971                      (unsigned int)config->txq_inline_mpw;
972         inlen_mode = (config->txq_inline_min == MLX5_ARG_UNSET) ?
973                      0 : (unsigned int)config->txq_inline_min;
974         if (config->mps != MLX5_MPW_ENHANCED && config->mps != MLX5_MPW)
975                 inlen_empw = 0;
976         /*
977          * If there is requested minimal amount of data to inline
978          * we MUST enable inlining. This is a case for ConnectX-4
979          * which usually requires L2 inlined for correct operating
980          * and ConnectX-4LX which requires L2-L4 inlined to
981          * support E-Switch Flows.
982          */
983         if (inlen_mode) {
984                 if (inlen_mode <= MLX5_ESEG_MIN_INLINE_SIZE) {
985                         /*
986                          * Optimize minimal inlining for single
987                          * segment packets to fill one WQEBB
988                          * without gaps.
989                          */
990                         temp = MLX5_ESEG_MIN_INLINE_SIZE;
991                 } else {
992                         temp = inlen_mode - MLX5_ESEG_MIN_INLINE_SIZE;
993                         temp = RTE_ALIGN(temp, MLX5_WSEG_SIZE) +
994                                MLX5_ESEG_MIN_INLINE_SIZE;
995                         temp = RTE_MIN(temp, MLX5_SEND_MAX_INLINE_LEN);
996                 }
997                 if (temp != inlen_mode) {
998                         DRV_LOG(INFO,
999                                 "port %u minimal required inline setting"
1000                                 " aligned from %u to %u",
1001                                 PORT_ID(priv), inlen_mode, temp);
1002                         inlen_mode = temp;
1003                 }
1004         }
1005         /*
1006          * If port is configured to support VLAN insertion and device
1007          * does not support this feature by HW (for NICs before ConnectX-5
1008          * or in case of wqe_vlan_insert flag is not set) we must enable
1009          * data inline on all queues because it is supported by single
1010          * tx_burst routine.
1011          */
1012         txq_ctrl->txq.vlan_en = config->hw_vlan_insert;
1013         vlan_inline = (dev_txoff & DEV_TX_OFFLOAD_VLAN_INSERT) &&
1014                       !config->hw_vlan_insert;
1015         /*
1016          * If there are few Tx queues it is prioritized
1017          * to save CPU cycles and disable data inlining at all.
1018          */
1019         if (inlen_send && priv->txqs_n >= txqs_inline) {
1020                 /*
1021                  * The data sent with ordinal MLX5_OPCODE_SEND
1022                  * may be inlined in Ethernet Segment, align the
1023                  * length accordingly to fit entire WQEBBs.
1024                  */
1025                 temp = RTE_MAX(inlen_send,
1026                                MLX5_ESEG_MIN_INLINE_SIZE + MLX5_WQE_DSEG_SIZE);
1027                 temp -= MLX5_ESEG_MIN_INLINE_SIZE + MLX5_WQE_DSEG_SIZE;
1028                 temp = RTE_ALIGN(temp, MLX5_WQE_SIZE);
1029                 temp += MLX5_ESEG_MIN_INLINE_SIZE + MLX5_WQE_DSEG_SIZE;
1030                 temp = RTE_MIN(temp, MLX5_WQE_SIZE_MAX +
1031                                      MLX5_ESEG_MIN_INLINE_SIZE -
1032                                      MLX5_WQE_CSEG_SIZE -
1033                                      MLX5_WQE_ESEG_SIZE -
1034                                      MLX5_WQE_DSEG_SIZE * 2);
1035                 temp = RTE_MIN(temp, MLX5_SEND_MAX_INLINE_LEN);
1036                 temp = RTE_MAX(temp, inlen_mode);
1037                 if (temp != inlen_send) {
1038                         DRV_LOG(INFO,
1039                                 "port %u ordinary send inline setting"
1040                                 " aligned from %u to %u",
1041                                 PORT_ID(priv), inlen_send, temp);
1042                         inlen_send = temp;
1043                 }
1044                 /*
1045                  * Not aligned to cache lines, but to WQEs.
1046                  * First bytes of data (initial alignment)
1047                  * is going to be copied explicitly at the
1048                  * beginning of inlining buffer in Ethernet
1049                  * Segment.
1050                  */
1051                 assert(inlen_send >= MLX5_ESEG_MIN_INLINE_SIZE);
1052                 assert(inlen_send <= MLX5_WQE_SIZE_MAX +
1053                                      MLX5_ESEG_MIN_INLINE_SIZE -
1054                                      MLX5_WQE_CSEG_SIZE -
1055                                      MLX5_WQE_ESEG_SIZE -
1056                                      MLX5_WQE_DSEG_SIZE * 2);
1057         } else if (inlen_mode) {
1058                 /*
1059                  * If minimal inlining is requested we must
1060                  * enable inlining in general, despite the
1061                  * number of configured queues. Ignore the
1062                  * txq_inline_max devarg, this is not
1063                  * full-featured inline.
1064                  */
1065                 inlen_send = inlen_mode;
1066                 inlen_empw = 0;
1067         } else if (vlan_inline) {
1068                 /*
1069                  * Hardware does not report offload for
1070                  * VLAN insertion, we must enable data inline
1071                  * to implement feature by software.
1072                  */
1073                 inlen_send = MLX5_ESEG_MIN_INLINE_SIZE;
1074                 inlen_empw = 0;
1075         } else {
1076                 inlen_send = 0;
1077                 inlen_empw = 0;
1078         }
1079         txq_ctrl->txq.inlen_send = inlen_send;
1080         txq_ctrl->txq.inlen_mode = inlen_mode;
1081         txq_ctrl->txq.inlen_empw = 0;
1082         if (inlen_send && inlen_empw && priv->txqs_n >= txqs_inline) {
1083                 /*
1084                  * The data sent with MLX5_OPCODE_ENHANCED_MPSW
1085                  * may be inlined in Data Segment, align the
1086                  * length accordingly to fit entire WQEBBs.
1087                  */
1088                 temp = RTE_MAX(inlen_empw,
1089                                MLX5_WQE_SIZE + MLX5_DSEG_MIN_INLINE_SIZE);
1090                 temp -= MLX5_DSEG_MIN_INLINE_SIZE;
1091                 temp = RTE_ALIGN(temp, MLX5_WQE_SIZE);
1092                 temp += MLX5_DSEG_MIN_INLINE_SIZE;
1093                 temp = RTE_MIN(temp, MLX5_WQE_SIZE_MAX +
1094                                      MLX5_DSEG_MIN_INLINE_SIZE -
1095                                      MLX5_WQE_CSEG_SIZE -
1096                                      MLX5_WQE_ESEG_SIZE -
1097                                      MLX5_WQE_DSEG_SIZE);
1098                 temp = RTE_MIN(temp, MLX5_EMPW_MAX_INLINE_LEN);
1099                 if (temp != inlen_empw) {
1100                         DRV_LOG(INFO,
1101                                 "port %u enhanced empw inline setting"
1102                                 " aligned from %u to %u",
1103                                 PORT_ID(priv), inlen_empw, temp);
1104                         inlen_empw = temp;
1105                 }
1106                 assert(inlen_empw >= MLX5_ESEG_MIN_INLINE_SIZE);
1107                 assert(inlen_empw <= MLX5_WQE_SIZE_MAX +
1108                                      MLX5_DSEG_MIN_INLINE_SIZE -
1109                                      MLX5_WQE_CSEG_SIZE -
1110                                      MLX5_WQE_ESEG_SIZE -
1111                                      MLX5_WQE_DSEG_SIZE);
1112                 txq_ctrl->txq.inlen_empw = inlen_empw;
1113         }
1114         txq_ctrl->max_inline_data = RTE_MAX(inlen_send, inlen_empw);
1115         if (tso) {
1116                 txq_ctrl->max_tso_header = MLX5_MAX_TSO_HEADER;
1117                 txq_ctrl->max_inline_data = RTE_MAX(txq_ctrl->max_inline_data,
1118                                                     MLX5_MAX_TSO_HEADER);
1119                 txq_ctrl->txq.tso_en = 1;
1120         }
1121         txq_ctrl->txq.tunnel_en = config->tunnel_en | config->swp;
1122         txq_ctrl->txq.swp_en = ((DEV_TX_OFFLOAD_IP_TNL_TSO |
1123                                  DEV_TX_OFFLOAD_UDP_TNL_TSO |
1124                                  DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) &
1125                                 txq_ctrl->txq.offloads) && config->swp;
1126 }
1127
1128 /**
1129  * Adjust Tx queue data inline parameters for large queue sizes.
1130  * The data inline feature requires multiple WQEs to fit the packets,
1131  * and if the large amount of Tx descriptors is requested by application
1132  * the total WQE amount may exceed the hardware capabilities. If the
1133  * default inline setting are used we can try to adjust these ones and
1134  * meet the hardware requirements and not exceed the queue size.
1135  *
1136  * @param txq_ctrl
1137  *   Pointer to Tx queue control structure.
1138  *
1139  * @return
1140  *   Zero on success, otherwise the parameters can not be adjusted.
1141  */
1142 static int
1143 txq_adjust_params(struct mlx5_txq_ctrl *txq_ctrl)
1144 {
1145         struct mlx5_priv *priv = txq_ctrl->priv;
1146         struct mlx5_dev_config *config = &priv->config;
1147         unsigned int max_inline;
1148
1149         max_inline = txq_calc_inline_max(txq_ctrl);
1150         if (!txq_ctrl->txq.inlen_send) {
1151                 /*
1152                  * Inline data feature is not engaged at all.
1153                  * There is nothing to adjust.
1154                  */
1155                 return 0;
1156         }
1157         if (txq_ctrl->max_inline_data <= max_inline) {
1158                 /*
1159                  * The requested inline data length does not
1160                  * exceed queue capabilities.
1161                  */
1162                 return 0;
1163         }
1164         if (txq_ctrl->txq.inlen_mode > max_inline) {
1165                 DRV_LOG(ERR,
1166                         "minimal data inline requirements (%u) are not"
1167                         " satisfied (%u) on port %u, try the smaller"
1168                         " Tx queue size (%d)",
1169                         txq_ctrl->txq.inlen_mode, max_inline,
1170                         priv->dev_data->port_id,
1171                         priv->sh->device_attr.orig_attr.max_qp_wr);
1172                 goto error;
1173         }
1174         if (txq_ctrl->txq.inlen_send > max_inline &&
1175             config->txq_inline_max != MLX5_ARG_UNSET &&
1176             config->txq_inline_max > (int)max_inline) {
1177                 DRV_LOG(ERR,
1178                         "txq_inline_max requirements (%u) are not"
1179                         " satisfied (%u) on port %u, try the smaller"
1180                         " Tx queue size (%d)",
1181                         txq_ctrl->txq.inlen_send, max_inline,
1182                         priv->dev_data->port_id,
1183                         priv->sh->device_attr.orig_attr.max_qp_wr);
1184                 goto error;
1185         }
1186         if (txq_ctrl->txq.inlen_empw > max_inline &&
1187             config->txq_inline_mpw != MLX5_ARG_UNSET &&
1188             config->txq_inline_mpw > (int)max_inline) {
1189                 DRV_LOG(ERR,
1190                         "txq_inline_mpw requirements (%u) are not"
1191                         " satisfied (%u) on port %u, try the smaller"
1192                         " Tx queue size (%d)",
1193                         txq_ctrl->txq.inlen_empw, max_inline,
1194                         priv->dev_data->port_id,
1195                         priv->sh->device_attr.orig_attr.max_qp_wr);
1196                 goto error;
1197         }
1198         if (txq_ctrl->txq.tso_en && max_inline < MLX5_MAX_TSO_HEADER) {
1199                 DRV_LOG(ERR,
1200                         "tso header inline requirements (%u) are not"
1201                         " satisfied (%u) on port %u, try the smaller"
1202                         " Tx queue size (%d)",
1203                         MLX5_MAX_TSO_HEADER, max_inline,
1204                         priv->dev_data->port_id,
1205                         priv->sh->device_attr.orig_attr.max_qp_wr);
1206                 goto error;
1207         }
1208         if (txq_ctrl->txq.inlen_send > max_inline) {
1209                 DRV_LOG(WARNING,
1210                         "adjust txq_inline_max (%u->%u)"
1211                         " due to large Tx queue on port %u",
1212                         txq_ctrl->txq.inlen_send, max_inline,
1213                         priv->dev_data->port_id);
1214                 txq_ctrl->txq.inlen_send = max_inline;
1215         }
1216         if (txq_ctrl->txq.inlen_empw > max_inline) {
1217                 DRV_LOG(WARNING,
1218                         "adjust txq_inline_mpw (%u->%u)"
1219                         "due to large Tx queue on port %u",
1220                         txq_ctrl->txq.inlen_empw, max_inline,
1221                         priv->dev_data->port_id);
1222                 txq_ctrl->txq.inlen_empw = max_inline;
1223         }
1224         txq_ctrl->max_inline_data = RTE_MAX(txq_ctrl->txq.inlen_send,
1225                                             txq_ctrl->txq.inlen_empw);
1226         assert(txq_ctrl->max_inline_data <= max_inline);
1227         assert(txq_ctrl->txq.inlen_mode <= max_inline);
1228         assert(txq_ctrl->txq.inlen_mode <= txq_ctrl->txq.inlen_send);
1229         assert(txq_ctrl->txq.inlen_mode <= txq_ctrl->txq.inlen_empw ||
1230                !txq_ctrl->txq.inlen_empw);
1231         return 0;
1232 error:
1233         rte_errno = ENOMEM;
1234         return -ENOMEM;
1235 }
1236
1237 /**
1238  * Create a DPDK Tx queue.
1239  *
1240  * @param dev
1241  *   Pointer to Ethernet device.
1242  * @param idx
1243  *   TX queue index.
1244  * @param desc
1245  *   Number of descriptors to configure in queue.
1246  * @param socket
1247  *   NUMA socket on which memory must be allocated.
1248  * @param[in] conf
1249  *  Thresholds parameters.
1250  *
1251  * @return
1252  *   A DPDK queue object on success, NULL otherwise and rte_errno is set.
1253  */
1254 struct mlx5_txq_ctrl *
1255 mlx5_txq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
1256              unsigned int socket, const struct rte_eth_txconf *conf)
1257 {
1258         struct mlx5_priv *priv = dev->data->dev_private;
1259         struct mlx5_txq_ctrl *tmpl;
1260
1261         tmpl = rte_calloc_socket("TXQ", 1,
1262                                  sizeof(*tmpl) +
1263                                  desc * sizeof(struct rte_mbuf *),
1264                                  0, socket);
1265         if (!tmpl) {
1266                 rte_errno = ENOMEM;
1267                 return NULL;
1268         }
1269         if (mlx5_mr_btree_init(&tmpl->txq.mr_ctrl.cache_bh,
1270                                MLX5_MR_BTREE_CACHE_N, socket)) {
1271                 /* rte_errno is already set. */
1272                 goto error;
1273         }
1274         /* Save pointer of global generation number to check memory event. */
1275         tmpl->txq.mr_ctrl.dev_gen_ptr = &priv->sh->mr.dev_gen;
1276         assert(desc > MLX5_TX_COMP_THRESH);
1277         tmpl->txq.offloads = conf->offloads |
1278                              dev->data->dev_conf.txmode.offloads;
1279         tmpl->priv = priv;
1280         tmpl->socket = socket;
1281         tmpl->txq.elts_n = log2above(desc);
1282         tmpl->txq.elts_s = desc;
1283         tmpl->txq.elts_m = desc - 1;
1284         tmpl->txq.port_id = dev->data->port_id;
1285         tmpl->txq.idx = idx;
1286         txq_set_params(tmpl);
1287         if (txq_adjust_params(tmpl))
1288                 goto error;
1289         if (txq_calc_wqebb_cnt(tmpl) >
1290             priv->sh->device_attr.orig_attr.max_qp_wr) {
1291                 DRV_LOG(ERR,
1292                         "port %u Tx WQEBB count (%d) exceeds the limit (%d),"
1293                         " try smaller queue size",
1294                         dev->data->port_id, txq_calc_wqebb_cnt(tmpl),
1295                         priv->sh->device_attr.orig_attr.max_qp_wr);
1296                 rte_errno = ENOMEM;
1297                 goto error;
1298         }
1299         rte_atomic32_inc(&tmpl->refcnt);
1300         tmpl->type = MLX5_TXQ_TYPE_STANDARD;
1301         LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
1302         return tmpl;
1303 error:
1304         rte_free(tmpl);
1305         return NULL;
1306 }
1307
1308 /**
1309  * Create a DPDK Tx hairpin queue.
1310  *
1311  * @param dev
1312  *   Pointer to Ethernet device.
1313  * @param idx
1314  *   TX queue index.
1315  * @param desc
1316  *   Number of descriptors to configure in queue.
1317  * @param hairpin_conf
1318  *  The hairpin configuration.
1319  *
1320  * @return
1321  *   A DPDK queue object on success, NULL otherwise and rte_errno is set.
1322  */
1323 struct mlx5_txq_ctrl *
1324 mlx5_txq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
1325                      const struct rte_eth_hairpin_conf *hairpin_conf)
1326 {
1327         struct mlx5_priv *priv = dev->data->dev_private;
1328         struct mlx5_txq_ctrl *tmpl;
1329
1330         tmpl = rte_calloc_socket("TXQ", 1,
1331                                  sizeof(*tmpl), 0, SOCKET_ID_ANY);
1332         if (!tmpl) {
1333                 rte_errno = ENOMEM;
1334                 return NULL;
1335         }
1336         tmpl->priv = priv;
1337         tmpl->socket = SOCKET_ID_ANY;
1338         tmpl->txq.elts_n = log2above(desc);
1339         tmpl->txq.port_id = dev->data->port_id;
1340         tmpl->txq.idx = idx;
1341         tmpl->hairpin_conf = *hairpin_conf;
1342         tmpl->type = MLX5_TXQ_TYPE_HAIRPIN;
1343         rte_atomic32_inc(&tmpl->refcnt);
1344         LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
1345         return tmpl;
1346 }
1347
1348 /**
1349  * Get a Tx queue.
1350  *
1351  * @param dev
1352  *   Pointer to Ethernet device.
1353  * @param idx
1354  *   TX queue index.
1355  *
1356  * @return
1357  *   A pointer to the queue if it exists.
1358  */
1359 struct mlx5_txq_ctrl *
1360 mlx5_txq_get(struct rte_eth_dev *dev, uint16_t idx)
1361 {
1362         struct mlx5_priv *priv = dev->data->dev_private;
1363         struct mlx5_txq_ctrl *ctrl = NULL;
1364
1365         if ((*priv->txqs)[idx]) {
1366                 ctrl = container_of((*priv->txqs)[idx], struct mlx5_txq_ctrl,
1367                                     txq);
1368                 mlx5_txq_obj_get(dev, idx);
1369                 rte_atomic32_inc(&ctrl->refcnt);
1370         }
1371         return ctrl;
1372 }
1373
1374 /**
1375  * Release a Tx queue.
1376  *
1377  * @param dev
1378  *   Pointer to Ethernet device.
1379  * @param idx
1380  *   TX queue index.
1381  *
1382  * @return
1383  *   1 while a reference on it exists, 0 when freed.
1384  */
1385 int
1386 mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
1387 {
1388         struct mlx5_priv *priv = dev->data->dev_private;
1389         struct mlx5_txq_ctrl *txq;
1390
1391         if (!(*priv->txqs)[idx])
1392                 return 0;
1393         txq = container_of((*priv->txqs)[idx], struct mlx5_txq_ctrl, txq);
1394         if (txq->obj && !mlx5_txq_obj_release(txq->obj))
1395                 txq->obj = NULL;
1396         if (rte_atomic32_dec_and_test(&txq->refcnt)) {
1397                 txq_free_elts(txq);
1398                 mlx5_mr_btree_free(&txq->txq.mr_ctrl.cache_bh);
1399                 LIST_REMOVE(txq, next);
1400                 rte_free(txq);
1401                 (*priv->txqs)[idx] = NULL;
1402                 return 0;
1403         }
1404         return 1;
1405 }
1406
1407 /**
1408  * Verify if the queue can be released.
1409  *
1410  * @param dev
1411  *   Pointer to Ethernet device.
1412  * @param idx
1413  *   TX queue index.
1414  *
1415  * @return
1416  *   1 if the queue can be released.
1417  */
1418 int
1419 mlx5_txq_releasable(struct rte_eth_dev *dev, uint16_t idx)
1420 {
1421         struct mlx5_priv *priv = dev->data->dev_private;
1422         struct mlx5_txq_ctrl *txq;
1423
1424         if (!(*priv->txqs)[idx])
1425                 return -1;
1426         txq = container_of((*priv->txqs)[idx], struct mlx5_txq_ctrl, txq);
1427         return (rte_atomic32_read(&txq->refcnt) == 1);
1428 }
1429
1430 /**
1431  * Verify the Tx Queue list is empty
1432  *
1433  * @param dev
1434  *   Pointer to Ethernet device.
1435  *
1436  * @return
1437  *   The number of object not released.
1438  */
1439 int
1440 mlx5_txq_verify(struct rte_eth_dev *dev)
1441 {
1442         struct mlx5_priv *priv = dev->data->dev_private;
1443         struct mlx5_txq_ctrl *txq_ctrl;
1444         int ret = 0;
1445
1446         LIST_FOREACH(txq_ctrl, &priv->txqsctrl, next) {
1447                 DRV_LOG(DEBUG, "port %u Tx queue %u still referenced",
1448                         dev->data->port_id, txq_ctrl->txq.idx);
1449                 ++ret;
1450         }
1451         return ret;
1452 }