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