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