xref: /dpdk/drivers/net/mlx5/mlx5_rx.c (revision 8b8036a66e3d59ffa58afb8d96fa2c73262155a7)
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_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, rx_queue_id);
152 	struct mlx5_rxq_data *rxq = mlx5_rxq_data_get(dev, rx_queue_id);
153 
154 	if (!rxq)
155 		return;
156 	qinfo->mp = mlx5_rxq_mprq_enabled(rxq) ?
157 					rxq->mprq_mp : rxq->mp;
158 	qinfo->conf.rx_thresh.pthresh = 0;
159 	qinfo->conf.rx_thresh.hthresh = 0;
160 	qinfo->conf.rx_thresh.wthresh = 0;
161 	qinfo->conf.rx_free_thresh = rxq->rq_repl_thresh;
162 	qinfo->conf.rx_drop_en = 1;
163 	if (rxq_ctrl == NULL || rxq_ctrl->obj == NULL)
164 		qinfo->conf.rx_deferred_start = 0;
165 	else
166 		qinfo->conf.rx_deferred_start = 1;
167 	qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads;
168 	qinfo->scattered_rx = dev->data->scattered_rx;
169 	qinfo->nb_desc = mlx5_rxq_mprq_enabled(rxq) ?
170 		(1 << rxq->elts_n) * (1 << rxq->strd_num_n) :
171 		(1 << rxq->elts_n);
172 }
173 
174 /**
175  * DPDK callback to get the RX packet burst mode information.
176  *
177  * @param dev
178  *   Pointer to the device structure.
179  *
180  * @param rx_queue_id
181  *   Rx queue identificatior.
182  *
183  * @param mode
184  *   Pointer to the burts mode information.
185  *
186  * @return
187  *   0 as success, -EINVAL as failure.
188  */
189 int
190 mlx5_rx_burst_mode_get(struct rte_eth_dev *dev,
191 		       uint16_t rx_queue_id __rte_unused,
192 		       struct rte_eth_burst_mode *mode)
193 {
194 	eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
195 	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, rx_queue_id);
196 
197 	if (!rxq) {
198 		rte_errno = EINVAL;
199 		return -rte_errno;
200 	}
201 	if (pkt_burst == mlx5_rx_burst) {
202 		snprintf(mode->info, sizeof(mode->info), "%s", "Scalar");
203 	} else if (pkt_burst == mlx5_rx_burst_mprq) {
204 		snprintf(mode->info, sizeof(mode->info), "%s", "Multi-Packet RQ");
205 	} else if (pkt_burst == mlx5_rx_burst_vec) {
206 #if defined RTE_ARCH_X86_64
207 		snprintf(mode->info, sizeof(mode->info), "%s", "Vector SSE");
208 #elif defined RTE_ARCH_ARM64
209 		snprintf(mode->info, sizeof(mode->info), "%s", "Vector Neon");
210 #elif defined RTE_ARCH_PPC_64
211 		snprintf(mode->info, sizeof(mode->info), "%s", "Vector AltiVec");
212 #else
213 		return -EINVAL;
214 #endif
215 	} else if (pkt_burst == mlx5_rx_burst_mprq_vec) {
216 #if defined RTE_ARCH_X86_64
217 		snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector SSE");
218 #elif defined RTE_ARCH_ARM64
219 		snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector Neon");
220 #elif defined RTE_ARCH_PPC_64
221 		snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector AltiVec");
222 #else
223 		return -EINVAL;
224 #endif
225 	} else {
226 		return -EINVAL;
227 	}
228 	return 0;
229 }
230 
231 /**
232  * DPDK callback to get the number of used descriptors in a RX queue.
233  *
234  * @param rx_queue
235  *   The Rx queue pointer.
236  *
237  * @return
238  *   The number of used rx descriptor.
239  *   -EINVAL if the queue is invalid
240  */
241 uint32_t
242 mlx5_rx_queue_count(void *rx_queue)
243 {
244 	struct mlx5_rxq_data *rxq = rx_queue;
245 	struct rte_eth_dev *dev;
246 
247 	if (!rxq) {
248 		rte_errno = EINVAL;
249 		return -rte_errno;
250 	}
251 
252 	dev = &rte_eth_devices[rxq->port_id];
253 
254 	if (dev->rx_pkt_burst == NULL ||
255 	    dev->rx_pkt_burst == removed_rx_burst) {
256 		rte_errno = ENOTSUP;
257 		return -rte_errno;
258 	}
259 
260 	return rx_queue_count(rxq);
261 }
262 
263 #define CLB_VAL_IDX 0
264 #define CLB_MSK_IDX 1
265 static int
266 mlx5_monitor_callback(const uint64_t value,
267 		const uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])
268 {
269 	const uint64_t m = opaque[CLB_MSK_IDX];
270 	const uint64_t v = opaque[CLB_VAL_IDX];
271 
272 	return (value & m) == v ? -1 : 0;
273 }
274 
275 int mlx5_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
276 {
277 	struct mlx5_rxq_data *rxq = rx_queue;
278 	const unsigned int cqe_num = 1 << rxq->cqe_n;
279 	const unsigned int cqe_mask = cqe_num - 1;
280 	const uint16_t idx = rxq->cq_ci & cqe_num;
281 	volatile struct mlx5_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
282 
283 	if (unlikely(rxq->cqes == NULL)) {
284 		rte_errno = EINVAL;
285 		return -rte_errno;
286 	}
287 	pmc->addr = &cqe->op_own;
288 	pmc->opaque[CLB_VAL_IDX] = !!idx;
289 	pmc->opaque[CLB_MSK_IDX] = MLX5_CQE_OWNER_MASK;
290 	pmc->fn = mlx5_monitor_callback;
291 	pmc->size = sizeof(uint8_t);
292 	return 0;
293 }
294 
295 /**
296  * Translate RX completion flags to packet type.
297  *
298  * @param[in] rxq
299  *   Pointer to RX queue structure.
300  * @param[in] cqe
301  *   Pointer to CQE.
302  *
303  * @note: fix mlx5_dev_supported_ptypes_get() if any change here.
304  *
305  * @return
306  *   Packet type for struct rte_mbuf.
307  */
308 static inline uint32_t
309 rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
310 				   volatile struct mlx5_mini_cqe8 *mcqe)
311 {
312 	uint8_t idx;
313 	uint8_t ptype;
314 	uint8_t pinfo = (cqe->pkt_info & 0x3) << 6;
315 
316 	/* Get l3/l4 header from mini-CQE in case L3/L4 format*/
317 	if (mcqe == NULL ||
318 	    rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
319 		ptype = (cqe->hdr_type_etc & 0xfc00) >> 10;
320 	else
321 		ptype = mcqe->hdr_type >> 2;
322 	/*
323 	 * The index to the array should have:
324 	 * bit[1:0] = l3_hdr_type
325 	 * bit[4:2] = l4_hdr_type
326 	 * bit[5] = ip_frag
327 	 * bit[6] = tunneled
328 	 * bit[7] = outer_l3_type
329 	 */
330 	idx = pinfo | ptype;
331 	return mlx5_ptype_table[idx] | rxq->tunnel * !!(idx & (1 << 6));
332 }
333 
334 /**
335  * Initialize Rx WQ and indexes.
336  *
337  * @param[in] rxq
338  *   Pointer to RX queue structure.
339  */
340 void
341 mlx5_rxq_initialize(struct mlx5_rxq_data *rxq)
342 {
343 	const unsigned int wqe_n = 1 << rxq->elts_n;
344 	unsigned int i;
345 
346 	for (i = 0; (i != wqe_n); ++i) {
347 		volatile struct mlx5_wqe_data_seg *scat;
348 		uintptr_t addr;
349 		uint32_t byte_count;
350 
351 		if (mlx5_rxq_mprq_enabled(rxq)) {
352 			struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[i];
353 
354 			scat = &((volatile struct mlx5_wqe_mprq *)
355 				rxq->wqes)[i].dseg;
356 			addr = (uintptr_t)mlx5_mprq_buf_addr(buf,
357 							 1 << rxq->strd_num_n);
358 			byte_count = (1 << rxq->strd_sz_n) *
359 					(1 << rxq->strd_num_n);
360 		} else {
361 			struct rte_mbuf *buf = (*rxq->elts)[i];
362 
363 			scat = &((volatile struct mlx5_wqe_data_seg *)
364 					rxq->wqes)[i];
365 			addr = rte_pktmbuf_mtod(buf, uintptr_t);
366 			byte_count = DATA_LEN(buf);
367 		}
368 		/* scat->addr must be able to store a pointer. */
369 		MLX5_ASSERT(sizeof(scat->addr) >= sizeof(uintptr_t));
370 		*scat = (struct mlx5_wqe_data_seg){
371 			.addr = rte_cpu_to_be_64(addr),
372 			.byte_count = rte_cpu_to_be_32(byte_count),
373 			.lkey = mlx5_rx_addr2mr(rxq, addr),
374 		};
375 	}
376 	rxq->consumed_strd = 0;
377 	rxq->decompressed = 0;
378 	rxq->rq_pi = 0;
379 	rxq->zip = (struct rxq_zip){
380 		.ai = 0,
381 	};
382 	rxq->elts_ci = mlx5_rxq_mprq_enabled(rxq) ?
383 		(wqe_n >> rxq->sges_n) * (1 << rxq->strd_num_n) : 0;
384 	/* Update doorbell counter. */
385 	rxq->rq_ci = wqe_n >> rxq->sges_n;
386 	rte_io_wmb();
387 	*rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
388 }
389 
390 /**
391  * Handle a Rx error.
392  * The function inserts the RQ state to reset when the first error CQE is
393  * shown, then drains the CQ by the caller function loop. When the CQ is empty,
394  * it moves the RQ state to ready and initializes the RQ.
395  * Next CQE identification and error counting are in the caller responsibility.
396  *
397  * @param[in] rxq
398  *   Pointer to RX queue structure.
399  * @param[in] vec
400  *   1 when called from vectorized Rx burst, need to prepare mbufs for the RQ.
401  *   0 when called from non-vectorized Rx burst.
402  *
403  * @return
404  *   -1 in case of recovery error, otherwise the CQE status.
405  */
406 int
407 mlx5_rx_err_handle(struct mlx5_rxq_data *rxq, uint8_t vec)
408 {
409 	const uint16_t cqe_n = 1 << rxq->cqe_n;
410 	const uint16_t cqe_mask = cqe_n - 1;
411 	const uint16_t wqe_n = 1 << rxq->elts_n;
412 	const uint16_t strd_n = 1 << rxq->strd_num_n;
413 	struct mlx5_rxq_ctrl *rxq_ctrl =
414 			container_of(rxq, struct mlx5_rxq_ctrl, rxq);
415 	union {
416 		volatile struct mlx5_cqe *cqe;
417 		volatile struct mlx5_err_cqe *err_cqe;
418 	} u = {
419 		.cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask],
420 	};
421 	struct mlx5_mp_arg_queue_state_modify sm;
422 	int ret;
423 
424 	switch (rxq->err_state) {
425 	case MLX5_RXQ_ERR_STATE_NO_ERROR:
426 		rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_RESET;
427 		/* Fall-through */
428 	case MLX5_RXQ_ERR_STATE_NEED_RESET:
429 		sm.is_wq = 1;
430 		sm.queue_id = rxq->idx;
431 		sm.state = IBV_WQS_RESET;
432 		if (mlx5_queue_state_modify(RXQ_DEV(rxq_ctrl), &sm))
433 			return -1;
434 		if (rxq_ctrl->dump_file_n <
435 		    RXQ_PORT(rxq_ctrl)->config.max_dump_files_num) {
436 			MKSTR(err_str, "Unexpected CQE error syndrome "
437 			      "0x%02x CQN = %u RQN = %u wqe_counter = %u"
438 			      " rq_ci = %u cq_ci = %u", u.err_cqe->syndrome,
439 			      rxq->cqn, rxq_ctrl->wqn,
440 			      rte_be_to_cpu_16(u.err_cqe->wqe_counter),
441 			      rxq->rq_ci << rxq->sges_n, rxq->cq_ci);
442 			MKSTR(name, "dpdk_mlx5_port_%u_rxq_%u_%u",
443 			      rxq->port_id, rxq->idx, (uint32_t)rte_rdtsc());
444 			mlx5_dump_debug_information(name, NULL, err_str, 0);
445 			mlx5_dump_debug_information(name, "MLX5 Error CQ:",
446 						    (const void *)((uintptr_t)
447 								    rxq->cqes),
448 						    sizeof(*u.cqe) * cqe_n);
449 			mlx5_dump_debug_information(name, "MLX5 Error RQ:",
450 						    (const void *)((uintptr_t)
451 								    rxq->wqes),
452 						    16 * wqe_n);
453 			rxq_ctrl->dump_file_n++;
454 		}
455 		rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_READY;
456 		/* Fall-through */
457 	case MLX5_RXQ_ERR_STATE_NEED_READY:
458 		ret = check_cqe(u.cqe, cqe_n, rxq->cq_ci);
459 		if (ret == MLX5_CQE_STATUS_HW_OWN) {
460 			rte_io_wmb();
461 			*rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
462 			rte_io_wmb();
463 			/*
464 			 * The RQ consumer index must be zeroed while moving
465 			 * from RESET state to RDY state.
466 			 */
467 			*rxq->rq_db = rte_cpu_to_be_32(0);
468 			rte_io_wmb();
469 			sm.is_wq = 1;
470 			sm.queue_id = rxq->idx;
471 			sm.state = IBV_WQS_RDY;
472 			if (mlx5_queue_state_modify(RXQ_DEV(rxq_ctrl), &sm))
473 				return -1;
474 			if (vec) {
475 				const uint32_t elts_n =
476 					mlx5_rxq_mprq_enabled(rxq) ?
477 					wqe_n * strd_n : wqe_n;
478 				const uint32_t e_mask = elts_n - 1;
479 				uint32_t elts_ci =
480 					mlx5_rxq_mprq_enabled(rxq) ?
481 					rxq->elts_ci : rxq->rq_ci;
482 				uint32_t elt_idx;
483 				struct rte_mbuf **elt;
484 				int i;
485 				unsigned int n = elts_n - (elts_ci -
486 							  rxq->rq_pi);
487 
488 				for (i = 0; i < (int)n; ++i) {
489 					elt_idx = (elts_ci + i) & e_mask;
490 					elt = &(*rxq->elts)[elt_idx];
491 					*elt = rte_mbuf_raw_alloc(rxq->mp);
492 					if (!*elt) {
493 						for (i--; i >= 0; --i) {
494 							elt_idx = (elts_ci +
495 								   i) & elts_n;
496 							elt = &(*rxq->elts)
497 								[elt_idx];
498 							rte_pktmbuf_free_seg
499 								(*elt);
500 						}
501 						return -1;
502 					}
503 				}
504 				for (i = 0; i < (int)elts_n; ++i) {
505 					elt = &(*rxq->elts)[i];
506 					DATA_LEN(*elt) =
507 						(uint16_t)((*elt)->buf_len -
508 						rte_pktmbuf_headroom(*elt));
509 				}
510 				/* Padding with a fake mbuf for vec Rx. */
511 				for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i)
512 					(*rxq->elts)[elts_n + i] =
513 								&rxq->fake_mbuf;
514 			}
515 			mlx5_rxq_initialize(rxq);
516 			rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR;
517 		}
518 		return ret;
519 	default:
520 		return -1;
521 	}
522 }
523 
524 /**
525  * Get size of the next packet for a given CQE. For compressed CQEs, the
526  * consumer index is updated only once all packets of the current one have
527  * been processed.
528  *
529  * @param rxq
530  *   Pointer to RX queue.
531  * @param cqe
532  *   CQE to process.
533  * @param[out] mcqe
534  *   Store pointer to mini-CQE if compressed. Otherwise, the pointer is not
535  *   written.
536  *
537  * @return
538  *   0 in case of empty CQE, otherwise the packet size in bytes.
539  */
540 static inline int
541 mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
542 		 uint16_t cqe_cnt, volatile struct mlx5_mini_cqe8 **mcqe)
543 {
544 	struct rxq_zip *zip = &rxq->zip;
545 	uint16_t cqe_n = cqe_cnt + 1;
546 	int len;
547 	uint16_t idx, end;
548 
549 	do {
550 		len = 0;
551 		/* Process compressed data in the CQE and mini arrays. */
552 		if (zip->ai) {
553 			volatile struct mlx5_mini_cqe8 (*mc)[8] =
554 				(volatile struct mlx5_mini_cqe8 (*)[8])
555 				(uintptr_t)(&(*rxq->cqes)[zip->ca &
556 							  cqe_cnt].pkt_info);
557 			len = rte_be_to_cpu_32((*mc)[zip->ai & 7].byte_cnt &
558 					       rxq->byte_mask);
559 			*mcqe = &(*mc)[zip->ai & 7];
560 			if ((++zip->ai & 7) == 0) {
561 				/* Invalidate consumed CQEs */
562 				idx = zip->ca;
563 				end = zip->na;
564 				while (idx != end) {
565 					(*rxq->cqes)[idx & cqe_cnt].op_own =
566 						MLX5_CQE_INVALIDATE;
567 					++idx;
568 				}
569 				/*
570 				 * Increment consumer index to skip the number
571 				 * of CQEs consumed. Hardware leaves holes in
572 				 * the CQ ring for software use.
573 				 */
574 				zip->ca = zip->na;
575 				zip->na += 8;
576 			}
577 			if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
578 				/* Invalidate the rest */
579 				idx = zip->ca;
580 				end = zip->cq_ci;
581 
582 				while (idx != end) {
583 					(*rxq->cqes)[idx & cqe_cnt].op_own =
584 						MLX5_CQE_INVALIDATE;
585 					++idx;
586 				}
587 				rxq->cq_ci = zip->cq_ci;
588 				zip->ai = 0;
589 			}
590 		/*
591 		 * No compressed data, get next CQE and verify if it is
592 		 * compressed.
593 		 */
594 		} else {
595 			int ret;
596 			int8_t op_own;
597 			uint32_t cq_ci;
598 
599 			ret = check_cqe(cqe, cqe_n, rxq->cq_ci);
600 			if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
601 				if (unlikely(ret == MLX5_CQE_STATUS_ERR ||
602 					     rxq->err_state)) {
603 					ret = mlx5_rx_err_handle(rxq, 0);
604 					if (ret == MLX5_CQE_STATUS_HW_OWN ||
605 					    ret == -1)
606 						return 0;
607 				} else {
608 					return 0;
609 				}
610 			}
611 			/*
612 			 * Introduce the local variable to have queue cq_ci
613 			 * index in queue structure always consistent with
614 			 * actual CQE boundary (not pointing to the middle
615 			 * of compressed CQE session).
616 			 */
617 			cq_ci = rxq->cq_ci + 1;
618 			op_own = cqe->op_own;
619 			if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
620 				volatile struct mlx5_mini_cqe8 (*mc)[8] =
621 					(volatile struct mlx5_mini_cqe8 (*)[8])
622 					(uintptr_t)(&(*rxq->cqes)
623 						[cq_ci & cqe_cnt].pkt_info);
624 
625 				/* Fix endianness. */
626 				zip->cqe_cnt = rte_be_to_cpu_32(cqe->byte_cnt);
627 				/*
628 				 * Current mini array position is the one
629 				 * returned by check_cqe64().
630 				 *
631 				 * If completion comprises several mini arrays,
632 				 * as a special case the second one is located
633 				 * 7 CQEs after the initial CQE instead of 8
634 				 * for subsequent ones.
635 				 */
636 				zip->ca = cq_ci;
637 				zip->na = zip->ca + 7;
638 				/* Compute the next non compressed CQE. */
639 				zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
640 				/* Get packet size to return. */
641 				len = rte_be_to_cpu_32((*mc)[0].byte_cnt &
642 						       rxq->byte_mask);
643 				*mcqe = &(*mc)[0];
644 				zip->ai = 1;
645 				/* Prefetch all to be invalidated */
646 				idx = zip->ca;
647 				end = zip->cq_ci;
648 				while (idx != end) {
649 					rte_prefetch0(&(*rxq->cqes)[(idx) &
650 								    cqe_cnt]);
651 					++idx;
652 				}
653 			} else {
654 				rxq->cq_ci = cq_ci;
655 				len = rte_be_to_cpu_32(cqe->byte_cnt);
656 			}
657 		}
658 		if (unlikely(rxq->err_state)) {
659 			cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
660 			++rxq->stats.idropped;
661 		} else {
662 			return len;
663 		}
664 	} while (1);
665 }
666 
667 /**
668  * Translate RX completion flags to offload flags.
669  *
670  * @param[in] cqe
671  *   Pointer to CQE.
672  *
673  * @return
674  *   Offload flags (ol_flags) for struct rte_mbuf.
675  */
676 static inline uint32_t
677 rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe)
678 {
679 	uint32_t ol_flags = 0;
680 	uint16_t flags = rte_be_to_cpu_16(cqe->hdr_type_etc);
681 
682 	ol_flags =
683 		TRANSPOSE(flags,
684 			  MLX5_CQE_RX_L3_HDR_VALID,
685 			  RTE_MBUF_F_RX_IP_CKSUM_GOOD) |
686 		TRANSPOSE(flags,
687 			  MLX5_CQE_RX_L4_HDR_VALID,
688 			  RTE_MBUF_F_RX_L4_CKSUM_GOOD);
689 	return ol_flags;
690 }
691 
692 /**
693  * Fill in mbuf fields from RX completion flags.
694  * Note that pkt->ol_flags should be initialized outside of this function.
695  *
696  * @param rxq
697  *   Pointer to RX queue.
698  * @param pkt
699  *   mbuf to fill.
700  * @param cqe
701  *   CQE to process.
702  * @param rss_hash_res
703  *   Packet RSS Hash result.
704  */
705 static inline void
706 rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
707 	       volatile struct mlx5_cqe *cqe,
708 	       volatile struct mlx5_mini_cqe8 *mcqe)
709 {
710 	/* Update packet information. */
711 	pkt->packet_type = rxq_cq_to_pkt_type(rxq, cqe, mcqe);
712 	pkt->port = unlikely(rxq->shared) ? cqe->user_index_low : rxq->port_id;
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 
1213