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