net/mlx5: add RSS hash result with mark id
[dpdk.git] / drivers / net / mlx5 / mlx5_rxtx.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2015 6WIND S.A.
5  *   Copyright 2015 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <assert.h>
35 #include <stdint.h>
36 #include <string.h>
37 #include <stdlib.h>
38
39 /* Verbs header. */
40 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
41 #ifdef PEDANTIC
42 #pragma GCC diagnostic ignored "-Wpedantic"
43 #endif
44 #include <infiniband/verbs.h>
45 #include <infiniband/mlx5_hw.h>
46 #include <infiniband/arch.h>
47 #ifdef PEDANTIC
48 #pragma GCC diagnostic error "-Wpedantic"
49 #endif
50
51 /* DPDK headers don't like -pedantic. */
52 #ifdef PEDANTIC
53 #pragma GCC diagnostic ignored "-Wpedantic"
54 #endif
55 #include <rte_mbuf.h>
56 #include <rte_mempool.h>
57 #include <rte_prefetch.h>
58 #include <rte_common.h>
59 #include <rte_branch_prediction.h>
60 #include <rte_ether.h>
61 #ifdef PEDANTIC
62 #pragma GCC diagnostic error "-Wpedantic"
63 #endif
64
65 #include "mlx5.h"
66 #include "mlx5_utils.h"
67 #include "mlx5_rxtx.h"
68 #include "mlx5_autoconf.h"
69 #include "mlx5_defs.h"
70 #include "mlx5_prm.h"
71
72 static inline int
73 check_cqe(volatile struct mlx5_cqe *cqe,
74           unsigned int cqes_n, const uint16_t ci)
75           __attribute__((always_inline));
76
77 static inline void
78 txq_complete(struct txq *txq) __attribute__((always_inline));
79
80 static inline uint32_t
81 txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
82         __attribute__((always_inline));
83
84 static inline void
85 mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
86         __attribute__((always_inline));
87
88 static inline uint32_t
89 rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe)
90         __attribute__((always_inline));
91
92 static inline int
93 mlx5_rx_poll_len(struct rxq *rxq, volatile struct mlx5_cqe *cqe,
94                  uint16_t cqe_cnt, uint32_t *rss_hash)
95                  __attribute__((always_inline));
96
97 static inline uint32_t
98 rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe *cqe)
99                    __attribute__((always_inline));
100
101 #ifndef NDEBUG
102
103 /**
104  * Verify or set magic value in CQE.
105  *
106  * @param cqe
107  *   Pointer to CQE.
108  *
109  * @return
110  *   0 the first time.
111  */
112 static inline int
113 check_cqe_seen(volatile struct mlx5_cqe *cqe)
114 {
115         static const uint8_t magic[] = "seen";
116         volatile uint8_t (*buf)[sizeof(cqe->rsvd0)] = &cqe->rsvd0;
117         int ret = 1;
118         unsigned int i;
119
120         for (i = 0; i < sizeof(magic) && i < sizeof(*buf); ++i)
121                 if (!ret || (*buf)[i] != magic[i]) {
122                         ret = 0;
123                         (*buf)[i] = magic[i];
124                 }
125         return ret;
126 }
127
128 #endif /* NDEBUG */
129
130 /**
131  * Check whether CQE is valid.
132  *
133  * @param cqe
134  *   Pointer to CQE.
135  * @param cqes_n
136  *   Size of completion queue.
137  * @param ci
138  *   Consumer index.
139  *
140  * @return
141  *   0 on success, 1 on failure.
142  */
143 static inline int
144 check_cqe(volatile struct mlx5_cqe *cqe,
145           unsigned int cqes_n, const uint16_t ci)
146 {
147         uint16_t idx = ci & cqes_n;
148         uint8_t op_own = cqe->op_own;
149         uint8_t op_owner = MLX5_CQE_OWNER(op_own);
150         uint8_t op_code = MLX5_CQE_OPCODE(op_own);
151
152         if (unlikely((op_owner != (!!(idx))) || (op_code == MLX5_CQE_INVALID)))
153                 return 1; /* No CQE. */
154 #ifndef NDEBUG
155         if ((op_code == MLX5_CQE_RESP_ERR) ||
156             (op_code == MLX5_CQE_REQ_ERR)) {
157                 volatile struct mlx5_err_cqe *err_cqe = (volatile void *)cqe;
158                 uint8_t syndrome = err_cqe->syndrome;
159
160                 if ((syndrome == MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR) ||
161                     (syndrome == MLX5_CQE_SYNDROME_REMOTE_ABORTED_ERR))
162                         return 0;
163                 if (!check_cqe_seen(cqe))
164                         ERROR("unexpected CQE error %u (0x%02x)"
165                               " syndrome 0x%02x",
166                               op_code, op_code, syndrome);
167                 return 1;
168         } else if ((op_code != MLX5_CQE_RESP_SEND) &&
169                    (op_code != MLX5_CQE_REQ)) {
170                 if (!check_cqe_seen(cqe))
171                         ERROR("unexpected CQE opcode %u (0x%02x)",
172                               op_code, op_code);
173                 return 1;
174         }
175 #endif /* NDEBUG */
176         return 0;
177 }
178
179 /**
180  * Return the address of the WQE.
181  *
182  * @param txq
183  *   Pointer to TX queue structure.
184  * @param  wqe_ci
185  *   WQE consumer index.
186  *
187  * @return
188  *   WQE address.
189  */
190 static inline uintptr_t *
191 tx_mlx5_wqe(struct txq *txq, uint16_t ci)
192 {
193         ci &= ((1 << txq->wqe_n) - 1);
194         return (uintptr_t *)((uintptr_t)txq->wqes + ci * MLX5_WQE_SIZE);
195 }
196
197 /**
198  * Manage TX completions.
199  *
200  * When sending a burst, mlx5_tx_burst() posts several WRs.
201  *
202  * @param txq
203  *   Pointer to TX queue structure.
204  */
205 static inline void
206 txq_complete(struct txq *txq)
207 {
208         const unsigned int elts_n = 1 << txq->elts_n;
209         const unsigned int cqe_n = 1 << txq->cqe_n;
210         const unsigned int cqe_cnt = cqe_n - 1;
211         uint16_t elts_free = txq->elts_tail;
212         uint16_t elts_tail;
213         uint16_t cq_ci = txq->cq_ci;
214         volatile struct mlx5_cqe *cqe = NULL;
215         volatile struct mlx5_wqe_ctrl *ctrl;
216
217         do {
218                 volatile struct mlx5_cqe *tmp;
219
220                 tmp = &(*txq->cqes)[cq_ci & cqe_cnt];
221                 if (check_cqe(tmp, cqe_n, cq_ci))
222                         break;
223                 cqe = tmp;
224 #ifndef NDEBUG
225                 if (MLX5_CQE_FORMAT(cqe->op_own) == MLX5_COMPRESSED) {
226                         if (!check_cqe_seen(cqe))
227                                 ERROR("unexpected compressed CQE, TX stopped");
228                         return;
229                 }
230                 if ((MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_RESP_ERR) ||
231                     (MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_REQ_ERR)) {
232                         if (!check_cqe_seen(cqe))
233                                 ERROR("unexpected error CQE, TX stopped");
234                         return;
235                 }
236 #endif /* NDEBUG */
237                 ++cq_ci;
238         } while (1);
239         if (unlikely(cqe == NULL))
240                 return;
241         txq->wqe_pi = ntohs(cqe->wqe_counter);
242         ctrl = (volatile struct mlx5_wqe_ctrl *)
243                 tx_mlx5_wqe(txq, txq->wqe_pi);
244         elts_tail = ctrl->ctrl3;
245         assert(elts_tail < (1 << txq->wqe_n));
246         /* Free buffers. */
247         while (elts_free != elts_tail) {
248                 struct rte_mbuf *elt = (*txq->elts)[elts_free];
249                 unsigned int elts_free_next =
250                         (elts_free + 1) & (elts_n - 1);
251                 struct rte_mbuf *elt_next = (*txq->elts)[elts_free_next];
252
253 #ifndef NDEBUG
254                 /* Poisoning. */
255                 memset(&(*txq->elts)[elts_free],
256                        0x66,
257                        sizeof((*txq->elts)[elts_free]));
258 #endif
259                 RTE_MBUF_PREFETCH_TO_FREE(elt_next);
260                 /* Only one segment needs to be freed. */
261                 rte_pktmbuf_free_seg(elt);
262                 elts_free = elts_free_next;
263         }
264         txq->cq_ci = cq_ci;
265         txq->elts_tail = elts_tail;
266         /* Update the consumer index. */
267         rte_wmb();
268         *txq->cq_db = htonl(cq_ci);
269 }
270
271 /**
272  * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which
273  * the cloned mbuf is allocated is returned instead.
274  *
275  * @param buf
276  *   Pointer to mbuf.
277  *
278  * @return
279  *   Memory pool where data is located for given mbuf.
280  */
281 static struct rte_mempool *
282 txq_mb2mp(struct rte_mbuf *buf)
283 {
284         if (unlikely(RTE_MBUF_INDIRECT(buf)))
285                 return rte_mbuf_from_indirect(buf)->pool;
286         return buf->pool;
287 }
288
289 /**
290  * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[].
291  * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
292  * remove an entry first.
293  *
294  * @param txq
295  *   Pointer to TX queue structure.
296  * @param[in] mp
297  *   Memory Pool for which a Memory Region lkey must be returned.
298  *
299  * @return
300  *   mr->lkey on success, (uint32_t)-1 on failure.
301  */
302 static inline uint32_t
303 txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
304 {
305         unsigned int i;
306         uint32_t lkey = (uint32_t)-1;
307
308         for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
309                 if (unlikely(txq->mp2mr[i].mp == NULL)) {
310                         /* Unknown MP, add a new MR for it. */
311                         break;
312                 }
313                 if (txq->mp2mr[i].mp == mp) {
314                         assert(txq->mp2mr[i].lkey != (uint32_t)-1);
315                         assert(htonl(txq->mp2mr[i].mr->lkey) ==
316                                txq->mp2mr[i].lkey);
317                         lkey = txq->mp2mr[i].lkey;
318                         break;
319                 }
320         }
321         if (unlikely(lkey == (uint32_t)-1))
322                 lkey = txq_mp2mr_reg(txq, mp, i);
323         return lkey;
324 }
325
326 /**
327  * Ring TX queue doorbell.
328  *
329  * @param txq
330  *   Pointer to TX queue structure.
331  * @param wqe
332  *   Pointer to the last WQE posted in the NIC.
333  */
334 static inline void
335 mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
336 {
337         uint64_t *dst = (uint64_t *)((uintptr_t)txq->bf_reg);
338         volatile uint64_t *src = ((volatile uint64_t *)wqe);
339
340         rte_wmb();
341         *txq->qp_db = htonl(txq->wqe_ci);
342         /* Ensure ordering between DB record and BF copy. */
343         rte_wmb();
344         *dst = *src;
345 }
346
347 /**
348  * DPDK callback to check the status of a tx descriptor.
349  *
350  * @param tx_queue
351  *   The tx queue.
352  * @param[in] offset
353  *   The index of the descriptor in the ring.
354  *
355  * @return
356  *   The status of the tx descriptor.
357  */
358 int
359 mlx5_tx_descriptor_status(void *tx_queue, uint16_t offset)
360 {
361         struct txq *txq = tx_queue;
362         const unsigned int elts_n = 1 << txq->elts_n;
363         const unsigned int elts_cnt = elts_n - 1;
364         unsigned int used;
365
366         txq_complete(txq);
367         used = (txq->elts_head - txq->elts_tail) & elts_cnt;
368         if (offset < used)
369                 return RTE_ETH_TX_DESC_FULL;
370         return RTE_ETH_TX_DESC_DONE;
371 }
372
373 /**
374  * DPDK callback to check the status of a rx descriptor.
375  *
376  * @param rx_queue
377  *   The rx queue.
378  * @param[in] offset
379  *   The index of the descriptor in the ring.
380  *
381  * @return
382  *   The status of the tx descriptor.
383  */
384 int
385 mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
386 {
387         struct rxq *rxq = rx_queue;
388         struct rxq_zip *zip = &rxq->zip;
389         volatile struct mlx5_cqe *cqe;
390         const unsigned int cqe_n = (1 << rxq->cqe_n);
391         const unsigned int cqe_cnt = cqe_n - 1;
392         unsigned int cq_ci;
393         unsigned int used;
394
395         /* if we are processing a compressed cqe */
396         if (zip->ai) {
397                 used = zip->cqe_cnt - zip->ca;
398                 cq_ci = zip->cq_ci;
399         } else {
400                 used = 0;
401                 cq_ci = rxq->cq_ci;
402         }
403         cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
404         while (check_cqe(cqe, cqe_n, cq_ci) == 0) {
405                 int8_t op_own;
406                 unsigned int n;
407
408                 op_own = cqe->op_own;
409                 if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
410                         n = ntohl(cqe->byte_cnt);
411                 else
412                         n = 1;
413                 cq_ci += n;
414                 used += n;
415                 cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
416         }
417         used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
418         if (offset < used)
419                 return RTE_ETH_RX_DESC_DONE;
420         return RTE_ETH_RX_DESC_AVAIL;
421 }
422
423 /**
424  * DPDK callback for TX.
425  *
426  * @param dpdk_txq
427  *   Generic pointer to TX queue structure.
428  * @param[in] pkts
429  *   Packets to transmit.
430  * @param pkts_n
431  *   Number of packets in array.
432  *
433  * @return
434  *   Number of packets successfully transmitted (<= pkts_n).
435  */
436 uint16_t
437 mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
438 {
439         struct txq *txq = (struct txq *)dpdk_txq;
440         uint16_t elts_head = txq->elts_head;
441         const unsigned int elts_n = 1 << txq->elts_n;
442         unsigned int i = 0;
443         unsigned int j = 0;
444         unsigned int max;
445         uint16_t max_wqe;
446         unsigned int comp;
447         volatile struct mlx5_wqe_v *wqe = NULL;
448         unsigned int segs_n = 0;
449         struct rte_mbuf *buf = NULL;
450         uint8_t *raw;
451
452         if (unlikely(!pkts_n))
453                 return 0;
454         /* Prefetch first packet cacheline. */
455         rte_prefetch0(*pkts);
456         /* Start processing. */
457         txq_complete(txq);
458         max = (elts_n - (elts_head - txq->elts_tail));
459         if (max > elts_n)
460                 max -= elts_n;
461         max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi);
462         if (unlikely(!max_wqe))
463                 return 0;
464         do {
465                 volatile rte_v128u32_t *dseg = NULL;
466                 uint32_t length;
467                 unsigned int ds = 0;
468                 uintptr_t addr;
469                 uint64_t naddr;
470                 uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE + 2;
471                 uint16_t ehdr;
472                 uint8_t cs_flags = 0;
473 #ifdef MLX5_PMD_SOFT_COUNTERS
474                 uint32_t total_length = 0;
475 #endif
476
477                 /* first_seg */
478                 buf = *(pkts++);
479                 segs_n = buf->nb_segs;
480                 /*
481                  * Make sure there is enough room to store this packet and
482                  * that one ring entry remains unused.
483                  */
484                 assert(segs_n);
485                 if (max < segs_n + 1)
486                         break;
487                 max -= segs_n;
488                 --segs_n;
489                 if (!segs_n)
490                         --pkts_n;
491                 if (unlikely(--max_wqe == 0))
492                         break;
493                 wqe = (volatile struct mlx5_wqe_v *)
494                         tx_mlx5_wqe(txq, txq->wqe_ci);
495                 rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
496                 if (pkts_n > 1)
497                         rte_prefetch0(*pkts);
498                 addr = rte_pktmbuf_mtod(buf, uintptr_t);
499                 length = DATA_LEN(buf);
500                 ehdr = (((uint8_t *)addr)[1] << 8) |
501                        ((uint8_t *)addr)[0];
502 #ifdef MLX5_PMD_SOFT_COUNTERS
503                 total_length = length;
504 #endif
505                 assert(length >= MLX5_WQE_DWORD_SIZE);
506                 /* Update element. */
507                 (*txq->elts)[elts_head] = buf;
508                 elts_head = (elts_head + 1) & (elts_n - 1);
509                 /* Prefetch next buffer data. */
510                 if (pkts_n > 1) {
511                         volatile void *pkt_addr;
512
513                         pkt_addr = rte_pktmbuf_mtod(*pkts, volatile void *);
514                         rte_prefetch0(pkt_addr);
515                 }
516                 /* Should we enable HW CKSUM offload */
517                 if (buf->ol_flags &
518                     (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {
519                         cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
520                 }
521                 raw = ((uint8_t *)(uintptr_t)wqe) + 2 * MLX5_WQE_DWORD_SIZE;
522                 /* Replace the Ethernet type by the VLAN if necessary. */
523                 if (buf->ol_flags & PKT_TX_VLAN_PKT) {
524                         uint32_t vlan = htonl(0x81000000 | buf->vlan_tci);
525                         unsigned int len = 2 * ETHER_ADDR_LEN - 2;
526
527                         addr += 2;
528                         length -= 2;
529                         /* Copy Destination and source mac address. */
530                         memcpy((uint8_t *)raw, ((uint8_t *)addr), len);
531                         /* Copy VLAN. */
532                         memcpy((uint8_t *)raw + len, &vlan, sizeof(vlan));
533                         /* Copy missing two bytes to end the DSeg. */
534                         memcpy((uint8_t *)raw + len + sizeof(vlan),
535                                ((uint8_t *)addr) + len, 2);
536                         addr += len + 2;
537                         length -= (len + 2);
538                 } else {
539                         memcpy((uint8_t *)raw, ((uint8_t *)addr) + 2,
540                                MLX5_WQE_DWORD_SIZE);
541                         length -= pkt_inline_sz;
542                         addr += pkt_inline_sz;
543                 }
544                 /* Inline if enough room. */
545                 if (txq->max_inline) {
546                         uintptr_t end = (uintptr_t)
547                                 (((uintptr_t)txq->wqes) +
548                                  (1 << txq->wqe_n) * MLX5_WQE_SIZE);
549                         unsigned int max_inline = txq->max_inline *
550                                                   RTE_CACHE_LINE_SIZE -
551                                                   MLX5_WQE_DWORD_SIZE;
552                         uintptr_t addr_end = (addr + max_inline) &
553                                              ~(RTE_CACHE_LINE_SIZE - 1);
554                         unsigned int copy_b = (addr_end > addr) ?
555                                 RTE_MIN((addr_end - addr), length) :
556                                 0;
557
558                         raw += MLX5_WQE_DWORD_SIZE;
559                         if (copy_b && ((end - (uintptr_t)raw) > copy_b)) {
560                                 /*
561                                  * One Dseg remains in the current WQE.  To
562                                  * keep the computation positive, it is
563                                  * removed after the bytes to Dseg conversion.
564                                  */
565                                 uint16_t n = (MLX5_WQE_DS(copy_b) - 1 + 3) / 4;
566
567                                 if (unlikely(max_wqe < n))
568                                         break;
569                                 max_wqe -= n;
570                                 rte_memcpy((void *)raw, (void *)addr, copy_b);
571                                 addr += copy_b;
572                                 length -= copy_b;
573                                 pkt_inline_sz += copy_b;
574                         }
575                         /*
576                          * 2 DWORDs consumed by the WQE header + ETH segment +
577                          * the size of the inline part of the packet.
578                          */
579                         ds = 2 + MLX5_WQE_DS(pkt_inline_sz - 2);
580                         if (length > 0) {
581                                 if (ds % (MLX5_WQE_SIZE /
582                                           MLX5_WQE_DWORD_SIZE) == 0) {
583                                         if (unlikely(--max_wqe == 0))
584                                                 break;
585                                         dseg = (volatile rte_v128u32_t *)
586                                                tx_mlx5_wqe(txq, txq->wqe_ci +
587                                                            ds / 4);
588                                 } else {
589                                         dseg = (volatile rte_v128u32_t *)
590                                                 ((uintptr_t)wqe +
591                                                  (ds * MLX5_WQE_DWORD_SIZE));
592                                 }
593                                 goto use_dseg;
594                         } else if (!segs_n) {
595                                 goto next_pkt;
596                         } else {
597                                 /* dseg will be advance as part of next_seg */
598                                 dseg = (volatile rte_v128u32_t *)
599                                         ((uintptr_t)wqe +
600                                          ((ds - 1) * MLX5_WQE_DWORD_SIZE));
601                                 goto next_seg;
602                         }
603                 } else {
604                         /*
605                          * No inline has been done in the packet, only the
606                          * Ethernet Header as been stored.
607                          */
608                         dseg = (volatile rte_v128u32_t *)
609                                 ((uintptr_t)wqe + (3 * MLX5_WQE_DWORD_SIZE));
610                         ds = 3;
611 use_dseg:
612                         /* Add the remaining packet as a simple ds. */
613                         naddr = htonll(addr);
614                         *dseg = (rte_v128u32_t){
615                                 htonl(length),
616                                 txq_mp2mr(txq, txq_mb2mp(buf)),
617                                 naddr,
618                                 naddr >> 32,
619                         };
620                         ++ds;
621                         if (!segs_n)
622                                 goto next_pkt;
623                 }
624 next_seg:
625                 assert(buf);
626                 assert(ds);
627                 assert(wqe);
628                 /*
629                  * Spill on next WQE when the current one does not have
630                  * enough room left. Size of WQE must a be a multiple
631                  * of data segment size.
632                  */
633                 assert(!(MLX5_WQE_SIZE % MLX5_WQE_DWORD_SIZE));
634                 if (!(ds % (MLX5_WQE_SIZE / MLX5_WQE_DWORD_SIZE))) {
635                         if (unlikely(--max_wqe == 0))
636                                 break;
637                         dseg = (volatile rte_v128u32_t *)
638                                tx_mlx5_wqe(txq, txq->wqe_ci + ds / 4);
639                         rte_prefetch0(tx_mlx5_wqe(txq,
640                                                   txq->wqe_ci + ds / 4 + 1));
641                 } else {
642                         ++dseg;
643                 }
644                 ++ds;
645                 buf = buf->next;
646                 assert(buf);
647                 length = DATA_LEN(buf);
648 #ifdef MLX5_PMD_SOFT_COUNTERS
649                 total_length += length;
650 #endif
651                 /* Store segment information. */
652                 naddr = htonll(rte_pktmbuf_mtod(buf, uintptr_t));
653                 *dseg = (rte_v128u32_t){
654                         htonl(length),
655                         txq_mp2mr(txq, txq_mb2mp(buf)),
656                         naddr,
657                         naddr >> 32,
658                 };
659                 (*txq->elts)[elts_head] = buf;
660                 elts_head = (elts_head + 1) & (elts_n - 1);
661                 ++j;
662                 --segs_n;
663                 if (segs_n)
664                         goto next_seg;
665                 else
666                         --pkts_n;
667 next_pkt:
668                 ++i;
669                 /* Initialize known and common part of the WQE structure. */
670                 wqe->ctrl = (rte_v128u32_t){
671                         htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND),
672                         htonl(txq->qp_num_8s | ds),
673                         0,
674                         0,
675                 };
676                 wqe->eseg = (rte_v128u32_t){
677                         0,
678                         cs_flags,
679                         0,
680                         (ehdr << 16) | htons(pkt_inline_sz),
681                 };
682                 txq->wqe_ci += (ds + 3) / 4;
683 #ifdef MLX5_PMD_SOFT_COUNTERS
684                 /* Increment sent bytes counter. */
685                 txq->stats.obytes += total_length;
686 #endif
687         } while (pkts_n);
688         /* Take a shortcut if nothing must be sent. */
689         if (unlikely(i == 0))
690                 return 0;
691         /* Check whether completion threshold has been reached. */
692         comp = txq->elts_comp + i + j;
693         if (comp >= MLX5_TX_COMP_THRESH) {
694                 volatile struct mlx5_wqe_ctrl *w =
695                         (volatile struct mlx5_wqe_ctrl *)wqe;
696
697                 /* Request completion on last WQE. */
698                 w->ctrl2 = htonl(8);
699                 /* Save elts_head in unused "immediate" field of WQE. */
700                 w->ctrl3 = elts_head;
701                 txq->elts_comp = 0;
702         } else {
703                 txq->elts_comp = comp;
704         }
705 #ifdef MLX5_PMD_SOFT_COUNTERS
706         /* Increment sent packets counter. */
707         txq->stats.opackets += i;
708 #endif
709         /* Ring QP doorbell. */
710         mlx5_tx_dbrec(txq, (volatile struct mlx5_wqe *)wqe);
711         txq->elts_head = elts_head;
712         return i;
713 }
714
715 /**
716  * Open a MPW session.
717  *
718  * @param txq
719  *   Pointer to TX queue structure.
720  * @param mpw
721  *   Pointer to MPW session structure.
722  * @param length
723  *   Packet length.
724  */
725 static inline void
726 mlx5_mpw_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
727 {
728         uint16_t idx = txq->wqe_ci & ((1 << txq->wqe_n) - 1);
729         volatile struct mlx5_wqe_data_seg (*dseg)[MLX5_MPW_DSEG_MAX] =
730                 (volatile struct mlx5_wqe_data_seg (*)[])
731                 tx_mlx5_wqe(txq, idx + 1);
732
733         mpw->state = MLX5_MPW_STATE_OPENED;
734         mpw->pkts_n = 0;
735         mpw->len = length;
736         mpw->total_len = 0;
737         mpw->wqe = (volatile struct mlx5_wqe *)tx_mlx5_wqe(txq, idx);
738         mpw->wqe->eseg.mss = htons(length);
739         mpw->wqe->eseg.inline_hdr_sz = 0;
740         mpw->wqe->eseg.rsvd0 = 0;
741         mpw->wqe->eseg.rsvd1 = 0;
742         mpw->wqe->eseg.rsvd2 = 0;
743         mpw->wqe->ctrl[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
744                                   (txq->wqe_ci << 8) | MLX5_OPCODE_TSO);
745         mpw->wqe->ctrl[2] = 0;
746         mpw->wqe->ctrl[3] = 0;
747         mpw->data.dseg[0] = (volatile struct mlx5_wqe_data_seg *)
748                 (((uintptr_t)mpw->wqe) + (2 * MLX5_WQE_DWORD_SIZE));
749         mpw->data.dseg[1] = (volatile struct mlx5_wqe_data_seg *)
750                 (((uintptr_t)mpw->wqe) + (3 * MLX5_WQE_DWORD_SIZE));
751         mpw->data.dseg[2] = &(*dseg)[0];
752         mpw->data.dseg[3] = &(*dseg)[1];
753         mpw->data.dseg[4] = &(*dseg)[2];
754 }
755
756 /**
757  * Close a MPW session.
758  *
759  * @param txq
760  *   Pointer to TX queue structure.
761  * @param mpw
762  *   Pointer to MPW session structure.
763  */
764 static inline void
765 mlx5_mpw_close(struct txq *txq, struct mlx5_mpw *mpw)
766 {
767         unsigned int num = mpw->pkts_n;
768
769         /*
770          * Store size in multiple of 16 bytes. Control and Ethernet segments
771          * count as 2.
772          */
773         mpw->wqe->ctrl[1] = htonl(txq->qp_num_8s | (2 + num));
774         mpw->state = MLX5_MPW_STATE_CLOSED;
775         if (num < 3)
776                 ++txq->wqe_ci;
777         else
778                 txq->wqe_ci += 2;
779         rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
780         rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
781 }
782
783 /**
784  * DPDK callback for TX with MPW support.
785  *
786  * @param dpdk_txq
787  *   Generic pointer to TX queue structure.
788  * @param[in] pkts
789  *   Packets to transmit.
790  * @param pkts_n
791  *   Number of packets in array.
792  *
793  * @return
794  *   Number of packets successfully transmitted (<= pkts_n).
795  */
796 uint16_t
797 mlx5_tx_burst_mpw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
798 {
799         struct txq *txq = (struct txq *)dpdk_txq;
800         uint16_t elts_head = txq->elts_head;
801         const unsigned int elts_n = 1 << txq->elts_n;
802         unsigned int i = 0;
803         unsigned int j = 0;
804         unsigned int max;
805         uint16_t max_wqe;
806         unsigned int comp;
807         struct mlx5_mpw mpw = {
808                 .state = MLX5_MPW_STATE_CLOSED,
809         };
810
811         if (unlikely(!pkts_n))
812                 return 0;
813         /* Prefetch first packet cacheline. */
814         rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
815         rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
816         /* Start processing. */
817         txq_complete(txq);
818         max = (elts_n - (elts_head - txq->elts_tail));
819         if (max > elts_n)
820                 max -= elts_n;
821         max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi);
822         if (unlikely(!max_wqe))
823                 return 0;
824         do {
825                 struct rte_mbuf *buf = *(pkts++);
826                 unsigned int elts_head_next;
827                 uint32_t length;
828                 unsigned int segs_n = buf->nb_segs;
829                 uint32_t cs_flags = 0;
830
831                 /*
832                  * Make sure there is enough room to store this packet and
833                  * that one ring entry remains unused.
834                  */
835                 assert(segs_n);
836                 if (max < segs_n + 1)
837                         break;
838                 /* Do not bother with large packets MPW cannot handle. */
839                 if (segs_n > MLX5_MPW_DSEG_MAX)
840                         break;
841                 max -= segs_n;
842                 --pkts_n;
843                 /* Should we enable HW CKSUM offload */
844                 if (buf->ol_flags &
845                     (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))
846                         cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
847                 /* Retrieve packet information. */
848                 length = PKT_LEN(buf);
849                 assert(length);
850                 /* Start new session if packet differs. */
851                 if ((mpw.state == MLX5_MPW_STATE_OPENED) &&
852                     ((mpw.len != length) ||
853                      (segs_n != 1) ||
854                      (mpw.wqe->eseg.cs_flags != cs_flags)))
855                         mlx5_mpw_close(txq, &mpw);
856                 if (mpw.state == MLX5_MPW_STATE_CLOSED) {
857                         /*
858                          * Multi-Packet WQE consumes at most two WQE.
859                          * mlx5_mpw_new() expects to be able to use such
860                          * resources.
861                          */
862                         if (unlikely(max_wqe < 2))
863                                 break;
864                         max_wqe -= 2;
865                         mlx5_mpw_new(txq, &mpw, length);
866                         mpw.wqe->eseg.cs_flags = cs_flags;
867                 }
868                 /* Multi-segment packets must be alone in their MPW. */
869                 assert((segs_n == 1) || (mpw.pkts_n == 0));
870 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
871                 length = 0;
872 #endif
873                 do {
874                         volatile struct mlx5_wqe_data_seg *dseg;
875                         uintptr_t addr;
876
877                         elts_head_next = (elts_head + 1) & (elts_n - 1);
878                         assert(buf);
879                         (*txq->elts)[elts_head] = buf;
880                         dseg = mpw.data.dseg[mpw.pkts_n];
881                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
882                         *dseg = (struct mlx5_wqe_data_seg){
883                                 .byte_count = htonl(DATA_LEN(buf)),
884                                 .lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
885                                 .addr = htonll(addr),
886                         };
887                         elts_head = elts_head_next;
888 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
889                         length += DATA_LEN(buf);
890 #endif
891                         buf = buf->next;
892                         ++mpw.pkts_n;
893                         ++j;
894                 } while (--segs_n);
895                 assert(length == mpw.len);
896                 if (mpw.pkts_n == MLX5_MPW_DSEG_MAX)
897                         mlx5_mpw_close(txq, &mpw);
898                 elts_head = elts_head_next;
899 #ifdef MLX5_PMD_SOFT_COUNTERS
900                 /* Increment sent bytes counter. */
901                 txq->stats.obytes += length;
902 #endif
903                 ++i;
904         } while (pkts_n);
905         /* Take a shortcut if nothing must be sent. */
906         if (unlikely(i == 0))
907                 return 0;
908         /* Check whether completion threshold has been reached. */
909         /* "j" includes both packets and segments. */
910         comp = txq->elts_comp + j;
911         if (comp >= MLX5_TX_COMP_THRESH) {
912                 volatile struct mlx5_wqe *wqe = mpw.wqe;
913
914                 /* Request completion on last WQE. */
915                 wqe->ctrl[2] = htonl(8);
916                 /* Save elts_head in unused "immediate" field of WQE. */
917                 wqe->ctrl[3] = elts_head;
918                 txq->elts_comp = 0;
919         } else {
920                 txq->elts_comp = comp;
921         }
922 #ifdef MLX5_PMD_SOFT_COUNTERS
923         /* Increment sent packets counter. */
924         txq->stats.opackets += i;
925 #endif
926         /* Ring QP doorbell. */
927         if (mpw.state == MLX5_MPW_STATE_OPENED)
928                 mlx5_mpw_close(txq, &mpw);
929         mlx5_tx_dbrec(txq, mpw.wqe);
930         txq->elts_head = elts_head;
931         return i;
932 }
933
934 /**
935  * Open a MPW inline session.
936  *
937  * @param txq
938  *   Pointer to TX queue structure.
939  * @param mpw
940  *   Pointer to MPW session structure.
941  * @param length
942  *   Packet length.
943  */
944 static inline void
945 mlx5_mpw_inline_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
946 {
947         uint16_t idx = txq->wqe_ci & ((1 << txq->wqe_n) - 1);
948         struct mlx5_wqe_inl_small *inl;
949
950         mpw->state = MLX5_MPW_INL_STATE_OPENED;
951         mpw->pkts_n = 0;
952         mpw->len = length;
953         mpw->total_len = 0;
954         mpw->wqe = (volatile struct mlx5_wqe *)tx_mlx5_wqe(txq, idx);
955         mpw->wqe->ctrl[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
956                                   (txq->wqe_ci << 8) |
957                                   MLX5_OPCODE_TSO);
958         mpw->wqe->ctrl[2] = 0;
959         mpw->wqe->ctrl[3] = 0;
960         mpw->wqe->eseg.mss = htons(length);
961         mpw->wqe->eseg.inline_hdr_sz = 0;
962         mpw->wqe->eseg.cs_flags = 0;
963         mpw->wqe->eseg.rsvd0 = 0;
964         mpw->wqe->eseg.rsvd1 = 0;
965         mpw->wqe->eseg.rsvd2 = 0;
966         inl = (struct mlx5_wqe_inl_small *)
967                 (((uintptr_t)mpw->wqe) + 2 * MLX5_WQE_DWORD_SIZE);
968         mpw->data.raw = (uint8_t *)&inl->raw;
969 }
970
971 /**
972  * Close a MPW inline session.
973  *
974  * @param txq
975  *   Pointer to TX queue structure.
976  * @param mpw
977  *   Pointer to MPW session structure.
978  */
979 static inline void
980 mlx5_mpw_inline_close(struct txq *txq, struct mlx5_mpw *mpw)
981 {
982         unsigned int size;
983         struct mlx5_wqe_inl_small *inl = (struct mlx5_wqe_inl_small *)
984                 (((uintptr_t)mpw->wqe) + (2 * MLX5_WQE_DWORD_SIZE));
985
986         size = MLX5_WQE_SIZE - MLX5_MWQE64_INL_DATA + mpw->total_len;
987         /*
988          * Store size in multiple of 16 bytes. Control and Ethernet segments
989          * count as 2.
990          */
991         mpw->wqe->ctrl[1] = htonl(txq->qp_num_8s | MLX5_WQE_DS(size));
992         mpw->state = MLX5_MPW_STATE_CLOSED;
993         inl->byte_cnt = htonl(mpw->total_len | MLX5_INLINE_SEG);
994         txq->wqe_ci += (size + (MLX5_WQE_SIZE - 1)) / MLX5_WQE_SIZE;
995 }
996
997 /**
998  * DPDK callback for TX with MPW inline support.
999  *
1000  * @param dpdk_txq
1001  *   Generic pointer to TX queue structure.
1002  * @param[in] pkts
1003  *   Packets to transmit.
1004  * @param pkts_n
1005  *   Number of packets in array.
1006  *
1007  * @return
1008  *   Number of packets successfully transmitted (<= pkts_n).
1009  */
1010 uint16_t
1011 mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
1012                          uint16_t pkts_n)
1013 {
1014         struct txq *txq = (struct txq *)dpdk_txq;
1015         uint16_t elts_head = txq->elts_head;
1016         const unsigned int elts_n = 1 << txq->elts_n;
1017         unsigned int i = 0;
1018         unsigned int j = 0;
1019         unsigned int max;
1020         uint16_t max_wqe;
1021         unsigned int comp;
1022         unsigned int inline_room = txq->max_inline * RTE_CACHE_LINE_SIZE;
1023         struct mlx5_mpw mpw = {
1024                 .state = MLX5_MPW_STATE_CLOSED,
1025         };
1026         /*
1027          * Compute the maximum number of WQE which can be consumed by inline
1028          * code.
1029          * - 2 DSEG for:
1030          *   - 1 control segment,
1031          *   - 1 Ethernet segment,
1032          * - N Dseg from the inline request.
1033          */
1034         const unsigned int wqe_inl_n =
1035                 ((2 * MLX5_WQE_DWORD_SIZE +
1036                   txq->max_inline * RTE_CACHE_LINE_SIZE) +
1037                  RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE;
1038
1039         if (unlikely(!pkts_n))
1040                 return 0;
1041         /* Prefetch first packet cacheline. */
1042         rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
1043         rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
1044         /* Start processing. */
1045         txq_complete(txq);
1046         max = (elts_n - (elts_head - txq->elts_tail));
1047         if (max > elts_n)
1048                 max -= elts_n;
1049         do {
1050                 struct rte_mbuf *buf = *(pkts++);
1051                 unsigned int elts_head_next;
1052                 uintptr_t addr;
1053                 uint32_t length;
1054                 unsigned int segs_n = buf->nb_segs;
1055                 uint32_t cs_flags = 0;
1056
1057                 /*
1058                  * Make sure there is enough room to store this packet and
1059                  * that one ring entry remains unused.
1060                  */
1061                 assert(segs_n);
1062                 if (max < segs_n + 1)
1063                         break;
1064                 /* Do not bother with large packets MPW cannot handle. */
1065                 if (segs_n > MLX5_MPW_DSEG_MAX)
1066                         break;
1067                 max -= segs_n;
1068                 --pkts_n;
1069                 /*
1070                  * Compute max_wqe in case less WQE were consumed in previous
1071                  * iteration.
1072                  */
1073                 max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi);
1074                 /* Should we enable HW CKSUM offload */
1075                 if (buf->ol_flags &
1076                     (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))
1077                         cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
1078                 /* Retrieve packet information. */
1079                 length = PKT_LEN(buf);
1080                 /* Start new session if packet differs. */
1081                 if (mpw.state == MLX5_MPW_STATE_OPENED) {
1082                         if ((mpw.len != length) ||
1083                             (segs_n != 1) ||
1084                             (mpw.wqe->eseg.cs_flags != cs_flags))
1085                                 mlx5_mpw_close(txq, &mpw);
1086                 } else if (mpw.state == MLX5_MPW_INL_STATE_OPENED) {
1087                         if ((mpw.len != length) ||
1088                             (segs_n != 1) ||
1089                             (length > inline_room) ||
1090                             (mpw.wqe->eseg.cs_flags != cs_flags)) {
1091                                 mlx5_mpw_inline_close(txq, &mpw);
1092                                 inline_room =
1093                                         txq->max_inline * RTE_CACHE_LINE_SIZE;
1094                         }
1095                 }
1096                 if (mpw.state == MLX5_MPW_STATE_CLOSED) {
1097                         if ((segs_n != 1) ||
1098                             (length > inline_room)) {
1099                                 /*
1100                                  * Multi-Packet WQE consumes at most two WQE.
1101                                  * mlx5_mpw_new() expects to be able to use
1102                                  * such resources.
1103                                  */
1104                                 if (unlikely(max_wqe < 2))
1105                                         break;
1106                                 max_wqe -= 2;
1107                                 mlx5_mpw_new(txq, &mpw, length);
1108                                 mpw.wqe->eseg.cs_flags = cs_flags;
1109                         } else {
1110                                 if (unlikely(max_wqe < wqe_inl_n))
1111                                         break;
1112                                 max_wqe -= wqe_inl_n;
1113                                 mlx5_mpw_inline_new(txq, &mpw, length);
1114                                 mpw.wqe->eseg.cs_flags = cs_flags;
1115                         }
1116                 }
1117                 /* Multi-segment packets must be alone in their MPW. */
1118                 assert((segs_n == 1) || (mpw.pkts_n == 0));
1119                 if (mpw.state == MLX5_MPW_STATE_OPENED) {
1120                         assert(inline_room ==
1121                                txq->max_inline * RTE_CACHE_LINE_SIZE);
1122 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
1123                         length = 0;
1124 #endif
1125                         do {
1126                                 volatile struct mlx5_wqe_data_seg *dseg;
1127
1128                                 elts_head_next =
1129                                         (elts_head + 1) & (elts_n - 1);
1130                                 assert(buf);
1131                                 (*txq->elts)[elts_head] = buf;
1132                                 dseg = mpw.data.dseg[mpw.pkts_n];
1133                                 addr = rte_pktmbuf_mtod(buf, uintptr_t);
1134                                 *dseg = (struct mlx5_wqe_data_seg){
1135                                         .byte_count = htonl(DATA_LEN(buf)),
1136                                         .lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
1137                                         .addr = htonll(addr),
1138                                 };
1139                                 elts_head = elts_head_next;
1140 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
1141                                 length += DATA_LEN(buf);
1142 #endif
1143                                 buf = buf->next;
1144                                 ++mpw.pkts_n;
1145                                 ++j;
1146                         } while (--segs_n);
1147                         assert(length == mpw.len);
1148                         if (mpw.pkts_n == MLX5_MPW_DSEG_MAX)
1149                                 mlx5_mpw_close(txq, &mpw);
1150                 } else {
1151                         unsigned int max;
1152
1153                         assert(mpw.state == MLX5_MPW_INL_STATE_OPENED);
1154                         assert(length <= inline_room);
1155                         assert(length == DATA_LEN(buf));
1156                         elts_head_next = (elts_head + 1) & (elts_n - 1);
1157                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
1158                         (*txq->elts)[elts_head] = buf;
1159                         /* Maximum number of bytes before wrapping. */
1160                         max = ((((uintptr_t)(txq->wqes)) +
1161                                 (1 << txq->wqe_n) *
1162                                 MLX5_WQE_SIZE) -
1163                                (uintptr_t)mpw.data.raw);
1164                         if (length > max) {
1165                                 rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1166                                            (void *)addr,
1167                                            max);
1168                                 mpw.data.raw = (volatile void *)txq->wqes;
1169                                 rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1170                                            (void *)(addr + max),
1171                                            length - max);
1172                                 mpw.data.raw += length - max;
1173                         } else {
1174                                 rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1175                                            (void *)addr,
1176                                            length);
1177
1178                                 if (length == max)
1179                                         mpw.data.raw =
1180                                                 (volatile void *)txq->wqes;
1181                                 else
1182                                         mpw.data.raw += length;
1183                         }
1184                         ++mpw.pkts_n;
1185                         mpw.total_len += length;
1186                         ++j;
1187                         if (mpw.pkts_n == MLX5_MPW_DSEG_MAX) {
1188                                 mlx5_mpw_inline_close(txq, &mpw);
1189                                 inline_room =
1190                                         txq->max_inline * RTE_CACHE_LINE_SIZE;
1191                         } else {
1192                                 inline_room -= length;
1193                         }
1194                 }
1195                 elts_head = elts_head_next;
1196 #ifdef MLX5_PMD_SOFT_COUNTERS
1197                 /* Increment sent bytes counter. */
1198                 txq->stats.obytes += length;
1199 #endif
1200                 ++i;
1201         } while (pkts_n);
1202         /* Take a shortcut if nothing must be sent. */
1203         if (unlikely(i == 0))
1204                 return 0;
1205         /* Check whether completion threshold has been reached. */
1206         /* "j" includes both packets and segments. */
1207         comp = txq->elts_comp + j;
1208         if (comp >= MLX5_TX_COMP_THRESH) {
1209                 volatile struct mlx5_wqe *wqe = mpw.wqe;
1210
1211                 /* Request completion on last WQE. */
1212                 wqe->ctrl[2] = htonl(8);
1213                 /* Save elts_head in unused "immediate" field of WQE. */
1214                 wqe->ctrl[3] = elts_head;
1215                 txq->elts_comp = 0;
1216         } else {
1217                 txq->elts_comp = comp;
1218         }
1219 #ifdef MLX5_PMD_SOFT_COUNTERS
1220         /* Increment sent packets counter. */
1221         txq->stats.opackets += i;
1222 #endif
1223         /* Ring QP doorbell. */
1224         if (mpw.state == MLX5_MPW_INL_STATE_OPENED)
1225                 mlx5_mpw_inline_close(txq, &mpw);
1226         else if (mpw.state == MLX5_MPW_STATE_OPENED)
1227                 mlx5_mpw_close(txq, &mpw);
1228         mlx5_tx_dbrec(txq, mpw.wqe);
1229         txq->elts_head = elts_head;
1230         return i;
1231 }
1232
1233 /**
1234  * Translate RX completion flags to packet type.
1235  *
1236  * @param[in] cqe
1237  *   Pointer to CQE.
1238  *
1239  * @note: fix mlx5_dev_supported_ptypes_get() if any change here.
1240  *
1241  * @return
1242  *   Packet type for struct rte_mbuf.
1243  */
1244 static inline uint32_t
1245 rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe)
1246 {
1247         uint32_t pkt_type;
1248         uint16_t flags = ntohs(cqe->hdr_type_etc);
1249
1250         if (cqe->pkt_info & MLX5_CQE_RX_TUNNEL_PACKET) {
1251                 pkt_type =
1252                         TRANSPOSE(flags,
1253                                   MLX5_CQE_RX_IPV4_PACKET,
1254                                   RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN) |
1255                         TRANSPOSE(flags,
1256                                   MLX5_CQE_RX_IPV6_PACKET,
1257                                   RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN);
1258                 pkt_type |= ((cqe->pkt_info & MLX5_CQE_RX_OUTER_PACKET) ?
1259                              RTE_PTYPE_L3_IPV6_EXT_UNKNOWN :
1260                              RTE_PTYPE_L3_IPV4_EXT_UNKNOWN);
1261         } else {
1262                 pkt_type =
1263                         TRANSPOSE(flags,
1264                                   MLX5_CQE_L3_HDR_TYPE_IPV6,
1265                                   RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) |
1266                         TRANSPOSE(flags,
1267                                   MLX5_CQE_L3_HDR_TYPE_IPV4,
1268                                   RTE_PTYPE_L3_IPV4_EXT_UNKNOWN);
1269         }
1270         return pkt_type;
1271 }
1272
1273 /**
1274  * Get size of the next packet for a given CQE. For compressed CQEs, the
1275  * consumer index is updated only once all packets of the current one have
1276  * been processed.
1277  *
1278  * @param rxq
1279  *   Pointer to RX queue.
1280  * @param cqe
1281  *   CQE to process.
1282  * @param[out] rss_hash
1283  *   Packet RSS Hash result.
1284  *
1285  * @return
1286  *   Packet size in bytes (0 if there is none), -1 in case of completion
1287  *   with error.
1288  */
1289 static inline int
1290 mlx5_rx_poll_len(struct rxq *rxq, volatile struct mlx5_cqe *cqe,
1291                  uint16_t cqe_cnt, uint32_t *rss_hash)
1292 {
1293         struct rxq_zip *zip = &rxq->zip;
1294         uint16_t cqe_n = cqe_cnt + 1;
1295         int len = 0;
1296         uint16_t idx, end;
1297
1298         /* Process compressed data in the CQE and mini arrays. */
1299         if (zip->ai) {
1300                 volatile struct mlx5_mini_cqe8 (*mc)[8] =
1301                         (volatile struct mlx5_mini_cqe8 (*)[8])
1302                         (uintptr_t)(&(*rxq->cqes)[zip->ca & cqe_cnt]);
1303
1304                 len = ntohl((*mc)[zip->ai & 7].byte_cnt);
1305                 *rss_hash = ntohl((*mc)[zip->ai & 7].rx_hash_result);
1306                 if ((++zip->ai & 7) == 0) {
1307                         /* Invalidate consumed CQEs */
1308                         idx = zip->ca;
1309                         end = zip->na;
1310                         while (idx != end) {
1311                                 (*rxq->cqes)[idx & cqe_cnt].op_own =
1312                                         MLX5_CQE_INVALIDATE;
1313                                 ++idx;
1314                         }
1315                         /*
1316                          * Increment consumer index to skip the number of
1317                          * CQEs consumed. Hardware leaves holes in the CQ
1318                          * ring for software use.
1319                          */
1320                         zip->ca = zip->na;
1321                         zip->na += 8;
1322                 }
1323                 if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
1324                         /* Invalidate the rest */
1325                         idx = zip->ca;
1326                         end = zip->cq_ci;
1327
1328                         while (idx != end) {
1329                                 (*rxq->cqes)[idx & cqe_cnt].op_own =
1330                                         MLX5_CQE_INVALIDATE;
1331                                 ++idx;
1332                         }
1333                         rxq->cq_ci = zip->cq_ci;
1334                         zip->ai = 0;
1335                 }
1336         /* No compressed data, get next CQE and verify if it is compressed. */
1337         } else {
1338                 int ret;
1339                 int8_t op_own;
1340
1341                 ret = check_cqe(cqe, cqe_n, rxq->cq_ci);
1342                 if (unlikely(ret == 1))
1343                         return 0;
1344                 ++rxq->cq_ci;
1345                 op_own = cqe->op_own;
1346                 if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
1347                         volatile struct mlx5_mini_cqe8 (*mc)[8] =
1348                                 (volatile struct mlx5_mini_cqe8 (*)[8])
1349                                 (uintptr_t)(&(*rxq->cqes)[rxq->cq_ci &
1350                                                           cqe_cnt]);
1351
1352                         /* Fix endianness. */
1353                         zip->cqe_cnt = ntohl(cqe->byte_cnt);
1354                         /*
1355                          * Current mini array position is the one returned by
1356                          * check_cqe64().
1357                          *
1358                          * If completion comprises several mini arrays, as a
1359                          * special case the second one is located 7 CQEs after
1360                          * the initial CQE instead of 8 for subsequent ones.
1361                          */
1362                         zip->ca = rxq->cq_ci;
1363                         zip->na = zip->ca + 7;
1364                         /* Compute the next non compressed CQE. */
1365                         --rxq->cq_ci;
1366                         zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
1367                         /* Get packet size to return. */
1368                         len = ntohl((*mc)[0].byte_cnt);
1369                         *rss_hash = ntohl((*mc)[0].rx_hash_result);
1370                         zip->ai = 1;
1371                         /* Prefetch all the entries to be invalidated */
1372                         idx = zip->ca;
1373                         end = zip->cq_ci;
1374                         while (idx != end) {
1375                                 rte_prefetch0(&(*rxq->cqes)[(idx) & cqe_cnt]);
1376                                 ++idx;
1377                         }
1378                 } else {
1379                         len = ntohl(cqe->byte_cnt);
1380                         *rss_hash = ntohl(cqe->rx_hash_res);
1381                 }
1382                 /* Error while receiving packet. */
1383                 if (unlikely(MLX5_CQE_OPCODE(op_own) == MLX5_CQE_RESP_ERR))
1384                         return -1;
1385         }
1386         return len;
1387 }
1388
1389 /**
1390  * Translate RX completion flags to offload flags.
1391  *
1392  * @param[in] rxq
1393  *   Pointer to RX queue structure.
1394  * @param[in] cqe
1395  *   Pointer to CQE.
1396  *
1397  * @return
1398  *   Offload flags (ol_flags) for struct rte_mbuf.
1399  */
1400 static inline uint32_t
1401 rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe *cqe)
1402 {
1403         uint32_t ol_flags = 0;
1404         uint16_t flags = ntohs(cqe->hdr_type_etc);
1405
1406         ol_flags =
1407                 TRANSPOSE(flags,
1408                           MLX5_CQE_RX_L3_HDR_VALID,
1409                           PKT_RX_IP_CKSUM_GOOD) |
1410                 TRANSPOSE(flags,
1411                           MLX5_CQE_RX_L4_HDR_VALID,
1412                           PKT_RX_L4_CKSUM_GOOD);
1413         if ((cqe->pkt_info & MLX5_CQE_RX_TUNNEL_PACKET) && (rxq->csum_l2tun))
1414                 ol_flags |=
1415                         TRANSPOSE(flags,
1416                                   MLX5_CQE_RX_L3_HDR_VALID,
1417                                   PKT_RX_IP_CKSUM_GOOD) |
1418                         TRANSPOSE(flags,
1419                                   MLX5_CQE_RX_L4_HDR_VALID,
1420                                   PKT_RX_L4_CKSUM_GOOD);
1421         return ol_flags;
1422 }
1423
1424 /**
1425  * DPDK callback for RX.
1426  *
1427  * @param dpdk_rxq
1428  *   Generic pointer to RX queue structure.
1429  * @param[out] pkts
1430  *   Array to store received packets.
1431  * @param pkts_n
1432  *   Maximum number of packets in array.
1433  *
1434  * @return
1435  *   Number of packets successfully received (<= pkts_n).
1436  */
1437 uint16_t
1438 mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1439 {
1440         struct rxq *rxq = dpdk_rxq;
1441         const unsigned int wqe_cnt = (1 << rxq->elts_n) - 1;
1442         const unsigned int cqe_cnt = (1 << rxq->cqe_n) - 1;
1443         const unsigned int sges_n = rxq->sges_n;
1444         struct rte_mbuf *pkt = NULL;
1445         struct rte_mbuf *seg = NULL;
1446         volatile struct mlx5_cqe *cqe =
1447                 &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
1448         unsigned int i = 0;
1449         unsigned int rq_ci = rxq->rq_ci << sges_n;
1450         int len; /* keep its value across iterations. */
1451
1452         while (pkts_n) {
1453                 unsigned int idx = rq_ci & wqe_cnt;
1454                 volatile struct mlx5_wqe_data_seg *wqe = &(*rxq->wqes)[idx];
1455                 struct rte_mbuf *rep = (*rxq->elts)[idx];
1456                 uint32_t rss_hash_res = 0;
1457
1458                 if (pkt)
1459                         NEXT(seg) = rep;
1460                 seg = rep;
1461                 rte_prefetch0(seg);
1462                 rte_prefetch0(cqe);
1463                 rte_prefetch0(wqe);
1464                 rep = rte_mbuf_raw_alloc(rxq->mp);
1465                 if (unlikely(rep == NULL)) {
1466                         ++rxq->stats.rx_nombuf;
1467                         if (!pkt) {
1468                                 /*
1469                                  * no buffers before we even started,
1470                                  * bail out silently.
1471                                  */
1472                                 break;
1473                         }
1474                         while (pkt != seg) {
1475                                 assert(pkt != (*rxq->elts)[idx]);
1476                                 rep = NEXT(pkt);
1477                                 rte_mbuf_refcnt_set(pkt, 0);
1478                                 __rte_mbuf_raw_free(pkt);
1479                                 pkt = rep;
1480                         }
1481                         break;
1482                 }
1483                 if (!pkt) {
1484                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
1485                         len = mlx5_rx_poll_len(rxq, cqe, cqe_cnt,
1486                                                &rss_hash_res);
1487                         if (!len) {
1488                                 rte_mbuf_refcnt_set(rep, 0);
1489                                 __rte_mbuf_raw_free(rep);
1490                                 break;
1491                         }
1492                         if (unlikely(len == -1)) {
1493                                 /* RX error, packet is likely too large. */
1494                                 rte_mbuf_refcnt_set(rep, 0);
1495                                 __rte_mbuf_raw_free(rep);
1496                                 ++rxq->stats.idropped;
1497                                 goto skip;
1498                         }
1499                         pkt = seg;
1500                         assert(len >= (rxq->crc_present << 2));
1501                         /* Update packet information. */
1502                         pkt->packet_type = 0;
1503                         pkt->ol_flags = 0;
1504                         if (rss_hash_res && rxq->rss_hash) {
1505                                 pkt->hash.rss = rss_hash_res;
1506                                 pkt->ol_flags = PKT_RX_RSS_HASH;
1507                         }
1508                         if (rxq->mark &&
1509                             ((cqe->sop_drop_qpn !=
1510                               htonl(MLX5_FLOW_MARK_INVALID)) &&
1511                              (cqe->sop_drop_qpn !=
1512                               htonl(MLX5_FLOW_MARK_DEFAULT)))) {
1513                                 pkt->hash.fdir.hi =
1514                                         mlx5_flow_mark_get(cqe->sop_drop_qpn);
1515                                 pkt->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
1516                         }
1517                         if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip |
1518                             rxq->crc_present) {
1519                                 if (rxq->csum) {
1520                                         pkt->packet_type =
1521                                                 rxq_cq_to_pkt_type(cqe);
1522                                         pkt->ol_flags |=
1523                                                 rxq_cq_to_ol_flags(rxq, cqe);
1524                                 }
1525                                 if (ntohs(cqe->hdr_type_etc) &
1526                                     MLX5_CQE_VLAN_STRIPPED) {
1527                                         pkt->ol_flags |= PKT_RX_VLAN_PKT |
1528                                                 PKT_RX_VLAN_STRIPPED;
1529                                         pkt->vlan_tci = ntohs(cqe->vlan_info);
1530                                 }
1531                                 if (rxq->crc_present)
1532                                         len -= ETHER_CRC_LEN;
1533                         }
1534                         PKT_LEN(pkt) = len;
1535                 }
1536                 DATA_LEN(rep) = DATA_LEN(seg);
1537                 PKT_LEN(rep) = PKT_LEN(seg);
1538                 SET_DATA_OFF(rep, DATA_OFF(seg));
1539                 NB_SEGS(rep) = NB_SEGS(seg);
1540                 PORT(rep) = PORT(seg);
1541                 NEXT(rep) = NULL;
1542                 (*rxq->elts)[idx] = rep;
1543                 /*
1544                  * Fill NIC descriptor with the new buffer.  The lkey and size
1545                  * of the buffers are already known, only the buffer address
1546                  * changes.
1547                  */
1548                 wqe->addr = htonll(rte_pktmbuf_mtod(rep, uintptr_t));
1549                 if (len > DATA_LEN(seg)) {
1550                         len -= DATA_LEN(seg);
1551                         ++NB_SEGS(pkt);
1552                         ++rq_ci;
1553                         continue;
1554                 }
1555                 DATA_LEN(seg) = len;
1556 #ifdef MLX5_PMD_SOFT_COUNTERS
1557                 /* Increment bytes counter. */
1558                 rxq->stats.ibytes += PKT_LEN(pkt);
1559 #endif
1560                 /* Return packet. */
1561                 *(pkts++) = pkt;
1562                 pkt = NULL;
1563                 --pkts_n;
1564                 ++i;
1565 skip:
1566                 /* Align consumer index to the next stride. */
1567                 rq_ci >>= sges_n;
1568                 ++rq_ci;
1569                 rq_ci <<= sges_n;
1570         }
1571         if (unlikely((i == 0) && ((rq_ci >> sges_n) == rxq->rq_ci)))
1572                 return 0;
1573         /* Update the consumer index. */
1574         rxq->rq_ci = rq_ci >> sges_n;
1575         rte_wmb();
1576         *rxq->cq_db = htonl(rxq->cq_ci);
1577         rte_wmb();
1578         *rxq->rq_db = htonl(rxq->rq_ci);
1579 #ifdef MLX5_PMD_SOFT_COUNTERS
1580         /* Increment packets counter. */
1581         rxq->stats.ipackets += i;
1582 #endif
1583         return i;
1584 }
1585
1586 /**
1587  * Dummy DPDK callback for TX.
1588  *
1589  * This function is used to temporarily replace the real callback during
1590  * unsafe control operations on the queue, or in case of error.
1591  *
1592  * @param dpdk_txq
1593  *   Generic pointer to TX queue structure.
1594  * @param[in] pkts
1595  *   Packets to transmit.
1596  * @param pkts_n
1597  *   Number of packets in array.
1598  *
1599  * @return
1600  *   Number of packets successfully transmitted (<= pkts_n).
1601  */
1602 uint16_t
1603 removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
1604 {
1605         (void)dpdk_txq;
1606         (void)pkts;
1607         (void)pkts_n;
1608         return 0;
1609 }
1610
1611 /**
1612  * Dummy DPDK callback for RX.
1613  *
1614  * This function is used to temporarily replace the real callback during
1615  * unsafe control operations on the queue, or in case of error.
1616  *
1617  * @param dpdk_rxq
1618  *   Generic pointer to RX queue structure.
1619  * @param[out] pkts
1620  *   Array to store received packets.
1621  * @param pkts_n
1622  *   Maximum number of packets in array.
1623  *
1624  * @return
1625  *   Number of packets successfully received (<= pkts_n).
1626  */
1627 uint16_t
1628 removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1629 {
1630         (void)dpdk_rxq;
1631         (void)pkts;
1632         (void)pkts_n;
1633         return 0;
1634 }