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