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