Imported Upstream version 16.07.2
[deb_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 #ifndef NDEBUG
73
74 /**
75  * Verify or set magic value in CQE.
76  *
77  * @param cqe
78  *   Pointer to CQE.
79  *
80  * @return
81  *   0 the first time.
82  */
83 static inline int
84 check_cqe64_seen(volatile struct mlx5_cqe64 *cqe)
85 {
86         static const uint8_t magic[] = "seen";
87         volatile uint8_t (*buf)[sizeof(cqe->rsvd40)] = &cqe->rsvd40;
88         int ret = 1;
89         unsigned int i;
90
91         for (i = 0; i < sizeof(magic) && i < sizeof(*buf); ++i)
92                 if (!ret || (*buf)[i] != magic[i]) {
93                         ret = 0;
94                         (*buf)[i] = magic[i];
95                 }
96         return ret;
97 }
98
99 #endif /* NDEBUG */
100
101 static inline int
102 check_cqe64(volatile struct mlx5_cqe64 *cqe,
103             unsigned int cqes_n, const uint16_t ci)
104             __attribute__((always_inline));
105
106 /**
107  * Check whether CQE is valid.
108  *
109  * @param cqe
110  *   Pointer to CQE.
111  * @param cqes_n
112  *   Size of completion queue.
113  * @param ci
114  *   Consumer index.
115  *
116  * @return
117  *   0 on success, 1 on failure.
118  */
119 static inline int
120 check_cqe64(volatile struct mlx5_cqe64 *cqe,
121                 unsigned int cqes_n, const uint16_t ci)
122 {
123         uint16_t idx = ci & cqes_n;
124         uint8_t op_own = cqe->op_own;
125         uint8_t op_owner = MLX5_CQE_OWNER(op_own);
126         uint8_t op_code = MLX5_CQE_OPCODE(op_own);
127
128         if (unlikely((op_owner != (!!(idx))) || (op_code == MLX5_CQE_INVALID)))
129                 return 1; /* No CQE. */
130 #ifndef NDEBUG
131         if ((op_code == MLX5_CQE_RESP_ERR) ||
132             (op_code == MLX5_CQE_REQ_ERR)) {
133                 volatile struct mlx5_err_cqe *err_cqe = (volatile void *)cqe;
134                 uint8_t syndrome = err_cqe->syndrome;
135
136                 if ((syndrome == MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR) ||
137                     (syndrome == MLX5_CQE_SYNDROME_REMOTE_ABORTED_ERR))
138                         return 0;
139                 if (!check_cqe64_seen(cqe))
140                         ERROR("unexpected CQE error %u (0x%02x)"
141                               " syndrome 0x%02x",
142                               op_code, op_code, syndrome);
143                 return 1;
144         } else if ((op_code != MLX5_CQE_RESP_SEND) &&
145                    (op_code != MLX5_CQE_REQ)) {
146                 if (!check_cqe64_seen(cqe))
147                         ERROR("unexpected CQE opcode %u (0x%02x)",
148                               op_code, op_code);
149                 return 1;
150         }
151 #endif /* NDEBUG */
152         return 0;
153 }
154
155 /**
156  * Manage TX completions.
157  *
158  * When sending a burst, mlx5_tx_burst() posts several WRs.
159  *
160  * @param txq
161  *   Pointer to TX queue structure.
162  */
163 static void
164 txq_complete(struct txq *txq)
165 {
166         const unsigned int elts_n = txq->elts_n;
167         const unsigned int cqe_n = txq->cqe_n;
168         const unsigned int cqe_cnt = cqe_n - 1;
169         uint16_t elts_free = txq->elts_tail;
170         uint16_t elts_tail;
171         uint16_t cq_ci = txq->cq_ci;
172         volatile struct mlx5_cqe64 *cqe = NULL;
173         volatile union mlx5_wqe *wqe;
174
175         do {
176                 volatile struct mlx5_cqe64 *tmp;
177
178                 tmp = &(*txq->cqes)[cq_ci & cqe_cnt].cqe64;
179                 if (check_cqe64(tmp, cqe_n, cq_ci))
180                         break;
181                 cqe = tmp;
182 #ifndef NDEBUG
183                 if (MLX5_CQE_FORMAT(cqe->op_own) == MLX5_COMPRESSED) {
184                         if (!check_cqe64_seen(cqe))
185                                 ERROR("unexpected compressed CQE, TX stopped");
186                         return;
187                 }
188                 if ((MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_RESP_ERR) ||
189                     (MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_REQ_ERR)) {
190                         if (!check_cqe64_seen(cqe))
191                                 ERROR("unexpected error CQE, TX stopped");
192                         return;
193                 }
194 #endif /* NDEBUG */
195                 ++cq_ci;
196         } while (1);
197         if (unlikely(cqe == NULL))
198                 return;
199         wqe = &(*txq->wqes)[htons(cqe->wqe_counter) & (txq->wqe_n - 1)];
200         elts_tail = wqe->wqe.ctrl.data[3];
201         assert(elts_tail < txq->wqe_n);
202         /* Free buffers. */
203         while (elts_free != elts_tail) {
204                 struct rte_mbuf *elt = (*txq->elts)[elts_free];
205                 unsigned int elts_free_next =
206                         (elts_free + 1) & (elts_n - 1);
207                 struct rte_mbuf *elt_next = (*txq->elts)[elts_free_next];
208
209 #ifndef NDEBUG
210                 /* Poisoning. */
211                 memset(&(*txq->elts)[elts_free],
212                        0x66,
213                        sizeof((*txq->elts)[elts_free]));
214 #endif
215                 RTE_MBUF_PREFETCH_TO_FREE(elt_next);
216                 /* Only one segment needs to be freed. */
217                 rte_pktmbuf_free_seg(elt);
218                 elts_free = elts_free_next;
219         }
220         txq->cq_ci = cq_ci;
221         txq->elts_tail = elts_tail;
222         /* Update the consumer index. */
223         rte_wmb();
224         *txq->cq_db = htonl(cq_ci);
225 }
226
227 /**
228  * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which
229  * the cloned mbuf is allocated is returned instead.
230  *
231  * @param buf
232  *   Pointer to mbuf.
233  *
234  * @return
235  *   Memory pool where data is located for given mbuf.
236  */
237 static struct rte_mempool *
238 txq_mb2mp(struct rte_mbuf *buf)
239 {
240         if (unlikely(RTE_MBUF_INDIRECT(buf)))
241                 return rte_mbuf_from_indirect(buf)->pool;
242         return buf->pool;
243 }
244
245 static inline uint32_t
246 txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
247         __attribute__((always_inline));
248
249 /**
250  * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[].
251  * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
252  * remove an entry first.
253  *
254  * @param txq
255  *   Pointer to TX queue structure.
256  * @param[in] mp
257  *   Memory Pool for which a Memory Region lkey must be returned.
258  *
259  * @return
260  *   mr->lkey on success, (uint32_t)-1 on failure.
261  */
262 static inline uint32_t
263 txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
264 {
265         unsigned int i;
266         uint32_t lkey = (uint32_t)-1;
267
268         for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
269                 if (unlikely(txq->mp2mr[i].mp == NULL)) {
270                         /* Unknown MP, add a new MR for it. */
271                         break;
272                 }
273                 if (txq->mp2mr[i].mp == mp) {
274                         assert(txq->mp2mr[i].lkey != (uint32_t)-1);
275                         assert(htonl(txq->mp2mr[i].mr->lkey) ==
276                                txq->mp2mr[i].lkey);
277                         lkey = txq->mp2mr[i].lkey;
278                         break;
279                 }
280         }
281         if (unlikely(lkey == (uint32_t)-1))
282                 lkey = txq_mp2mr_reg(txq, mp, i);
283         return lkey;
284 }
285
286 /**
287  * Write a regular WQE.
288  *
289  * @param txq
290  *   Pointer to TX queue structure.
291  * @param wqe
292  *   Pointer to the WQE to fill.
293  * @param buf
294  *   Buffer.
295  * @param length
296  *   Packet length.
297  *
298  * @return ds
299  *   Number of DS elements consumed.
300  */
301 static inline unsigned int
302 mlx5_wqe_write(struct txq *txq, volatile union mlx5_wqe *wqe,
303                struct rte_mbuf *buf, uint32_t length)
304 {
305         uintptr_t raw = (uintptr_t)&wqe->wqe.eseg.inline_hdr_start;
306         uint16_t ds;
307         uint16_t pkt_inline_sz = 16;
308         uintptr_t addr = rte_pktmbuf_mtod(buf, uintptr_t);
309         struct mlx5_wqe_data_seg *dseg = NULL;
310
311         assert(length >= 16);
312         /* Start the know and common part of the WQE structure. */
313         wqe->wqe.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
314         wqe->wqe.ctrl.data[2] = 0;
315         wqe->wqe.ctrl.data[3] = 0;
316         wqe->wqe.eseg.rsvd0 = 0;
317         wqe->wqe.eseg.rsvd1 = 0;
318         wqe->wqe.eseg.mss = 0;
319         wqe->wqe.eseg.rsvd2 = 0;
320         /* Start by copying the Ethernet Header. */
321         rte_mov16((uint8_t *)raw, (uint8_t *)addr);
322         length -= 16;
323         addr += 16;
324         /* Replace the Ethernet type by the VLAN if necessary. */
325         if (buf->ol_flags & PKT_TX_VLAN_PKT) {
326                 uint32_t vlan = htonl(0x81000000 | buf->vlan_tci);
327
328                 memcpy((uint8_t *)(raw + 16 - sizeof(vlan)),
329                        &vlan, sizeof(vlan));
330                 addr -= sizeof(vlan);
331                 length += sizeof(vlan);
332         }
333         /* Inline if enough room. */
334         if (txq->max_inline != 0) {
335                 uintptr_t end = (uintptr_t)&(*txq->wqes)[txq->wqe_n];
336                 uint16_t max_inline = txq->max_inline * RTE_CACHE_LINE_SIZE;
337                 uint16_t room;
338
339                 raw += 16;
340                 room = end - (uintptr_t)raw;
341                 if (room > max_inline) {
342                         uintptr_t addr_end = (addr + max_inline) &
343                                 ~(RTE_CACHE_LINE_SIZE - 1);
344                         uint16_t copy_b = ((addr_end - addr) > length) ?
345                                           length :
346                                           (addr_end - addr);
347
348                         rte_memcpy((void *)raw, (void *)addr, copy_b);
349                         addr += copy_b;
350                         length -= copy_b;
351                         pkt_inline_sz += copy_b;
352                         /* Sanity check. */
353                         assert(addr <= addr_end);
354                 }
355                 /* Store the inlined packet size in the WQE. */
356                 wqe->wqe.eseg.inline_hdr_sz = htons(pkt_inline_sz);
357                 /*
358                  * 2 DWORDs consumed by the WQE header + 1 DSEG +
359                  * the size of the inline part of the packet.
360                  */
361                 ds = 2 + ((pkt_inline_sz - 2 + 15) / 16);
362                 if (length > 0) {
363                         dseg = (struct mlx5_wqe_data_seg *)
364                                 ((uintptr_t)wqe + (ds * 16));
365                         if ((uintptr_t)dseg >= end)
366                                 dseg = (struct mlx5_wqe_data_seg *)
367                                         ((uintptr_t)&(*txq->wqes)[0]);
368                         goto use_dseg;
369                 }
370         } else {
371                 /* Add the remaining packet as a simple ds. */
372                 ds = 3;
373                 /*
374                  * No inline has been done in the packet, only the Ethernet
375                  * Header as been stored.
376                  */
377                 wqe->wqe.eseg.inline_hdr_sz = htons(16);
378                 dseg = (struct mlx5_wqe_data_seg *)
379                         ((uintptr_t)wqe + (ds * 16));
380 use_dseg:
381                 *dseg = (struct mlx5_wqe_data_seg) {
382                         .addr = htonll(addr),
383                         .byte_count = htonl(length),
384                         .lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
385                 };
386                 ++ds;
387         }
388         wqe->wqe.ctrl.data[1] = htonl(txq->qp_num_8s | ds);
389         return ds;
390 }
391
392 /**
393  * Ring TX queue doorbell.
394  *
395  * @param txq
396  *   Pointer to TX queue structure.
397  */
398 static inline void
399 mlx5_tx_dbrec(struct txq *txq)
400 {
401         uint8_t *dst = (uint8_t *)((uintptr_t)txq->bf_reg + txq->bf_offset);
402         uint32_t data[4] = {
403                 htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND),
404                 htonl(txq->qp_num_8s),
405                 0,
406                 0,
407         };
408         rte_wmb();
409         *txq->qp_db = htonl(txq->wqe_ci);
410         /* Ensure ordering between DB record and BF copy. */
411         rte_wmb();
412         rte_mov16(dst, (uint8_t *)data);
413         txq->bf_offset ^= txq->bf_buf_size;
414 }
415
416 /**
417  * Prefetch a CQE.
418  *
419  * @param txq
420  *   Pointer to TX queue structure.
421  * @param cqe_ci
422  *   CQE consumer index.
423  */
424 static inline void
425 tx_prefetch_cqe(struct txq *txq, uint16_t ci)
426 {
427         volatile struct mlx5_cqe64 *cqe;
428
429         cqe = &(*txq->cqes)[ci & (txq->cqe_n - 1)].cqe64;
430         rte_prefetch0(cqe);
431 }
432
433 /**
434  * Prefetch a WQE.
435  *
436  * @param txq
437  *   Pointer to TX queue structure.
438  * @param  wqe_ci
439  *   WQE consumer index.
440  */
441 static inline void
442 tx_prefetch_wqe(struct txq *txq, uint16_t ci)
443 {
444         volatile union mlx5_wqe *wqe;
445
446         wqe = &(*txq->wqes)[ci & (txq->wqe_n - 1)];
447         rte_prefetch0(wqe);
448 }
449
450 /**
451  * DPDK callback for TX.
452  *
453  * @param dpdk_txq
454  *   Generic pointer to TX queue structure.
455  * @param[in] pkts
456  *   Packets to transmit.
457  * @param pkts_n
458  *   Number of packets in array.
459  *
460  * @return
461  *   Number of packets successfully transmitted (<= pkts_n).
462  */
463 uint16_t
464 mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
465 {
466         struct txq *txq = (struct txq *)dpdk_txq;
467         uint16_t elts_head = txq->elts_head;
468         const unsigned int elts_n = txq->elts_n;
469         unsigned int i = 0;
470         unsigned int j = 0;
471         unsigned int max;
472         unsigned int comp;
473         volatile union mlx5_wqe *wqe = NULL;
474
475         if (unlikely(!pkts_n))
476                 return 0;
477         /* Prefetch first packet cacheline. */
478         tx_prefetch_cqe(txq, txq->cq_ci);
479         tx_prefetch_cqe(txq, txq->cq_ci + 1);
480         rte_prefetch0(*pkts);
481         /* Start processing. */
482         txq_complete(txq);
483         max = (elts_n - (elts_head - txq->elts_tail));
484         if (max > elts_n)
485                 max -= elts_n;
486         do {
487                 struct rte_mbuf *buf = *(pkts++);
488                 unsigned int elts_head_next;
489                 uint32_t length;
490                 unsigned int segs_n = buf->nb_segs;
491                 volatile struct mlx5_wqe_data_seg *dseg;
492                 unsigned int ds = sizeof(*wqe) / 16;
493
494                 /*
495                  * Make sure there is enough room to store this packet and
496                  * that one ring entry remains unused.
497                  */
498                 assert(segs_n);
499                 if (max < segs_n + 1)
500                         break;
501                 max -= segs_n;
502                 --pkts_n;
503                 elts_head_next = (elts_head + 1) & (elts_n - 1);
504                 wqe = &(*txq->wqes)[txq->wqe_ci & (txq->wqe_n - 1)];
505                 tx_prefetch_wqe(txq, txq->wqe_ci);
506                 tx_prefetch_wqe(txq, txq->wqe_ci + 1);
507                 if (pkts_n)
508                         rte_prefetch0(*pkts);
509                 length = DATA_LEN(buf);
510                 /* Update element. */
511                 (*txq->elts)[elts_head] = buf;
512                 /* Prefetch next buffer data. */
513                 if (pkts_n)
514                         rte_prefetch0(rte_pktmbuf_mtod(*pkts,
515                                                        volatile void *));
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                         wqe->wqe.eseg.cs_flags =
520                                 MLX5_ETH_WQE_L3_CSUM |
521                                 MLX5_ETH_WQE_L4_CSUM;
522                 } else {
523                         wqe->wqe.eseg.cs_flags = 0;
524                 }
525                 ds = mlx5_wqe_write(txq, wqe, buf, length);
526                 if (segs_n == 1)
527                         goto skip_segs;
528                 dseg = (volatile struct mlx5_wqe_data_seg *)
529                         (((uintptr_t)wqe) + ds * 16);
530                 while (--segs_n) {
531                         /*
532                          * Spill on next WQE when the current one does not have
533                          * enough room left. Size of WQE must a be a multiple
534                          * of data segment size.
535                          */
536                         assert(!(sizeof(*wqe) % sizeof(*dseg)));
537                         if (!(ds % (sizeof(*wqe) / 16)))
538                                 dseg = (volatile void *)
539                                         &(*txq->wqes)[txq->wqe_ci++ &
540                                                       (txq->wqe_n - 1)];
541                         else
542                                 ++dseg;
543                         ++ds;
544                         buf = buf->next;
545                         assert(buf);
546                         /* Store segment information. */
547                         dseg->byte_count = htonl(DATA_LEN(buf));
548                         dseg->lkey = txq_mp2mr(txq, txq_mb2mp(buf));
549                         dseg->addr = htonll(rte_pktmbuf_mtod(buf, uintptr_t));
550                         (*txq->elts)[elts_head_next] = buf;
551                         elts_head_next = (elts_head_next + 1) & (elts_n - 1);
552 #ifdef MLX5_PMD_SOFT_COUNTERS
553                         length += DATA_LEN(buf);
554 #endif
555                         ++j;
556                 }
557                 /* Update DS field in WQE. */
558                 wqe->wqe.ctrl.data[1] &= htonl(0xffffffc0);
559                 wqe->wqe.ctrl.data[1] |= htonl(ds & 0x3f);
560 skip_segs:
561 #ifdef MLX5_PMD_SOFT_COUNTERS
562                 /* Increment sent bytes counter. */
563                 txq->stats.obytes += length;
564 #endif
565                 /* Increment consumer index. */
566                 txq->wqe_ci += (ds + 3) / 4;
567                 elts_head = elts_head_next;
568                 ++i;
569         } while (pkts_n);
570         /* Take a shortcut if nothing must be sent. */
571         if (unlikely(i == 0))
572                 return 0;
573         /* Check whether completion threshold has been reached. */
574         comp = txq->elts_comp + i + j;
575         if (comp >= MLX5_TX_COMP_THRESH) {
576                 /* Request completion on last WQE. */
577                 wqe->wqe.ctrl.data[2] = htonl(8);
578                 /* Save elts_head in unused "immediate" field of WQE. */
579                 wqe->wqe.ctrl.data[3] = elts_head;
580                 txq->elts_comp = 0;
581         } else {
582                 txq->elts_comp = comp;
583         }
584 #ifdef MLX5_PMD_SOFT_COUNTERS
585         /* Increment sent packets counter. */
586         txq->stats.opackets += i;
587 #endif
588         /* Ring QP doorbell. */
589         mlx5_tx_dbrec(txq);
590         txq->elts_head = elts_head;
591         return i;
592 }
593
594 /**
595  * Open a MPW session.
596  *
597  * @param txq
598  *   Pointer to TX queue structure.
599  * @param mpw
600  *   Pointer to MPW session structure.
601  * @param length
602  *   Packet length.
603  */
604 static inline void
605 mlx5_mpw_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
606 {
607         uint16_t idx = txq->wqe_ci & (txq->wqe_n - 1);
608         volatile struct mlx5_wqe_data_seg (*dseg)[MLX5_MPW_DSEG_MAX] =
609                 (volatile struct mlx5_wqe_data_seg (*)[])
610                 (uintptr_t)&(*txq->wqes)[(idx + 1) & (txq->wqe_n - 1)];
611
612         mpw->state = MLX5_MPW_STATE_OPENED;
613         mpw->pkts_n = 0;
614         mpw->len = length;
615         mpw->total_len = 0;
616         mpw->wqe = &(*txq->wqes)[idx];
617         mpw->wqe->mpw.eseg.mss = htons(length);
618         mpw->wqe->mpw.eseg.inline_hdr_sz = 0;
619         mpw->wqe->mpw.eseg.rsvd0 = 0;
620         mpw->wqe->mpw.eseg.rsvd1 = 0;
621         mpw->wqe->mpw.eseg.rsvd2 = 0;
622         mpw->wqe->mpw.ctrl.data[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
623                                            (txq->wqe_ci << 8) |
624                                            MLX5_OPCODE_TSO);
625         mpw->wqe->mpw.ctrl.data[2] = 0;
626         mpw->wqe->mpw.ctrl.data[3] = 0;
627         mpw->data.dseg[0] = &mpw->wqe->mpw.dseg[0];
628         mpw->data.dseg[1] = &mpw->wqe->mpw.dseg[1];
629         mpw->data.dseg[2] = &(*dseg)[0];
630         mpw->data.dseg[3] = &(*dseg)[1];
631         mpw->data.dseg[4] = &(*dseg)[2];
632 }
633
634 /**
635  * Close a MPW session.
636  *
637  * @param txq
638  *   Pointer to TX queue structure.
639  * @param mpw
640  *   Pointer to MPW session structure.
641  */
642 static inline void
643 mlx5_mpw_close(struct txq *txq, struct mlx5_mpw *mpw)
644 {
645         unsigned int num = mpw->pkts_n;
646
647         /*
648          * Store size in multiple of 16 bytes. Control and Ethernet segments
649          * count as 2.
650          */
651         mpw->wqe->mpw.ctrl.data[1] = htonl(txq->qp_num_8s | (2 + num));
652         mpw->state = MLX5_MPW_STATE_CLOSED;
653         if (num < 3)
654                 ++txq->wqe_ci;
655         else
656                 txq->wqe_ci += 2;
657         tx_prefetch_wqe(txq, txq->wqe_ci);
658         tx_prefetch_wqe(txq, txq->wqe_ci + 1);
659 }
660
661 /**
662  * DPDK callback for TX with MPW support.
663  *
664  * @param dpdk_txq
665  *   Generic pointer to TX queue structure.
666  * @param[in] pkts
667  *   Packets to transmit.
668  * @param pkts_n
669  *   Number of packets in array.
670  *
671  * @return
672  *   Number of packets successfully transmitted (<= pkts_n).
673  */
674 uint16_t
675 mlx5_tx_burst_mpw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
676 {
677         struct txq *txq = (struct txq *)dpdk_txq;
678         uint16_t elts_head = txq->elts_head;
679         const unsigned int elts_n = txq->elts_n;
680         unsigned int i = 0;
681         unsigned int j = 0;
682         unsigned int max;
683         unsigned int comp;
684         struct mlx5_mpw mpw = {
685                 .state = MLX5_MPW_STATE_CLOSED,
686         };
687
688         if (unlikely(!pkts_n))
689                 return 0;
690         /* Prefetch first packet cacheline. */
691         tx_prefetch_cqe(txq, txq->cq_ci);
692         tx_prefetch_wqe(txq, txq->wqe_ci);
693         tx_prefetch_wqe(txq, txq->wqe_ci + 1);
694         /* Start processing. */
695         txq_complete(txq);
696         max = (elts_n - (elts_head - txq->elts_tail));
697         if (max > elts_n)
698                 max -= elts_n;
699         do {
700                 struct rte_mbuf *buf = *(pkts++);
701                 unsigned int elts_head_next;
702                 uint32_t length;
703                 unsigned int segs_n = buf->nb_segs;
704                 uint32_t cs_flags = 0;
705
706                 /*
707                  * Make sure there is enough room to store this packet and
708                  * that one ring entry remains unused.
709                  */
710                 assert(segs_n);
711                 if (max < segs_n + 1)
712                         break;
713                 /* Do not bother with large packets MPW cannot handle. */
714                 if (segs_n > MLX5_MPW_DSEG_MAX)
715                         break;
716                 max -= segs_n;
717                 --pkts_n;
718                 /* Should we enable HW CKSUM offload */
719                 if (buf->ol_flags &
720                     (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))
721                         cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
722                 /* Retrieve packet information. */
723                 length = PKT_LEN(buf);
724                 assert(length);
725                 /* Start new session if packet differs. */
726                 if ((mpw.state == MLX5_MPW_STATE_OPENED) &&
727                     ((mpw.len != length) ||
728                      (segs_n != 1) ||
729                      (mpw.wqe->mpw.eseg.cs_flags != cs_flags)))
730                         mlx5_mpw_close(txq, &mpw);
731                 if (mpw.state == MLX5_MPW_STATE_CLOSED) {
732                         mlx5_mpw_new(txq, &mpw, length);
733                         mpw.wqe->mpw.eseg.cs_flags = cs_flags;
734                 }
735                 /* Multi-segment packets must be alone in their MPW. */
736                 assert((segs_n == 1) || (mpw.pkts_n == 0));
737 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
738                 length = 0;
739 #endif
740                 do {
741                         volatile struct mlx5_wqe_data_seg *dseg;
742                         uintptr_t addr;
743
744                         elts_head_next = (elts_head + 1) & (elts_n - 1);
745                         assert(buf);
746                         (*txq->elts)[elts_head] = buf;
747                         dseg = mpw.data.dseg[mpw.pkts_n];
748                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
749                         *dseg = (struct mlx5_wqe_data_seg){
750                                 .byte_count = htonl(DATA_LEN(buf)),
751                                 .lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
752                                 .addr = htonll(addr),
753                         };
754                         elts_head = elts_head_next;
755 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
756                         length += DATA_LEN(buf);
757 #endif
758                         buf = buf->next;
759                         ++mpw.pkts_n;
760                         ++j;
761                 } while (--segs_n);
762                 assert(length == mpw.len);
763                 if (mpw.pkts_n == MLX5_MPW_DSEG_MAX)
764                         mlx5_mpw_close(txq, &mpw);
765                 elts_head = elts_head_next;
766 #ifdef MLX5_PMD_SOFT_COUNTERS
767                 /* Increment sent bytes counter. */
768                 txq->stats.obytes += length;
769 #endif
770                 ++i;
771         } while (pkts_n);
772         /* Take a shortcut if nothing must be sent. */
773         if (unlikely(i == 0))
774                 return 0;
775         /* Check whether completion threshold has been reached. */
776         /* "j" includes both packets and segments. */
777         comp = txq->elts_comp + j;
778         if (comp >= MLX5_TX_COMP_THRESH) {
779                 volatile union mlx5_wqe *wqe = mpw.wqe;
780
781                 /* Request completion on last WQE. */
782                 wqe->mpw.ctrl.data[2] = htonl(8);
783                 /* Save elts_head in unused "immediate" field of WQE. */
784                 wqe->mpw.ctrl.data[3] = elts_head;
785                 txq->elts_comp = 0;
786         } else {
787                 txq->elts_comp = comp;
788         }
789 #ifdef MLX5_PMD_SOFT_COUNTERS
790         /* Increment sent packets counter. */
791         txq->stats.opackets += i;
792 #endif
793         /* Ring QP doorbell. */
794         if (mpw.state == MLX5_MPW_STATE_OPENED)
795                 mlx5_mpw_close(txq, &mpw);
796         mlx5_tx_dbrec(txq);
797         txq->elts_head = elts_head;
798         return i;
799 }
800
801 /**
802  * Open a MPW inline session.
803  *
804  * @param txq
805  *   Pointer to TX queue structure.
806  * @param mpw
807  *   Pointer to MPW session structure.
808  * @param length
809  *   Packet length.
810  */
811 static inline void
812 mlx5_mpw_inline_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
813 {
814         uint16_t idx = txq->wqe_ci & (txq->wqe_n - 1);
815
816         mpw->state = MLX5_MPW_INL_STATE_OPENED;
817         mpw->pkts_n = 0;
818         mpw->len = length;
819         mpw->total_len = 0;
820         mpw->wqe = &(*txq->wqes)[idx];
821         mpw->wqe->mpw_inl.ctrl.data[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
822                                                (txq->wqe_ci << 8) |
823                                                MLX5_OPCODE_TSO);
824         mpw->wqe->mpw_inl.ctrl.data[2] = 0;
825         mpw->wqe->mpw_inl.ctrl.data[3] = 0;
826         mpw->wqe->mpw_inl.eseg.mss = htons(length);
827         mpw->wqe->mpw_inl.eseg.inline_hdr_sz = 0;
828         mpw->wqe->mpw_inl.eseg.cs_flags = 0;
829         mpw->wqe->mpw_inl.eseg.rsvd0 = 0;
830         mpw->wqe->mpw_inl.eseg.rsvd1 = 0;
831         mpw->wqe->mpw_inl.eseg.rsvd2 = 0;
832         mpw->data.raw = &mpw->wqe->mpw_inl.data[0];
833 }
834
835 /**
836  * Close a MPW inline session.
837  *
838  * @param txq
839  *   Pointer to TX queue structure.
840  * @param mpw
841  *   Pointer to MPW session structure.
842  */
843 static inline void
844 mlx5_mpw_inline_close(struct txq *txq, struct mlx5_mpw *mpw)
845 {
846         unsigned int size;
847
848         size = sizeof(*mpw->wqe) - MLX5_MWQE64_INL_DATA + mpw->total_len;
849         /*
850          * Store size in multiple of 16 bytes. Control and Ethernet segments
851          * count as 2.
852          */
853         mpw->wqe->mpw_inl.ctrl.data[1] =
854                 htonl(txq->qp_num_8s | ((size + 15) / 16));
855         mpw->state = MLX5_MPW_STATE_CLOSED;
856         mpw->wqe->mpw_inl.byte_cnt = htonl(mpw->total_len | MLX5_INLINE_SEG);
857         txq->wqe_ci += (size + (sizeof(*mpw->wqe) - 1)) / sizeof(*mpw->wqe);
858 }
859
860 /**
861  * DPDK callback for TX with MPW inline support.
862  *
863  * @param dpdk_txq
864  *   Generic pointer to TX queue structure.
865  * @param[in] pkts
866  *   Packets to transmit.
867  * @param pkts_n
868  *   Number of packets in array.
869  *
870  * @return
871  *   Number of packets successfully transmitted (<= pkts_n).
872  */
873 uint16_t
874 mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
875                          uint16_t pkts_n)
876 {
877         struct txq *txq = (struct txq *)dpdk_txq;
878         uint16_t elts_head = txq->elts_head;
879         const unsigned int elts_n = txq->elts_n;
880         unsigned int i = 0;
881         unsigned int j = 0;
882         unsigned int max;
883         unsigned int comp;
884         unsigned int inline_room = txq->max_inline * RTE_CACHE_LINE_SIZE;
885         struct mlx5_mpw mpw = {
886                 .state = MLX5_MPW_STATE_CLOSED,
887         };
888
889         if (unlikely(!pkts_n))
890                 return 0;
891         /* Prefetch first packet cacheline. */
892         tx_prefetch_cqe(txq, txq->cq_ci);
893         tx_prefetch_wqe(txq, txq->wqe_ci);
894         tx_prefetch_wqe(txq, txq->wqe_ci + 1);
895         /* Start processing. */
896         txq_complete(txq);
897         max = (elts_n - (elts_head - txq->elts_tail));
898         if (max > elts_n)
899                 max -= elts_n;
900         do {
901                 struct rte_mbuf *buf = *(pkts++);
902                 unsigned int elts_head_next;
903                 uintptr_t addr;
904                 uint32_t length;
905                 unsigned int segs_n = buf->nb_segs;
906                 uint32_t cs_flags = 0;
907
908                 /*
909                  * Make sure there is enough room to store this packet and
910                  * that one ring entry remains unused.
911                  */
912                 assert(segs_n);
913                 if (max < segs_n + 1)
914                         break;
915                 /* Do not bother with large packets MPW cannot handle. */
916                 if (segs_n > MLX5_MPW_DSEG_MAX)
917                         break;
918                 max -= segs_n;
919                 --pkts_n;
920                 /* Should we enable HW CKSUM offload */
921                 if (buf->ol_flags &
922                     (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))
923                         cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
924                 /* Retrieve packet information. */
925                 length = PKT_LEN(buf);
926                 /* Start new session if packet differs. */
927                 if (mpw.state == MLX5_MPW_STATE_OPENED) {
928                         if ((mpw.len != length) ||
929                             (segs_n != 1) ||
930                             (mpw.wqe->mpw.eseg.cs_flags != cs_flags))
931                                 mlx5_mpw_close(txq, &mpw);
932                 } else if (mpw.state == MLX5_MPW_INL_STATE_OPENED) {
933                         if ((mpw.len != length) ||
934                             (segs_n != 1) ||
935                             (length > inline_room) ||
936                             (mpw.wqe->mpw_inl.eseg.cs_flags != cs_flags)) {
937                                 mlx5_mpw_inline_close(txq, &mpw);
938                                 inline_room =
939                                         txq->max_inline * RTE_CACHE_LINE_SIZE;
940                         }
941                 }
942                 if (mpw.state == MLX5_MPW_STATE_CLOSED) {
943                         if ((segs_n != 1) ||
944                             (length > inline_room)) {
945                                 mlx5_mpw_new(txq, &mpw, length);
946                                 mpw.wqe->mpw.eseg.cs_flags = cs_flags;
947                         } else {
948                                 mlx5_mpw_inline_new(txq, &mpw, length);
949                                 mpw.wqe->mpw_inl.eseg.cs_flags = cs_flags;
950                         }
951                 }
952                 /* Multi-segment packets must be alone in their MPW. */
953                 assert((segs_n == 1) || (mpw.pkts_n == 0));
954                 if (mpw.state == MLX5_MPW_STATE_OPENED) {
955                         assert(inline_room ==
956                                txq->max_inline * RTE_CACHE_LINE_SIZE);
957 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
958                         length = 0;
959 #endif
960                         do {
961                                 volatile struct mlx5_wqe_data_seg *dseg;
962
963                                 elts_head_next =
964                                         (elts_head + 1) & (elts_n - 1);
965                                 assert(buf);
966                                 (*txq->elts)[elts_head] = buf;
967                                 dseg = mpw.data.dseg[mpw.pkts_n];
968                                 addr = rte_pktmbuf_mtod(buf, uintptr_t);
969                                 *dseg = (struct mlx5_wqe_data_seg){
970                                         .byte_count = htonl(DATA_LEN(buf)),
971                                         .lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
972                                         .addr = htonll(addr),
973                                 };
974                                 elts_head = elts_head_next;
975 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
976                                 length += DATA_LEN(buf);
977 #endif
978                                 buf = buf->next;
979                                 ++mpw.pkts_n;
980                                 ++j;
981                         } while (--segs_n);
982                         assert(length == mpw.len);
983                         if (mpw.pkts_n == MLX5_MPW_DSEG_MAX)
984                                 mlx5_mpw_close(txq, &mpw);
985                 } else {
986                         unsigned int max;
987
988                         assert(mpw.state == MLX5_MPW_INL_STATE_OPENED);
989                         assert(length <= inline_room);
990                         assert(length == DATA_LEN(buf));
991                         elts_head_next = (elts_head + 1) & (elts_n - 1);
992                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
993                         (*txq->elts)[elts_head] = buf;
994                         /* Maximum number of bytes before wrapping. */
995                         max = ((uintptr_t)&(*txq->wqes)[txq->wqe_n] -
996                                (uintptr_t)mpw.data.raw);
997                         if (length > max) {
998                                 rte_memcpy((void *)(uintptr_t)mpw.data.raw,
999                                            (void *)addr,
1000                                            max);
1001                                 mpw.data.raw =
1002                                         (volatile void *)&(*txq->wqes)[0];
1003                                 rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1004                                            (void *)(addr + max),
1005                                            length - max);
1006                                 mpw.data.raw += length - max;
1007                         } else {
1008                                 rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1009                                            (void *)addr,
1010                                            length);
1011                                 mpw.data.raw += length;
1012                         }
1013                         if ((uintptr_t)mpw.data.raw ==
1014                             (uintptr_t)&(*txq->wqes)[txq->wqe_n])
1015                                 mpw.data.raw =
1016                                         (volatile void *)&(*txq->wqes)[0];
1017                         ++mpw.pkts_n;
1018                         ++j;
1019                         if (mpw.pkts_n == MLX5_MPW_DSEG_MAX) {
1020                                 mlx5_mpw_inline_close(txq, &mpw);
1021                                 inline_room =
1022                                         txq->max_inline * RTE_CACHE_LINE_SIZE;
1023                         } else {
1024                                 inline_room -= length;
1025                         }
1026                 }
1027                 mpw.total_len += length;
1028                 elts_head = elts_head_next;
1029 #ifdef MLX5_PMD_SOFT_COUNTERS
1030                 /* Increment sent bytes counter. */
1031                 txq->stats.obytes += length;
1032 #endif
1033                 ++i;
1034         } while (pkts_n);
1035         /* Take a shortcut if nothing must be sent. */
1036         if (unlikely(i == 0))
1037                 return 0;
1038         /* Check whether completion threshold has been reached. */
1039         /* "j" includes both packets and segments. */
1040         comp = txq->elts_comp + j;
1041         if (comp >= MLX5_TX_COMP_THRESH) {
1042                 volatile union mlx5_wqe *wqe = mpw.wqe;
1043
1044                 /* Request completion on last WQE. */
1045                 wqe->mpw_inl.ctrl.data[2] = htonl(8);
1046                 /* Save elts_head in unused "immediate" field of WQE. */
1047                 wqe->mpw_inl.ctrl.data[3] = elts_head;
1048                 txq->elts_comp = 0;
1049         } else {
1050                 txq->elts_comp = comp;
1051         }
1052 #ifdef MLX5_PMD_SOFT_COUNTERS
1053         /* Increment sent packets counter. */
1054         txq->stats.opackets += i;
1055 #endif
1056         /* Ring QP doorbell. */
1057         if (mpw.state == MLX5_MPW_INL_STATE_OPENED)
1058                 mlx5_mpw_inline_close(txq, &mpw);
1059         else if (mpw.state == MLX5_MPW_STATE_OPENED)
1060                 mlx5_mpw_close(txq, &mpw);
1061         mlx5_tx_dbrec(txq);
1062         txq->elts_head = elts_head;
1063         return i;
1064 }
1065
1066 /**
1067  * Translate RX completion flags to packet type.
1068  *
1069  * @param[in] cqe
1070  *   Pointer to CQE.
1071  *
1072  * @note: fix mlx5_dev_supported_ptypes_get() if any change here.
1073  *
1074  * @return
1075  *   Packet type for struct rte_mbuf.
1076  */
1077 static inline uint32_t
1078 rxq_cq_to_pkt_type(volatile struct mlx5_cqe64 *cqe)
1079 {
1080         uint32_t pkt_type;
1081         uint8_t flags = cqe->l4_hdr_type_etc;
1082         uint8_t info = cqe->rsvd0[0];
1083
1084         if (info & MLX5_CQE_RX_TUNNEL_PACKET)
1085                 pkt_type =
1086                         TRANSPOSE(flags,
1087                                   MLX5_CQE_RX_OUTER_IPV4_PACKET,
1088                                   RTE_PTYPE_L3_IPV4) |
1089                         TRANSPOSE(flags,
1090                                   MLX5_CQE_RX_OUTER_IPV6_PACKET,
1091                                   RTE_PTYPE_L3_IPV6) |
1092                         TRANSPOSE(flags,
1093                                   MLX5_CQE_RX_IPV4_PACKET,
1094                                   RTE_PTYPE_INNER_L3_IPV4) |
1095                         TRANSPOSE(flags,
1096                                   MLX5_CQE_RX_IPV6_PACKET,
1097                                   RTE_PTYPE_INNER_L3_IPV6);
1098         else
1099                 pkt_type =
1100                         TRANSPOSE(flags,
1101                                   MLX5_CQE_L3_HDR_TYPE_IPV6,
1102                                   RTE_PTYPE_L3_IPV6) |
1103                         TRANSPOSE(flags,
1104                                   MLX5_CQE_L3_HDR_TYPE_IPV4,
1105                                   RTE_PTYPE_L3_IPV4);
1106         return pkt_type;
1107 }
1108
1109 /**
1110  * Get size of the next packet for a given CQE. For compressed CQEs, the
1111  * consumer index is updated only once all packets of the current one have
1112  * been processed.
1113  *
1114  * @param rxq
1115  *   Pointer to RX queue.
1116  * @param cqe
1117  *   CQE to process.
1118  *
1119  * @return
1120  *   Packet size in bytes (0 if there is none), -1 in case of completion
1121  *   with error.
1122  */
1123 static inline int
1124 mlx5_rx_poll_len(struct rxq *rxq, volatile struct mlx5_cqe64 *cqe,
1125                  uint16_t cqe_cnt)
1126 {
1127         struct rxq_zip *zip = &rxq->zip;
1128         uint16_t cqe_n = cqe_cnt + 1;
1129         int len = 0;
1130
1131         /* Process compressed data in the CQE and mini arrays. */
1132         if (zip->ai) {
1133                 volatile struct mlx5_mini_cqe8 (*mc)[8] =
1134                         (volatile struct mlx5_mini_cqe8 (*)[8])
1135                         (uintptr_t)(&(*rxq->cqes)[zip->ca & cqe_cnt].cqe64);
1136
1137                 len = ntohl((*mc)[zip->ai & 7].byte_cnt);
1138                 if ((++zip->ai & 7) == 0) {
1139                         /*
1140                          * Increment consumer index to skip the number of
1141                          * CQEs consumed. Hardware leaves holes in the CQ
1142                          * ring for software use.
1143                          */
1144                         zip->ca = zip->na;
1145                         zip->na += 8;
1146                 }
1147                 if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
1148                         uint16_t idx = rxq->cq_ci;
1149                         uint16_t end = zip->cq_ci;
1150
1151                         while (idx != end) {
1152                                 (*rxq->cqes)[idx & cqe_cnt].cqe64.op_own =
1153                                         MLX5_CQE_INVALIDATE;
1154                                 ++idx;
1155                         }
1156                         rxq->cq_ci = zip->cq_ci;
1157                         zip->ai = 0;
1158                 }
1159         /* No compressed data, get next CQE and verify if it is compressed. */
1160         } else {
1161                 int ret;
1162                 int8_t op_own;
1163
1164                 ret = check_cqe64(cqe, cqe_n, rxq->cq_ci);
1165                 if (unlikely(ret == 1))
1166                         return 0;
1167                 ++rxq->cq_ci;
1168                 op_own = cqe->op_own;
1169                 if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
1170                         volatile struct mlx5_mini_cqe8 (*mc)[8] =
1171                                 (volatile struct mlx5_mini_cqe8 (*)[8])
1172                                 (uintptr_t)(&(*rxq->cqes)[rxq->cq_ci &
1173                                                           cqe_cnt].cqe64);
1174
1175                         /* Fix endianness. */
1176                         zip->cqe_cnt = ntohl(cqe->byte_cnt);
1177                         /*
1178                          * Current mini array position is the one returned by
1179                          * check_cqe64().
1180                          *
1181                          * If completion comprises several mini arrays, as a
1182                          * special case the second one is located 7 CQEs after
1183                          * the initial CQE instead of 8 for subsequent ones.
1184                          */
1185                         zip->ca = rxq->cq_ci & cqe_cnt;
1186                         zip->na = zip->ca + 7;
1187                         /* Compute the next non compressed CQE. */
1188                         --rxq->cq_ci;
1189                         zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
1190                         /* Get packet size to return. */
1191                         len = ntohl((*mc)[0].byte_cnt);
1192                         zip->ai = 1;
1193                 } else {
1194                         len = ntohl(cqe->byte_cnt);
1195                 }
1196                 /* Error while receiving packet. */
1197                 if (unlikely(MLX5_CQE_OPCODE(op_own) == MLX5_CQE_RESP_ERR))
1198                         return -1;
1199         }
1200         return len;
1201 }
1202
1203 /**
1204  * Translate RX completion flags to offload flags.
1205  *
1206  * @param[in] rxq
1207  *   Pointer to RX queue structure.
1208  * @param[in] cqe
1209  *   Pointer to CQE.
1210  *
1211  * @return
1212  *   Offload flags (ol_flags) for struct rte_mbuf.
1213  */
1214 static inline uint32_t
1215 rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe64 *cqe)
1216 {
1217         uint32_t ol_flags = 0;
1218         uint8_t l3_hdr = (cqe->l4_hdr_type_etc) & MLX5_CQE_L3_HDR_TYPE_MASK;
1219         uint8_t l4_hdr = (cqe->l4_hdr_type_etc) & MLX5_CQE_L4_HDR_TYPE_MASK;
1220         uint8_t info = cqe->rsvd0[0];
1221
1222         if ((l3_hdr == MLX5_CQE_L3_HDR_TYPE_IPV4) ||
1223             (l3_hdr == MLX5_CQE_L3_HDR_TYPE_IPV6))
1224                 ol_flags |=
1225                         (!(cqe->hds_ip_ext & MLX5_CQE_L3_OK) *
1226                          PKT_RX_IP_CKSUM_BAD);
1227         if ((l4_hdr == MLX5_CQE_L4_HDR_TYPE_TCP) ||
1228             (l4_hdr == MLX5_CQE_L4_HDR_TYPE_TCP_EMP_ACK) ||
1229             (l4_hdr == MLX5_CQE_L4_HDR_TYPE_TCP_ACK) ||
1230             (l4_hdr == MLX5_CQE_L4_HDR_TYPE_UDP))
1231                 ol_flags |=
1232                         (!(cqe->hds_ip_ext & MLX5_CQE_L4_OK) *
1233                          PKT_RX_L4_CKSUM_BAD);
1234         /*
1235          * PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD are used in place
1236          * of PKT_RX_EIP_CKSUM_BAD because the latter is not functional
1237          * (its value is 0).
1238          */
1239         if ((info & MLX5_CQE_RX_TUNNEL_PACKET) && (rxq->csum_l2tun))
1240                 ol_flags |=
1241                         TRANSPOSE(~cqe->l4_hdr_type_etc,
1242                                   MLX5_CQE_RX_OUTER_IP_CSUM_OK,
1243                                   PKT_RX_IP_CKSUM_BAD) |
1244                         TRANSPOSE(~cqe->l4_hdr_type_etc,
1245                                   MLX5_CQE_RX_OUTER_TCP_UDP_CSUM_OK,
1246                                   PKT_RX_L4_CKSUM_BAD);
1247         return ol_flags;
1248 }
1249
1250 /**
1251  * DPDK callback for RX.
1252  *
1253  * @param dpdk_rxq
1254  *   Generic pointer to RX queue structure.
1255  * @param[out] pkts
1256  *   Array to store received packets.
1257  * @param pkts_n
1258  *   Maximum number of packets in array.
1259  *
1260  * @return
1261  *   Number of packets successfully received (<= pkts_n).
1262  */
1263 uint16_t
1264 mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1265 {
1266         struct rxq *rxq = dpdk_rxq;
1267         const unsigned int wqe_cnt = rxq->elts_n - 1;
1268         const unsigned int cqe_cnt = rxq->cqe_n - 1;
1269         const unsigned int sges_n = rxq->sges_n;
1270         struct rte_mbuf *pkt = NULL;
1271         struct rte_mbuf *seg = NULL;
1272         volatile struct mlx5_cqe64 *cqe =
1273                 &(*rxq->cqes)[rxq->cq_ci & cqe_cnt].cqe64;
1274         unsigned int i = 0;
1275         unsigned int rq_ci = rxq->rq_ci << sges_n;
1276         int len;
1277
1278         while (pkts_n) {
1279                 unsigned int idx = rq_ci & wqe_cnt;
1280                 volatile struct mlx5_wqe_data_seg *wqe = &(*rxq->wqes)[idx];
1281                 struct rte_mbuf *rep = (*rxq->elts)[idx];
1282
1283                 if (pkt)
1284                         NEXT(seg) = rep;
1285                 seg = rep;
1286                 rte_prefetch0(seg);
1287                 rte_prefetch0(cqe);
1288                 rte_prefetch0(wqe);
1289                 rep = rte_mbuf_raw_alloc(rxq->mp);
1290                 if (unlikely(rep == NULL)) {
1291                         ++rxq->stats.rx_nombuf;
1292                         if (!pkt) {
1293                                 /*
1294                                  * no buffers before we even started,
1295                                  * bail out silently.
1296                                  */
1297                                 break;
1298                         }
1299                         while (pkt != seg) {
1300                                 assert(pkt != (*rxq->elts)[idx]);
1301                                 seg = NEXT(pkt);
1302                                 rte_mbuf_refcnt_set(pkt, 0);
1303                                 __rte_mbuf_raw_free(pkt);
1304                                 pkt = seg;
1305                         }
1306                         break;
1307                 }
1308                 if (!pkt) {
1309                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt].cqe64;
1310                         len = mlx5_rx_poll_len(rxq, cqe, cqe_cnt);
1311                         if (len == 0) {
1312                                 rte_mbuf_refcnt_set(rep, 0);
1313                                 __rte_mbuf_raw_free(rep);
1314                                 break;
1315                         }
1316                         if (unlikely(len == -1)) {
1317                                 /* RX error, packet is likely too large. */
1318                                 rte_mbuf_refcnt_set(rep, 0);
1319                                 __rte_mbuf_raw_free(rep);
1320                                 ++rxq->stats.idropped;
1321                                 goto skip;
1322                         }
1323                         pkt = seg;
1324                         assert(len >= (rxq->crc_present << 2));
1325                         /* Update packet information. */
1326                         pkt->packet_type = 0;
1327                         pkt->ol_flags = 0;
1328                         if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip |
1329                             rxq->crc_present) {
1330                                 if (rxq->csum) {
1331                                         pkt->packet_type =
1332                                                 rxq_cq_to_pkt_type(cqe);
1333                                         pkt->ol_flags =
1334                                                 rxq_cq_to_ol_flags(rxq, cqe);
1335                                 }
1336                                 if (cqe->l4_hdr_type_etc &
1337                                     MLX5_CQE_VLAN_STRIPPED) {
1338                                         pkt->ol_flags |= PKT_RX_VLAN_PKT |
1339                                                 PKT_RX_VLAN_STRIPPED;
1340                                         pkt->vlan_tci = ntohs(cqe->vlan_info);
1341                                 }
1342                                 if (rxq->crc_present)
1343                                         len -= ETHER_CRC_LEN;
1344                         }
1345                         PKT_LEN(pkt) = len;
1346                 }
1347                 DATA_LEN(rep) = DATA_LEN(seg);
1348                 PKT_LEN(rep) = PKT_LEN(seg);
1349                 SET_DATA_OFF(rep, DATA_OFF(seg));
1350                 NB_SEGS(rep) = NB_SEGS(seg);
1351                 PORT(rep) = PORT(seg);
1352                 NEXT(rep) = NULL;
1353                 (*rxq->elts)[idx] = rep;
1354                 /*
1355                  * Fill NIC descriptor with the new buffer.  The lkey and size
1356                  * of the buffers are already known, only the buffer address
1357                  * changes.
1358                  */
1359                 wqe->addr = htonll(rte_pktmbuf_mtod(rep, uintptr_t));
1360                 if (len > DATA_LEN(seg)) {
1361                         len -= DATA_LEN(seg);
1362                         ++NB_SEGS(pkt);
1363                         ++rq_ci;
1364                         continue;
1365                 }
1366                 DATA_LEN(seg) = len;
1367 #ifdef MLX5_PMD_SOFT_COUNTERS
1368                 /* Increment bytes counter. */
1369                 rxq->stats.ibytes += PKT_LEN(pkt);
1370 #endif
1371                 /* Return packet. */
1372                 *(pkts++) = pkt;
1373                 pkt = NULL;
1374                 --pkts_n;
1375                 ++i;
1376 skip:
1377                 /* Align consumer index to the next stride. */
1378                 rq_ci >>= sges_n;
1379                 ++rq_ci;
1380                 rq_ci <<= sges_n;
1381         }
1382         if (unlikely((i == 0) && ((rq_ci >> sges_n) == rxq->rq_ci)))
1383                 return 0;
1384         /* Update the consumer index. */
1385         rxq->rq_ci = rq_ci >> sges_n;
1386         rte_wmb();
1387         *rxq->cq_db = htonl(rxq->cq_ci);
1388         rte_wmb();
1389         *rxq->rq_db = htonl(rxq->rq_ci);
1390 #ifdef MLX5_PMD_SOFT_COUNTERS
1391         /* Increment packets counter. */
1392         rxq->stats.ipackets += i;
1393 #endif
1394         return i;
1395 }
1396
1397 /**
1398  * Dummy DPDK callback for TX.
1399  *
1400  * This function is used to temporarily replace the real callback during
1401  * unsafe control operations on the queue, or in case of error.
1402  *
1403  * @param dpdk_txq
1404  *   Generic pointer to TX queue structure.
1405  * @param[in] pkts
1406  *   Packets to transmit.
1407  * @param pkts_n
1408  *   Number of packets in array.
1409  *
1410  * @return
1411  *   Number of packets successfully transmitted (<= pkts_n).
1412  */
1413 uint16_t
1414 removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
1415 {
1416         (void)dpdk_txq;
1417         (void)pkts;
1418         (void)pkts_n;
1419         return 0;
1420 }
1421
1422 /**
1423  * Dummy DPDK callback for RX.
1424  *
1425  * This function is used to temporarily replace the real callback during
1426  * unsafe control operations on the queue, or in case of error.
1427  *
1428  * @param dpdk_rxq
1429  *   Generic pointer to RX queue structure.
1430  * @param[out] pkts
1431  *   Array to store received packets.
1432  * @param pkts_n
1433  *   Maximum number of packets in array.
1434  *
1435  * @return
1436  *   Number of packets successfully received (<= pkts_n).
1437  */
1438 uint16_t
1439 removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1440 {
1441         (void)dpdk_rxq;
1442         (void)pkts;
1443         (void)pkts_n;
1444         return 0;
1445 }