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