net/mlx5: remove port info from shareable Rx queue
[dpdk.git] / drivers / net / mlx5 / mlx5_rx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2021 6WIND S.A.
3  * Copyright 2021 Mellanox Technologies, Ltd
4  */
5
6 #include <stdint.h>
7 #include <string.h>
8 #include <stdlib.h>
9
10 #include <rte_mbuf.h>
11 #include <rte_mempool.h>
12 #include <rte_prefetch.h>
13 #include <rte_common.h>
14 #include <rte_branch_prediction.h>
15 #include <rte_ether.h>
16 #include <rte_cycles.h>
17 #include <rte_flow.h>
18
19 #include <mlx5_prm.h>
20 #include <mlx5_common.h>
21 #include <mlx5_common_mr.h>
22
23 #include "mlx5_autoconf.h"
24 #include "mlx5_defs.h"
25 #include "mlx5.h"
26 #include "mlx5_utils.h"
27 #include "mlx5_rxtx.h"
28 #include "mlx5_rx.h"
29
30
31 static __rte_always_inline uint32_t
32 rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
33                    volatile struct mlx5_mini_cqe8 *mcqe);
34
35 static __rte_always_inline int
36 mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
37                  uint16_t cqe_cnt, volatile struct mlx5_mini_cqe8 **mcqe);
38
39 static __rte_always_inline uint32_t
40 rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe);
41
42 static __rte_always_inline void
43 rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
44                volatile struct mlx5_cqe *cqe,
45                volatile struct mlx5_mini_cqe8 *mcqe);
46
47 static inline void
48 mlx5_lro_update_tcp_hdr(struct rte_tcp_hdr *__rte_restrict tcp,
49                         volatile struct mlx5_cqe *__rte_restrict cqe,
50                         uint32_t phcsum, uint8_t l4_type);
51
52 static inline void
53 mlx5_lro_update_hdr(uint8_t *__rte_restrict padd,
54                     volatile struct mlx5_cqe *__rte_restrict cqe,
55                     volatile struct mlx5_mini_cqe8 *mcqe,
56                     struct mlx5_rxq_data *rxq, uint32_t len);
57
58
59 /**
60  * Internal function to compute the number of used descriptors in an RX queue.
61  *
62  * @param rxq
63  *   The Rx queue.
64  *
65  * @return
66  *   The number of used Rx descriptor.
67  */
68 static uint32_t
69 rx_queue_count(struct mlx5_rxq_data *rxq)
70 {
71         struct rxq_zip *zip = &rxq->zip;
72         volatile struct mlx5_cqe *cqe;
73         const unsigned int cqe_n = (1 << rxq->cqe_n);
74         const unsigned int sges_n = (1 << rxq->sges_n);
75         const unsigned int elts_n = (1 << rxq->elts_n);
76         const unsigned int strd_n = (1 << rxq->strd_num_n);
77         const unsigned int cqe_cnt = cqe_n - 1;
78         unsigned int cq_ci, used;
79
80         /* if we are processing a compressed cqe */
81         if (zip->ai) {
82                 used = zip->cqe_cnt - zip->ai;
83                 cq_ci = zip->cq_ci;
84         } else {
85                 used = 0;
86                 cq_ci = rxq->cq_ci;
87         }
88         cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
89         while (check_cqe(cqe, cqe_n, cq_ci) != MLX5_CQE_STATUS_HW_OWN) {
90                 int8_t op_own;
91                 unsigned int n;
92
93                 op_own = cqe->op_own;
94                 if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
95                         n = rte_be_to_cpu_32(cqe->byte_cnt);
96                 else
97                         n = 1;
98                 cq_ci += n;
99                 used += n;
100                 cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
101         }
102         used = RTE_MIN(used * sges_n, elts_n * strd_n);
103         return used;
104 }
105
106 /**
107  * DPDK callback to check the status of a Rx descriptor.
108  *
109  * @param rx_queue
110  *   The Rx queue.
111  * @param[in] offset
112  *   The index of the descriptor in the ring.
113  *
114  * @return
115  *   The status of the Rx descriptor.
116  */
117 int
118 mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
119 {
120         struct mlx5_rxq_data *rxq = rx_queue;
121
122         if (offset >= (1 << rxq->cqe_n)) {
123                 rte_errno = EINVAL;
124                 return -rte_errno;
125         }
126         if (offset < rx_queue_count(rxq))
127                 return RTE_ETH_RX_DESC_DONE;
128         return RTE_ETH_RX_DESC_AVAIL;
129 }
130
131 /**
132  * DPDK callback to get the RX queue information.
133  *
134  * @param dev
135  *   Pointer to the device structure.
136  *
137  * @param rx_queue_id
138  *   Rx queue identificator.
139  *
140  * @param qinfo
141  *   Pointer to the RX queue information structure.
142  *
143  * @return
144  *   None.
145  */
146
147 void
148 mlx5_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
149                   struct rte_eth_rxq_info *qinfo)
150 {
151         struct mlx5_priv *priv = dev->data->dev_private;
152         struct mlx5_rxq_data *rxq = (*priv->rxqs)[rx_queue_id];
153         struct mlx5_rxq_ctrl *rxq_ctrl =
154                 container_of(rxq, struct mlx5_rxq_ctrl, rxq);
155
156         if (!rxq)
157                 return;
158         qinfo->mp = mlx5_rxq_mprq_enabled(rxq) ?
159                                         rxq->mprq_mp : rxq->mp;
160         qinfo->conf.rx_thresh.pthresh = 0;
161         qinfo->conf.rx_thresh.hthresh = 0;
162         qinfo->conf.rx_thresh.wthresh = 0;
163         qinfo->conf.rx_free_thresh = rxq->rq_repl_thresh;
164         qinfo->conf.rx_drop_en = 1;
165         qinfo->conf.rx_deferred_start = rxq_ctrl ? 0 : 1;
166         qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads;
167         qinfo->scattered_rx = dev->data->scattered_rx;
168         qinfo->nb_desc = mlx5_rxq_mprq_enabled(rxq) ?
169                 (1 << rxq->elts_n) * (1 << rxq->strd_num_n) :
170                 (1 << rxq->elts_n);
171 }
172
173 /**
174  * DPDK callback to get the RX packet burst mode information.
175  *
176  * @param dev
177  *   Pointer to the device structure.
178  *
179  * @param rx_queue_id
180  *   Rx queue identificatior.
181  *
182  * @param mode
183  *   Pointer to the burts mode information.
184  *
185  * @return
186  *   0 as success, -EINVAL as failure.
187  */
188 int
189 mlx5_rx_burst_mode_get(struct rte_eth_dev *dev,
190                        uint16_t rx_queue_id __rte_unused,
191                        struct rte_eth_burst_mode *mode)
192 {
193         eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
194         struct mlx5_priv *priv = dev->data->dev_private;
195         struct mlx5_rxq_data *rxq;
196
197         rxq = (*priv->rxqs)[rx_queue_id];
198         if (!rxq) {
199                 rte_errno = EINVAL;
200                 return -rte_errno;
201         }
202         if (pkt_burst == mlx5_rx_burst) {
203                 snprintf(mode->info, sizeof(mode->info), "%s", "Scalar");
204         } else if (pkt_burst == mlx5_rx_burst_mprq) {
205                 snprintf(mode->info, sizeof(mode->info), "%s", "Multi-Packet RQ");
206         } else if (pkt_burst == mlx5_rx_burst_vec) {
207 #if defined RTE_ARCH_X86_64
208                 snprintf(mode->info, sizeof(mode->info), "%s", "Vector SSE");
209 #elif defined RTE_ARCH_ARM64
210                 snprintf(mode->info, sizeof(mode->info), "%s", "Vector Neon");
211 #elif defined RTE_ARCH_PPC_64
212                 snprintf(mode->info, sizeof(mode->info), "%s", "Vector AltiVec");
213 #else
214                 return -EINVAL;
215 #endif
216         } else if (pkt_burst == mlx5_rx_burst_mprq_vec) {
217 #if defined RTE_ARCH_X86_64
218                 snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector SSE");
219 #elif defined RTE_ARCH_ARM64
220                 snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector Neon");
221 #elif defined RTE_ARCH_PPC_64
222                 snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector AltiVec");
223 #else
224                 return -EINVAL;
225 #endif
226         } else {
227                 return -EINVAL;
228         }
229         return 0;
230 }
231
232 /**
233  * DPDK callback to get the number of used descriptors in a RX queue.
234  *
235  * @param rx_queue
236  *   The Rx queue pointer.
237  *
238  * @return
239  *   The number of used rx descriptor.
240  *   -EINVAL if the queue is invalid
241  */
242 uint32_t
243 mlx5_rx_queue_count(void *rx_queue)
244 {
245         struct mlx5_rxq_data *rxq = rx_queue;
246         struct rte_eth_dev *dev;
247
248         if (!rxq) {
249                 rte_errno = EINVAL;
250                 return -rte_errno;
251         }
252
253         dev = &rte_eth_devices[rxq->port_id];
254
255         if (dev->rx_pkt_burst == NULL ||
256             dev->rx_pkt_burst == removed_rx_burst) {
257                 rte_errno = ENOTSUP;
258                 return -rte_errno;
259         }
260
261         return rx_queue_count(rxq);
262 }
263
264 #define CLB_VAL_IDX 0
265 #define CLB_MSK_IDX 1
266 static int
267 mlx5_monitor_callback(const uint64_t value,
268                 const uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])
269 {
270         const uint64_t m = opaque[CLB_MSK_IDX];
271         const uint64_t v = opaque[CLB_VAL_IDX];
272
273         return (value & m) == v ? -1 : 0;
274 }
275
276 int mlx5_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
277 {
278         struct mlx5_rxq_data *rxq = rx_queue;
279         const unsigned int cqe_num = 1 << rxq->cqe_n;
280         const unsigned int cqe_mask = cqe_num - 1;
281         const uint16_t idx = rxq->cq_ci & cqe_num;
282         volatile struct mlx5_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
283
284         if (unlikely(rxq->cqes == NULL)) {
285                 rte_errno = EINVAL;
286                 return -rte_errno;
287         }
288         pmc->addr = &cqe->op_own;
289         pmc->opaque[CLB_VAL_IDX] = !!idx;
290         pmc->opaque[CLB_MSK_IDX] = MLX5_CQE_OWNER_MASK;
291         pmc->fn = mlx5_monitor_callback;
292         pmc->size = sizeof(uint8_t);
293         return 0;
294 }
295
296 /**
297  * Translate RX completion flags to packet type.
298  *
299  * @param[in] rxq
300  *   Pointer to RX queue structure.
301  * @param[in] cqe
302  *   Pointer to CQE.
303  *
304  * @note: fix mlx5_dev_supported_ptypes_get() if any change here.
305  *
306  * @return
307  *   Packet type for struct rte_mbuf.
308  */
309 static inline uint32_t
310 rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
311                                    volatile struct mlx5_mini_cqe8 *mcqe)
312 {
313         uint8_t idx;
314         uint8_t ptype;
315         uint8_t pinfo = (cqe->pkt_info & 0x3) << 6;
316
317         /* Get l3/l4 header from mini-CQE in case L3/L4 format*/
318         if (mcqe == NULL ||
319             rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
320                 ptype = (cqe->hdr_type_etc & 0xfc00) >> 10;
321         else
322                 ptype = mcqe->hdr_type >> 2;
323         /*
324          * The index to the array should have:
325          * bit[1:0] = l3_hdr_type
326          * bit[4:2] = l4_hdr_type
327          * bit[5] = ip_frag
328          * bit[6] = tunneled
329          * bit[7] = outer_l3_type
330          */
331         idx = pinfo | ptype;
332         return mlx5_ptype_table[idx] | rxq->tunnel * !!(idx & (1 << 6));
333 }
334
335 /**
336  * Initialize Rx WQ and indexes.
337  *
338  * @param[in] rxq
339  *   Pointer to RX queue structure.
340  */
341 void
342 mlx5_rxq_initialize(struct mlx5_rxq_data *rxq)
343 {
344         const unsigned int wqe_n = 1 << rxq->elts_n;
345         unsigned int i;
346
347         for (i = 0; (i != wqe_n); ++i) {
348                 volatile struct mlx5_wqe_data_seg *scat;
349                 uintptr_t addr;
350                 uint32_t byte_count;
351
352                 if (mlx5_rxq_mprq_enabled(rxq)) {
353                         struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[i];
354
355                         scat = &((volatile struct mlx5_wqe_mprq *)
356                                 rxq->wqes)[i].dseg;
357                         addr = (uintptr_t)mlx5_mprq_buf_addr(buf,
358                                                          1 << rxq->strd_num_n);
359                         byte_count = (1 << rxq->strd_sz_n) *
360                                         (1 << rxq->strd_num_n);
361                 } else {
362                         struct rte_mbuf *buf = (*rxq->elts)[i];
363
364                         scat = &((volatile struct mlx5_wqe_data_seg *)
365                                         rxq->wqes)[i];
366                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
367                         byte_count = DATA_LEN(buf);
368                 }
369                 /* scat->addr must be able to store a pointer. */
370                 MLX5_ASSERT(sizeof(scat->addr) >= sizeof(uintptr_t));
371                 *scat = (struct mlx5_wqe_data_seg){
372                         .addr = rte_cpu_to_be_64(addr),
373                         .byte_count = rte_cpu_to_be_32(byte_count),
374                         .lkey = mlx5_rx_addr2mr(rxq, addr),
375                 };
376         }
377         rxq->consumed_strd = 0;
378         rxq->decompressed = 0;
379         rxq->rq_pi = 0;
380         rxq->zip = (struct rxq_zip){
381                 .ai = 0,
382         };
383         rxq->elts_ci = mlx5_rxq_mprq_enabled(rxq) ?
384                 (wqe_n >> rxq->sges_n) * (1 << rxq->strd_num_n) : 0;
385         /* Update doorbell counter. */
386         rxq->rq_ci = wqe_n >> rxq->sges_n;
387         rte_io_wmb();
388         *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
389 }
390
391 /**
392  * Handle a Rx error.
393  * The function inserts the RQ state to reset when the first error CQE is
394  * shown, then drains the CQ by the caller function loop. When the CQ is empty,
395  * it moves the RQ state to ready and initializes the RQ.
396  * Next CQE identification and error counting are in the caller responsibility.
397  *
398  * @param[in] rxq
399  *   Pointer to RX queue structure.
400  * @param[in] vec
401  *   1 when called from vectorized Rx burst, need to prepare mbufs for the RQ.
402  *   0 when called from non-vectorized Rx burst.
403  *
404  * @return
405  *   -1 in case of recovery error, otherwise the CQE status.
406  */
407 int
408 mlx5_rx_err_handle(struct mlx5_rxq_data *rxq, uint8_t vec)
409 {
410         const uint16_t cqe_n = 1 << rxq->cqe_n;
411         const uint16_t cqe_mask = cqe_n - 1;
412         const uint16_t wqe_n = 1 << rxq->elts_n;
413         const uint16_t strd_n = 1 << rxq->strd_num_n;
414         struct mlx5_rxq_ctrl *rxq_ctrl =
415                         container_of(rxq, struct mlx5_rxq_ctrl, rxq);
416         union {
417                 volatile struct mlx5_cqe *cqe;
418                 volatile struct mlx5_err_cqe *err_cqe;
419         } u = {
420                 .cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask],
421         };
422         struct mlx5_mp_arg_queue_state_modify sm;
423         int ret;
424
425         switch (rxq->err_state) {
426         case MLX5_RXQ_ERR_STATE_NO_ERROR:
427                 rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_RESET;
428                 /* Fall-through */
429         case MLX5_RXQ_ERR_STATE_NEED_RESET:
430                 sm.is_wq = 1;
431                 sm.queue_id = rxq->idx;
432                 sm.state = IBV_WQS_RESET;
433                 if (mlx5_queue_state_modify(RXQ_DEV(rxq_ctrl), &sm))
434                         return -1;
435                 if (rxq_ctrl->dump_file_n <
436                     RXQ_PORT(rxq_ctrl)->config.max_dump_files_num) {
437                         MKSTR(err_str, "Unexpected CQE error syndrome "
438                               "0x%02x CQN = %u RQN = %u wqe_counter = %u"
439                               " rq_ci = %u cq_ci = %u", u.err_cqe->syndrome,
440                               rxq->cqn, rxq_ctrl->wqn,
441                               rte_be_to_cpu_16(u.err_cqe->wqe_counter),
442                               rxq->rq_ci << rxq->sges_n, rxq->cq_ci);
443                         MKSTR(name, "dpdk_mlx5_port_%u_rxq_%u_%u",
444                               rxq->port_id, rxq->idx, (uint32_t)rte_rdtsc());
445                         mlx5_dump_debug_information(name, NULL, err_str, 0);
446                         mlx5_dump_debug_information(name, "MLX5 Error CQ:",
447                                                     (const void *)((uintptr_t)
448                                                                     rxq->cqes),
449                                                     sizeof(*u.cqe) * cqe_n);
450                         mlx5_dump_debug_information(name, "MLX5 Error RQ:",
451                                                     (const void *)((uintptr_t)
452                                                                     rxq->wqes),
453                                                     16 * wqe_n);
454                         rxq_ctrl->dump_file_n++;
455                 }
456                 rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_READY;
457                 /* Fall-through */
458         case MLX5_RXQ_ERR_STATE_NEED_READY:
459                 ret = check_cqe(u.cqe, cqe_n, rxq->cq_ci);
460                 if (ret == MLX5_CQE_STATUS_HW_OWN) {
461                         rte_io_wmb();
462                         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
463                         rte_io_wmb();
464                         /*
465                          * The RQ consumer index must be zeroed while moving
466                          * from RESET state to RDY state.
467                          */
468                         *rxq->rq_db = rte_cpu_to_be_32(0);
469                         rte_io_wmb();
470                         sm.is_wq = 1;
471                         sm.queue_id = rxq->idx;
472                         sm.state = IBV_WQS_RDY;
473                         if (mlx5_queue_state_modify(RXQ_DEV(rxq_ctrl), &sm))
474                                 return -1;
475                         if (vec) {
476                                 const uint32_t elts_n =
477                                         mlx5_rxq_mprq_enabled(rxq) ?
478                                         wqe_n * strd_n : wqe_n;
479                                 const uint32_t e_mask = elts_n - 1;
480                                 uint32_t elts_ci =
481                                         mlx5_rxq_mprq_enabled(rxq) ?
482                                         rxq->elts_ci : rxq->rq_ci;
483                                 uint32_t elt_idx;
484                                 struct rte_mbuf **elt;
485                                 int i;
486                                 unsigned int n = elts_n - (elts_ci -
487                                                           rxq->rq_pi);
488
489                                 for (i = 0; i < (int)n; ++i) {
490                                         elt_idx = (elts_ci + i) & e_mask;
491                                         elt = &(*rxq->elts)[elt_idx];
492                                         *elt = rte_mbuf_raw_alloc(rxq->mp);
493                                         if (!*elt) {
494                                                 for (i--; i >= 0; --i) {
495                                                         elt_idx = (elts_ci +
496                                                                    i) & elts_n;
497                                                         elt = &(*rxq->elts)
498                                                                 [elt_idx];
499                                                         rte_pktmbuf_free_seg
500                                                                 (*elt);
501                                                 }
502                                                 return -1;
503                                         }
504                                 }
505                                 for (i = 0; i < (int)elts_n; ++i) {
506                                         elt = &(*rxq->elts)[i];
507                                         DATA_LEN(*elt) =
508                                                 (uint16_t)((*elt)->buf_len -
509                                                 rte_pktmbuf_headroom(*elt));
510                                 }
511                                 /* Padding with a fake mbuf for vec Rx. */
512                                 for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i)
513                                         (*rxq->elts)[elts_n + i] =
514                                                                 &rxq->fake_mbuf;
515                         }
516                         mlx5_rxq_initialize(rxq);
517                         rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR;
518                 }
519                 return ret;
520         default:
521                 return -1;
522         }
523 }
524
525 /**
526  * Get size of the next packet for a given CQE. For compressed CQEs, the
527  * consumer index is updated only once all packets of the current one have
528  * been processed.
529  *
530  * @param rxq
531  *   Pointer to RX queue.
532  * @param cqe
533  *   CQE to process.
534  * @param[out] mcqe
535  *   Store pointer to mini-CQE if compressed. Otherwise, the pointer is not
536  *   written.
537  *
538  * @return
539  *   0 in case of empty CQE, otherwise the packet size in bytes.
540  */
541 static inline int
542 mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
543                  uint16_t cqe_cnt, volatile struct mlx5_mini_cqe8 **mcqe)
544 {
545         struct rxq_zip *zip = &rxq->zip;
546         uint16_t cqe_n = cqe_cnt + 1;
547         int len;
548         uint16_t idx, end;
549
550         do {
551                 len = 0;
552                 /* Process compressed data in the CQE and mini arrays. */
553                 if (zip->ai) {
554                         volatile struct mlx5_mini_cqe8 (*mc)[8] =
555                                 (volatile struct mlx5_mini_cqe8 (*)[8])
556                                 (uintptr_t)(&(*rxq->cqes)[zip->ca &
557                                                           cqe_cnt].pkt_info);
558                         len = rte_be_to_cpu_32((*mc)[zip->ai & 7].byte_cnt &
559                                                rxq->byte_mask);
560                         *mcqe = &(*mc)[zip->ai & 7];
561                         if ((++zip->ai & 7) == 0) {
562                                 /* Invalidate consumed CQEs */
563                                 idx = zip->ca;
564                                 end = zip->na;
565                                 while (idx != end) {
566                                         (*rxq->cqes)[idx & cqe_cnt].op_own =
567                                                 MLX5_CQE_INVALIDATE;
568                                         ++idx;
569                                 }
570                                 /*
571                                  * Increment consumer index to skip the number
572                                  * of CQEs consumed. Hardware leaves holes in
573                                  * the CQ ring for software use.
574                                  */
575                                 zip->ca = zip->na;
576                                 zip->na += 8;
577                         }
578                         if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
579                                 /* Invalidate the rest */
580                                 idx = zip->ca;
581                                 end = zip->cq_ci;
582
583                                 while (idx != end) {
584                                         (*rxq->cqes)[idx & cqe_cnt].op_own =
585                                                 MLX5_CQE_INVALIDATE;
586                                         ++idx;
587                                 }
588                                 rxq->cq_ci = zip->cq_ci;
589                                 zip->ai = 0;
590                         }
591                 /*
592                  * No compressed data, get next CQE and verify if it is
593                  * compressed.
594                  */
595                 } else {
596                         int ret;
597                         int8_t op_own;
598                         uint32_t cq_ci;
599
600                         ret = check_cqe(cqe, cqe_n, rxq->cq_ci);
601                         if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
602                                 if (unlikely(ret == MLX5_CQE_STATUS_ERR ||
603                                              rxq->err_state)) {
604                                         ret = mlx5_rx_err_handle(rxq, 0);
605                                         if (ret == MLX5_CQE_STATUS_HW_OWN ||
606                                             ret == -1)
607                                                 return 0;
608                                 } else {
609                                         return 0;
610                                 }
611                         }
612                         /*
613                          * Introduce the local variable to have queue cq_ci
614                          * index in queue structure always consistent with
615                          * actual CQE boundary (not pointing to the middle
616                          * of compressed CQE session).
617                          */
618                         cq_ci = rxq->cq_ci + 1;
619                         op_own = cqe->op_own;
620                         if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
621                                 volatile struct mlx5_mini_cqe8 (*mc)[8] =
622                                         (volatile struct mlx5_mini_cqe8 (*)[8])
623                                         (uintptr_t)(&(*rxq->cqes)
624                                                 [cq_ci & cqe_cnt].pkt_info);
625
626                                 /* Fix endianness. */
627                                 zip->cqe_cnt = rte_be_to_cpu_32(cqe->byte_cnt);
628                                 /*
629                                  * Current mini array position is the one
630                                  * returned by check_cqe64().
631                                  *
632                                  * If completion comprises several mini arrays,
633                                  * as a special case the second one is located
634                                  * 7 CQEs after the initial CQE instead of 8
635                                  * for subsequent ones.
636                                  */
637                                 zip->ca = cq_ci;
638                                 zip->na = zip->ca + 7;
639                                 /* Compute the next non compressed CQE. */
640                                 zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
641                                 /* Get packet size to return. */
642                                 len = rte_be_to_cpu_32((*mc)[0].byte_cnt &
643                                                        rxq->byte_mask);
644                                 *mcqe = &(*mc)[0];
645                                 zip->ai = 1;
646                                 /* Prefetch all to be invalidated */
647                                 idx = zip->ca;
648                                 end = zip->cq_ci;
649                                 while (idx != end) {
650                                         rte_prefetch0(&(*rxq->cqes)[(idx) &
651                                                                     cqe_cnt]);
652                                         ++idx;
653                                 }
654                         } else {
655                                 rxq->cq_ci = cq_ci;
656                                 len = rte_be_to_cpu_32(cqe->byte_cnt);
657                         }
658                 }
659                 if (unlikely(rxq->err_state)) {
660                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
661                         ++rxq->stats.idropped;
662                 } else {
663                         return len;
664                 }
665         } while (1);
666 }
667
668 /**
669  * Translate RX completion flags to offload flags.
670  *
671  * @param[in] cqe
672  *   Pointer to CQE.
673  *
674  * @return
675  *   Offload flags (ol_flags) for struct rte_mbuf.
676  */
677 static inline uint32_t
678 rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe)
679 {
680         uint32_t ol_flags = 0;
681         uint16_t flags = rte_be_to_cpu_16(cqe->hdr_type_etc);
682
683         ol_flags =
684                 TRANSPOSE(flags,
685                           MLX5_CQE_RX_L3_HDR_VALID,
686                           RTE_MBUF_F_RX_IP_CKSUM_GOOD) |
687                 TRANSPOSE(flags,
688                           MLX5_CQE_RX_L4_HDR_VALID,
689                           RTE_MBUF_F_RX_L4_CKSUM_GOOD);
690         return ol_flags;
691 }
692
693 /**
694  * Fill in mbuf fields from RX completion flags.
695  * Note that pkt->ol_flags should be initialized outside of this function.
696  *
697  * @param rxq
698  *   Pointer to RX queue.
699  * @param pkt
700  *   mbuf to fill.
701  * @param cqe
702  *   CQE to process.
703  * @param rss_hash_res
704  *   Packet RSS Hash result.
705  */
706 static inline void
707 rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
708                volatile struct mlx5_cqe *cqe,
709                volatile struct mlx5_mini_cqe8 *mcqe)
710 {
711         /* Update packet information. */
712         pkt->packet_type = rxq_cq_to_pkt_type(rxq, cqe, mcqe);
713
714         if (rxq->rss_hash) {
715                 uint32_t rss_hash_res = 0;
716
717                 /* If compressed, take hash result from mini-CQE. */
718                 if (mcqe == NULL ||
719                     rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_HASH)
720                         rss_hash_res = rte_be_to_cpu_32(cqe->rx_hash_res);
721                 else
722                         rss_hash_res = rte_be_to_cpu_32(mcqe->rx_hash_result);
723                 if (rss_hash_res) {
724                         pkt->hash.rss = rss_hash_res;
725                         pkt->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
726                 }
727         }
728         if (rxq->mark) {
729                 uint32_t mark = 0;
730
731                 /* If compressed, take flow tag from mini-CQE. */
732                 if (mcqe == NULL ||
733                     rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_FTAG_STRIDX)
734                         mark = cqe->sop_drop_qpn;
735                 else
736                         mark = ((mcqe->byte_cnt_flow & 0xff) << 8) |
737                                 (mcqe->flow_tag_high << 16);
738                 if (MLX5_FLOW_MARK_IS_VALID(mark)) {
739                         pkt->ol_flags |= RTE_MBUF_F_RX_FDIR;
740                         if (mark != RTE_BE32(MLX5_FLOW_MARK_DEFAULT)) {
741                                 pkt->ol_flags |= RTE_MBUF_F_RX_FDIR_ID;
742                                 pkt->hash.fdir.hi = mlx5_flow_mark_get(mark);
743                         }
744                 }
745         }
746         if (rxq->dynf_meta) {
747                 uint32_t meta = rte_be_to_cpu_32(cqe->flow_table_metadata) &
748                         rxq->flow_meta_port_mask;
749
750                 if (meta) {
751                         pkt->ol_flags |= rxq->flow_meta_mask;
752                         *RTE_MBUF_DYNFIELD(pkt, rxq->flow_meta_offset,
753                                                 uint32_t *) = meta;
754                 }
755         }
756         if (rxq->csum)
757                 pkt->ol_flags |= rxq_cq_to_ol_flags(cqe);
758         if (rxq->vlan_strip) {
759                 bool vlan_strip;
760
761                 if (mcqe == NULL ||
762                     rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
763                         vlan_strip = cqe->hdr_type_etc &
764                                      RTE_BE16(MLX5_CQE_VLAN_STRIPPED);
765                 else
766                         vlan_strip = mcqe->hdr_type &
767                                      RTE_BE16(MLX5_CQE_VLAN_STRIPPED);
768                 if (vlan_strip) {
769                         pkt->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
770                         pkt->vlan_tci = rte_be_to_cpu_16(cqe->vlan_info);
771                 }
772         }
773         if (rxq->hw_timestamp) {
774                 uint64_t ts = rte_be_to_cpu_64(cqe->timestamp);
775
776                 if (rxq->rt_timestamp)
777                         ts = mlx5_txpp_convert_rx_ts(rxq->sh, ts);
778                 mlx5_timestamp_set(pkt, rxq->timestamp_offset, ts);
779                 pkt->ol_flags |= rxq->timestamp_rx_flag;
780         }
781 }
782
783 /**
784  * DPDK callback for RX.
785  *
786  * @param dpdk_rxq
787  *   Generic pointer to RX queue structure.
788  * @param[out] pkts
789  *   Array to store received packets.
790  * @param pkts_n
791  *   Maximum number of packets in array.
792  *
793  * @return
794  *   Number of packets successfully received (<= pkts_n).
795  */
796 uint16_t
797 mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
798 {
799         struct mlx5_rxq_data *rxq = dpdk_rxq;
800         const unsigned int wqe_cnt = (1 << rxq->elts_n) - 1;
801         const unsigned int cqe_cnt = (1 << rxq->cqe_n) - 1;
802         const unsigned int sges_n = rxq->sges_n;
803         struct rte_mbuf *pkt = NULL;
804         struct rte_mbuf *seg = NULL;
805         volatile struct mlx5_cqe *cqe =
806                 &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
807         unsigned int i = 0;
808         unsigned int rq_ci = rxq->rq_ci << sges_n;
809         int len = 0; /* keep its value across iterations. */
810
811         while (pkts_n) {
812                 unsigned int idx = rq_ci & wqe_cnt;
813                 volatile struct mlx5_wqe_data_seg *wqe =
814                         &((volatile struct mlx5_wqe_data_seg *)rxq->wqes)[idx];
815                 struct rte_mbuf *rep = (*rxq->elts)[idx];
816                 volatile struct mlx5_mini_cqe8 *mcqe = NULL;
817
818                 if (pkt)
819                         NEXT(seg) = rep;
820                 seg = rep;
821                 rte_prefetch0(seg);
822                 rte_prefetch0(cqe);
823                 rte_prefetch0(wqe);
824                 /* Allocate the buf from the same pool. */
825                 rep = rte_mbuf_raw_alloc(seg->pool);
826                 if (unlikely(rep == NULL)) {
827                         ++rxq->stats.rx_nombuf;
828                         if (!pkt) {
829                                 /*
830                                  * no buffers before we even started,
831                                  * bail out silently.
832                                  */
833                                 break;
834                         }
835                         while (pkt != seg) {
836                                 MLX5_ASSERT(pkt != (*rxq->elts)[idx]);
837                                 rep = NEXT(pkt);
838                                 NEXT(pkt) = NULL;
839                                 NB_SEGS(pkt) = 1;
840                                 rte_mbuf_raw_free(pkt);
841                                 pkt = rep;
842                         }
843                         rq_ci >>= sges_n;
844                         ++rq_ci;
845                         rq_ci <<= sges_n;
846                         break;
847                 }
848                 if (!pkt) {
849                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
850                         len = mlx5_rx_poll_len(rxq, cqe, cqe_cnt, &mcqe);
851                         if (!len) {
852                                 rte_mbuf_raw_free(rep);
853                                 break;
854                         }
855                         pkt = seg;
856                         MLX5_ASSERT(len >= (rxq->crc_present << 2));
857                         pkt->ol_flags &= RTE_MBUF_F_EXTERNAL;
858                         rxq_cq_to_mbuf(rxq, pkt, cqe, mcqe);
859                         if (rxq->crc_present)
860                                 len -= RTE_ETHER_CRC_LEN;
861                         PKT_LEN(pkt) = len;
862                         if (cqe->lro_num_seg > 1) {
863                                 mlx5_lro_update_hdr
864                                         (rte_pktmbuf_mtod(pkt, uint8_t *), cqe,
865                                          mcqe, rxq, len);
866                                 pkt->ol_flags |= RTE_MBUF_F_RX_LRO;
867                                 pkt->tso_segsz = len / cqe->lro_num_seg;
868                         }
869                 }
870                 DATA_LEN(rep) = DATA_LEN(seg);
871                 PKT_LEN(rep) = PKT_LEN(seg);
872                 SET_DATA_OFF(rep, DATA_OFF(seg));
873                 PORT(rep) = PORT(seg);
874                 (*rxq->elts)[idx] = rep;
875                 /*
876                  * Fill NIC descriptor with the new buffer. The lkey and size
877                  * of the buffers are already known, only the buffer address
878                  * changes.
879                  */
880                 wqe->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(rep, uintptr_t));
881                 /* If there's only one MR, no need to replace LKey in WQE. */
882                 if (unlikely(mlx5_mr_btree_len(&rxq->mr_ctrl.cache_bh) > 1))
883                         wqe->lkey = mlx5_rx_mb2mr(rxq, rep);
884                 if (len > DATA_LEN(seg)) {
885                         len -= DATA_LEN(seg);
886                         ++NB_SEGS(pkt);
887                         ++rq_ci;
888                         continue;
889                 }
890                 DATA_LEN(seg) = len;
891 #ifdef MLX5_PMD_SOFT_COUNTERS
892                 /* Increment bytes counter. */
893                 rxq->stats.ibytes += PKT_LEN(pkt);
894 #endif
895                 /* Return packet. */
896                 *(pkts++) = pkt;
897                 pkt = NULL;
898                 --pkts_n;
899                 ++i;
900                 /* Align consumer index to the next stride. */
901                 rq_ci >>= sges_n;
902                 ++rq_ci;
903                 rq_ci <<= sges_n;
904         }
905         if (unlikely(i == 0 && ((rq_ci >> sges_n) == rxq->rq_ci)))
906                 return 0;
907         /* Update the consumer index. */
908         rxq->rq_ci = rq_ci >> sges_n;
909         rte_io_wmb();
910         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
911         rte_io_wmb();
912         *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
913 #ifdef MLX5_PMD_SOFT_COUNTERS
914         /* Increment packets counter. */
915         rxq->stats.ipackets += i;
916 #endif
917         return i;
918 }
919
920 /**
921  * Update LRO packet TCP header.
922  * The HW LRO feature doesn't update the TCP header after coalescing the
923  * TCP segments but supplies information in CQE to fill it by SW.
924  *
925  * @param tcp
926  *   Pointer to the TCP header.
927  * @param cqe
928  *   Pointer to the completion entry.
929  * @param phcsum
930  *   The L3 pseudo-header checksum.
931  */
932 static inline void
933 mlx5_lro_update_tcp_hdr(struct rte_tcp_hdr *__rte_restrict tcp,
934                         volatile struct mlx5_cqe *__rte_restrict cqe,
935                         uint32_t phcsum, uint8_t l4_type)
936 {
937         /*
938          * The HW calculates only the TCP payload checksum, need to complete
939          * the TCP header checksum and the L3 pseudo-header checksum.
940          */
941         uint32_t csum = phcsum + cqe->csum;
942
943         if (l4_type == MLX5_L4_HDR_TYPE_TCP_EMPTY_ACK ||
944             l4_type == MLX5_L4_HDR_TYPE_TCP_WITH_ACL) {
945                 tcp->tcp_flags |= RTE_TCP_ACK_FLAG;
946                 tcp->recv_ack = cqe->lro_ack_seq_num;
947                 tcp->rx_win = cqe->lro_tcp_win;
948         }
949         if (cqe->lro_tcppsh_abort_dupack & MLX5_CQE_LRO_PUSH_MASK)
950                 tcp->tcp_flags |= RTE_TCP_PSH_FLAG;
951         tcp->cksum = 0;
952         csum += rte_raw_cksum(tcp, (tcp->data_off >> 4) * 4);
953         csum = ((csum & 0xffff0000) >> 16) + (csum & 0xffff);
954         csum = (~csum) & 0xffff;
955         if (csum == 0)
956                 csum = 0xffff;
957         tcp->cksum = csum;
958 }
959
960 /**
961  * Update LRO packet headers.
962  * The HW LRO feature doesn't update the L3/TCP headers after coalescing the
963  * TCP segments but supply information in CQE to fill it by SW.
964  *
965  * @param padd
966  *   The packet address.
967  * @param cqe
968  *   Pointer to the completion entry.
969  * @param len
970  *   The packet length.
971  */
972 static inline void
973 mlx5_lro_update_hdr(uint8_t *__rte_restrict padd,
974                     volatile struct mlx5_cqe *__rte_restrict cqe,
975                     volatile struct mlx5_mini_cqe8 *mcqe,
976                     struct mlx5_rxq_data *rxq, uint32_t len)
977 {
978         union {
979                 struct rte_ether_hdr *eth;
980                 struct rte_vlan_hdr *vlan;
981                 struct rte_ipv4_hdr *ipv4;
982                 struct rte_ipv6_hdr *ipv6;
983                 struct rte_tcp_hdr *tcp;
984                 uint8_t *hdr;
985         } h = {
986                 .hdr = padd,
987         };
988         uint16_t proto = h.eth->ether_type;
989         uint32_t phcsum;
990         uint8_t l4_type;
991
992         h.eth++;
993         while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
994                proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
995                 proto = h.vlan->eth_proto;
996                 h.vlan++;
997         }
998         if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
999                 h.ipv4->time_to_live = cqe->lro_min_ttl;
1000                 h.ipv4->total_length = rte_cpu_to_be_16(len - (h.hdr - padd));
1001                 h.ipv4->hdr_checksum = 0;
1002                 h.ipv4->hdr_checksum = rte_ipv4_cksum(h.ipv4);
1003                 phcsum = rte_ipv4_phdr_cksum(h.ipv4, 0);
1004                 h.ipv4++;
1005         } else {
1006                 h.ipv6->hop_limits = cqe->lro_min_ttl;
1007                 h.ipv6->payload_len = rte_cpu_to_be_16(len - (h.hdr - padd) -
1008                                                        sizeof(*h.ipv6));
1009                 phcsum = rte_ipv6_phdr_cksum(h.ipv6, 0);
1010                 h.ipv6++;
1011         }
1012         if (mcqe == NULL ||
1013             rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
1014                 l4_type = (rte_be_to_cpu_16(cqe->hdr_type_etc) &
1015                            MLX5_CQE_L4_TYPE_MASK) >> MLX5_CQE_L4_TYPE_SHIFT;
1016         else
1017                 l4_type = (rte_be_to_cpu_16(mcqe->hdr_type) &
1018                            MLX5_CQE_L4_TYPE_MASK) >> MLX5_CQE_L4_TYPE_SHIFT;
1019         mlx5_lro_update_tcp_hdr(h.tcp, cqe, phcsum, l4_type);
1020 }
1021
1022 void
1023 mlx5_mprq_buf_free(struct mlx5_mprq_buf *buf)
1024 {
1025         mlx5_mprq_buf_free_cb(NULL, buf);
1026 }
1027
1028 /**
1029  * DPDK callback for RX with Multi-Packet RQ support.
1030  *
1031  * @param dpdk_rxq
1032  *   Generic pointer to RX queue structure.
1033  * @param[out] pkts
1034  *   Array to store received packets.
1035  * @param pkts_n
1036  *   Maximum number of packets in array.
1037  *
1038  * @return
1039  *   Number of packets successfully received (<= pkts_n).
1040  */
1041 uint16_t
1042 mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1043 {
1044         struct mlx5_rxq_data *rxq = dpdk_rxq;
1045         const uint32_t strd_n = 1 << rxq->strd_num_n;
1046         const uint32_t strd_sz = 1 << rxq->strd_sz_n;
1047         const uint32_t cq_mask = (1 << rxq->cqe_n) - 1;
1048         const uint32_t wq_mask = (1 << rxq->elts_n) - 1;
1049         volatile struct mlx5_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask];
1050         unsigned int i = 0;
1051         uint32_t rq_ci = rxq->rq_ci;
1052         uint16_t consumed_strd = rxq->consumed_strd;
1053         struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[rq_ci & wq_mask];
1054
1055         while (i < pkts_n) {
1056                 struct rte_mbuf *pkt;
1057                 int ret;
1058                 uint32_t len;
1059                 uint16_t strd_cnt;
1060                 uint16_t strd_idx;
1061                 uint32_t byte_cnt;
1062                 volatile struct mlx5_mini_cqe8 *mcqe = NULL;
1063                 enum mlx5_rqx_code rxq_code;
1064
1065                 if (consumed_strd == strd_n) {
1066                         /* Replace WQE if the buffer is still in use. */
1067                         mprq_buf_replace(rxq, rq_ci & wq_mask);
1068                         /* Advance to the next WQE. */
1069                         consumed_strd = 0;
1070                         ++rq_ci;
1071                         buf = (*rxq->mprq_bufs)[rq_ci & wq_mask];
1072                 }
1073                 cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask];
1074                 ret = mlx5_rx_poll_len(rxq, cqe, cq_mask, &mcqe);
1075                 if (!ret)
1076                         break;
1077                 byte_cnt = ret;
1078                 len = (byte_cnt & MLX5_MPRQ_LEN_MASK) >> MLX5_MPRQ_LEN_SHIFT;
1079                 MLX5_ASSERT((int)len >= (rxq->crc_present << 2));
1080                 if (rxq->crc_present)
1081                         len -= RTE_ETHER_CRC_LEN;
1082                 if (mcqe &&
1083                     rxq->mcqe_format == MLX5_CQE_RESP_FORMAT_FTAG_STRIDX)
1084                         strd_cnt = (len / strd_sz) + !!(len % strd_sz);
1085                 else
1086                         strd_cnt = (byte_cnt & MLX5_MPRQ_STRIDE_NUM_MASK) >>
1087                                    MLX5_MPRQ_STRIDE_NUM_SHIFT;
1088                 MLX5_ASSERT(strd_cnt);
1089                 consumed_strd += strd_cnt;
1090                 if (byte_cnt & MLX5_MPRQ_FILLER_MASK)
1091                         continue;
1092                 strd_idx = rte_be_to_cpu_16(mcqe == NULL ?
1093                                         cqe->wqe_counter :
1094                                         mcqe->stride_idx);
1095                 MLX5_ASSERT(strd_idx < strd_n);
1096                 MLX5_ASSERT(!((rte_be_to_cpu_16(cqe->wqe_id) ^ rq_ci) &
1097                             wq_mask));
1098                 pkt = rte_pktmbuf_alloc(rxq->mp);
1099                 if (unlikely(pkt == NULL)) {
1100                         ++rxq->stats.rx_nombuf;
1101                         break;
1102                 }
1103                 len = (byte_cnt & MLX5_MPRQ_LEN_MASK) >> MLX5_MPRQ_LEN_SHIFT;
1104                 MLX5_ASSERT((int)len >= (rxq->crc_present << 2));
1105                 if (rxq->crc_present)
1106                         len -= RTE_ETHER_CRC_LEN;
1107                 rxq_code = mprq_buf_to_pkt(rxq, pkt, len, buf,
1108                                            strd_idx, strd_cnt);
1109                 if (unlikely(rxq_code != MLX5_RXQ_CODE_EXIT)) {
1110                         rte_pktmbuf_free_seg(pkt);
1111                         if (rxq_code == MLX5_RXQ_CODE_DROPPED) {
1112                                 ++rxq->stats.idropped;
1113                                 continue;
1114                         }
1115                         if (rxq_code == MLX5_RXQ_CODE_NOMBUF) {
1116                                 ++rxq->stats.rx_nombuf;
1117                                 break;
1118                         }
1119                 }
1120                 rxq_cq_to_mbuf(rxq, pkt, cqe, mcqe);
1121                 if (cqe->lro_num_seg > 1) {
1122                         mlx5_lro_update_hdr(rte_pktmbuf_mtod(pkt, uint8_t *),
1123                                             cqe, mcqe, rxq, len);
1124                         pkt->ol_flags |= RTE_MBUF_F_RX_LRO;
1125                         pkt->tso_segsz = len / cqe->lro_num_seg;
1126                 }
1127                 PKT_LEN(pkt) = len;
1128                 PORT(pkt) = rxq->port_id;
1129 #ifdef MLX5_PMD_SOFT_COUNTERS
1130                 /* Increment bytes counter. */
1131                 rxq->stats.ibytes += PKT_LEN(pkt);
1132 #endif
1133                 /* Return packet. */
1134                 *(pkts++) = pkt;
1135                 ++i;
1136         }
1137         /* Update the consumer indexes. */
1138         rxq->consumed_strd = consumed_strd;
1139         rte_io_wmb();
1140         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
1141         if (rq_ci != rxq->rq_ci) {
1142                 rxq->rq_ci = rq_ci;
1143                 rte_io_wmb();
1144                 *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
1145         }
1146 #ifdef MLX5_PMD_SOFT_COUNTERS
1147         /* Increment packets counter. */
1148         rxq->stats.ipackets += i;
1149 #endif
1150         return i;
1151 }
1152
1153 /**
1154  * Dummy DPDK callback for RX.
1155  *
1156  * This function is used to temporarily replace the real callback during
1157  * unsafe control operations on the queue, or in case of error.
1158  *
1159  * @param dpdk_rxq
1160  *   Generic pointer to RX queue structure.
1161  * @param[out] pkts
1162  *   Array to store received packets.
1163  * @param pkts_n
1164  *   Maximum number of packets in array.
1165  *
1166  * @return
1167  *   Number of packets successfully received (<= pkts_n).
1168  */
1169 uint16_t
1170 removed_rx_burst(void *dpdk_rxq __rte_unused,
1171                  struct rte_mbuf **pkts __rte_unused,
1172                  uint16_t pkts_n __rte_unused)
1173 {
1174         rte_mb();
1175         return 0;
1176 }
1177
1178 /*
1179  * Vectorized Rx routines are not compiled in when required vector instructions
1180  * are not supported on a target architecture.
1181  * The following null stubs are needed for linkage when those are not included
1182  * outside of this file (e.g. mlx5_rxtx_vec_sse.c for x86).
1183  */
1184
1185 __rte_weak uint16_t
1186 mlx5_rx_burst_vec(void *dpdk_rxq __rte_unused,
1187                   struct rte_mbuf **pkts __rte_unused,
1188                   uint16_t pkts_n __rte_unused)
1189 {
1190         return 0;
1191 }
1192
1193 __rte_weak uint16_t
1194 mlx5_rx_burst_mprq_vec(void *dpdk_rxq __rte_unused,
1195                        struct rte_mbuf **pkts __rte_unused,
1196                        uint16_t pkts_n __rte_unused)
1197 {
1198         return 0;
1199 }
1200
1201 __rte_weak int
1202 mlx5_rxq_check_vec_support(struct mlx5_rxq_data *rxq __rte_unused)
1203 {
1204         return -ENOTSUP;
1205 }
1206
1207 __rte_weak int
1208 mlx5_check_vec_rx_support(struct rte_eth_dev *dev __rte_unused)
1209 {
1210         return -ENOTSUP;
1211 }
1212