1
2
3
4
5
6
7
8
9
10
11#include <stdbool.h>
12#include <stdint.h>
13#include <string.h>
14
15
16#ifdef PEDANTIC
17#pragma GCC diagnostic ignored "-Wpedantic"
18#endif
19#include <infiniband/verbs.h>
20#ifdef PEDANTIC
21#pragma GCC diagnostic error "-Wpedantic"
22#endif
23
24#include <rte_branch_prediction.h>
25#include <rte_common.h>
26#include <rte_io.h>
27#include <rte_mbuf.h>
28#include <rte_mempool.h>
29#include <rte_prefetch.h>
30
31#include "mlx4.h"
32#include "mlx4_prm.h"
33#include "mlx4_rxtx.h"
34#include "mlx4_utils.h"
35
36
37
38
39
40struct pv {
41 union {
42 volatile struct mlx4_wqe_data_seg *dseg;
43 volatile uint32_t *dst;
44 };
45 uint32_t val;
46};
47
48
49struct tso_info {
50
51 struct pv *pv;
52
53 int pv_counter;
54
55 uint32_t wqe_size;
56
57 uint16_t tso_header_size;
58
59 uint16_t wqe_tso_seg_size;
60
61 uint8_t fence_size;
62};
63
64
65uint32_t mlx4_ptype_table[0x100] __rte_cache_aligned = {
66
67
68
69
70
71
72
73
74
75
76
77
78
79 [0x00] = RTE_PTYPE_L2_ETHER,
80
81 [0x01] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
82 RTE_PTYPE_L4_NONFRAG,
83 [0x02] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
84 RTE_PTYPE_L4_FRAG,
85 [0x03] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
86 RTE_PTYPE_L4_FRAG,
87 [0x04] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
88 RTE_PTYPE_L4_NONFRAG,
89 [0x06] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
90 RTE_PTYPE_L4_FRAG,
91 [0x08] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
92 RTE_PTYPE_L4_NONFRAG,
93 [0x09] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
94 RTE_PTYPE_L4_NONFRAG,
95 [0x0a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
96 RTE_PTYPE_L4_FRAG,
97 [0x0b] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
98 RTE_PTYPE_L4_FRAG,
99
100 [0x11] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
101 RTE_PTYPE_L4_TCP,
102 [0x14] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
103 RTE_PTYPE_L4_TCP,
104 [0x16] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
105 RTE_PTYPE_L4_FRAG,
106 [0x18] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
107 RTE_PTYPE_L4_TCP,
108 [0x19] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
109 RTE_PTYPE_L4_TCP,
110
111 [0x21] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
112 RTE_PTYPE_L4_UDP,
113 [0x24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
114 RTE_PTYPE_L4_UDP,
115 [0x26] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
116 RTE_PTYPE_L4_FRAG,
117 [0x28] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
118 RTE_PTYPE_L4_UDP,
119 [0x29] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
120 RTE_PTYPE_L4_UDP,
121
122 [0x80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
123 [0x81] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
124 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
125 RTE_PTYPE_INNER_L4_NONFRAG,
126 [0x82] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
127 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
128 RTE_PTYPE_INNER_L4_FRAG,
129 [0x83] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
130 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
131 RTE_PTYPE_INNER_L4_FRAG,
132 [0x84] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
133 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
134 RTE_PTYPE_INNER_L4_NONFRAG,
135 [0x86] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
136 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
137 RTE_PTYPE_INNER_L4_FRAG,
138 [0x88] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
139 RTE_PTYPE_INNER_L3_IPV4_EXT |
140 RTE_PTYPE_INNER_L4_NONFRAG,
141 [0x89] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
142 RTE_PTYPE_INNER_L3_IPV4_EXT |
143 RTE_PTYPE_INNER_L4_NONFRAG,
144 [0x8a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
145 RTE_PTYPE_INNER_L3_IPV4_EXT |
146 RTE_PTYPE_INNER_L4_FRAG,
147 [0x8b] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
148 RTE_PTYPE_INNER_L3_IPV4_EXT |
149 RTE_PTYPE_INNER_L4_FRAG,
150
151 [0x91] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
152 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
153 RTE_PTYPE_INNER_L4_TCP,
154 [0x94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
155 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
156 RTE_PTYPE_INNER_L4_TCP,
157 [0x96] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
158 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
159 RTE_PTYPE_INNER_L4_FRAG,
160 [0x98] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
161 RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_TCP,
162 [0x99] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
163 RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_TCP,
164
165 [0xa1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
166 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
167 RTE_PTYPE_INNER_L4_UDP,
168 [0xa4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
169 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
170 RTE_PTYPE_INNER_L4_UDP,
171 [0xa6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
172 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
173 RTE_PTYPE_INNER_L4_FRAG,
174 [0xa8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
175 RTE_PTYPE_INNER_L3_IPV4_EXT |
176 RTE_PTYPE_INNER_L4_UDP,
177 [0xa9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
178 RTE_PTYPE_INNER_L3_IPV4_EXT |
179 RTE_PTYPE_INNER_L4_UDP,
180
181 [0xc0] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
182 [0xc1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
183 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
184 RTE_PTYPE_INNER_L4_NONFRAG,
185 [0xc2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
186 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
187 RTE_PTYPE_INNER_L4_FRAG,
188 [0xc3] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
189 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
190 RTE_PTYPE_INNER_L4_FRAG,
191 [0xc4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
192 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
193 RTE_PTYPE_INNER_L4_NONFRAG,
194 [0xc6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
195 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
196 RTE_PTYPE_INNER_L4_FRAG,
197 [0xc8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
198 RTE_PTYPE_INNER_L3_IPV4_EXT |
199 RTE_PTYPE_INNER_L4_NONFRAG,
200 [0xc9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
201 RTE_PTYPE_INNER_L3_IPV4_EXT |
202 RTE_PTYPE_INNER_L4_NONFRAG,
203 [0xca] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
204 RTE_PTYPE_INNER_L3_IPV4_EXT |
205 RTE_PTYPE_INNER_L4_FRAG,
206 [0xcb] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
207 RTE_PTYPE_INNER_L3_IPV4_EXT |
208 RTE_PTYPE_INNER_L4_FRAG,
209
210 [0xd1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
211 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
212 RTE_PTYPE_INNER_L4_TCP,
213 [0xd4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
214 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
215 RTE_PTYPE_INNER_L4_TCP,
216 [0xd6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
217 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
218 RTE_PTYPE_INNER_L4_FRAG,
219 [0xd8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
220 RTE_PTYPE_INNER_L3_IPV4_EXT |
221 RTE_PTYPE_INNER_L4_TCP,
222 [0xd9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
223 RTE_PTYPE_INNER_L3_IPV4_EXT |
224 RTE_PTYPE_INNER_L4_TCP,
225
226 [0xe1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
227 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
228 RTE_PTYPE_INNER_L4_UDP,
229 [0xe4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
230 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
231 RTE_PTYPE_INNER_L4_UDP,
232 [0xe6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
233 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
234 RTE_PTYPE_INNER_L4_FRAG,
235 [0xe8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
236 RTE_PTYPE_INNER_L3_IPV4_EXT |
237 RTE_PTYPE_INNER_L4_UDP,
238 [0xe9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
239 RTE_PTYPE_INNER_L3_IPV4_EXT |
240 RTE_PTYPE_INNER_L4_UDP,
241};
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259static uint32_t
260mlx4_txq_stamp_freed_wqe(struct mlx4_sq *sq, volatile uint32_t *start,
261 volatile uint32_t *end)
262{
263 uint32_t stamp = sq->stamp;
264 int32_t size = (intptr_t)end - (intptr_t)start;
265
266 MLX4_ASSERT(start != end);
267
268 if (size < 0) {
269 size = (int32_t)sq->size + size;
270 do {
271 *start = stamp;
272 start += MLX4_SQ_STAMP_DWORDS;
273 } while (start != (volatile uint32_t *)sq->eob);
274 start = (volatile uint32_t *)sq->buf;
275
276 stamp ^= RTE_BE32(1u << MLX4_SQ_OWNER_BIT);
277 sq->stamp = stamp;
278 if (start == end)
279 return size;
280 }
281 do {
282 *start = stamp;
283 start += MLX4_SQ_STAMP_DWORDS;
284 } while (start != end);
285 return (uint32_t)size;
286}
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303static void
304mlx4_txq_complete(struct txq *txq, const unsigned int elts_m,
305 struct mlx4_sq *sq)
306{
307 unsigned int elts_tail = txq->elts_tail;
308 struct mlx4_cq *cq = &txq->mcq;
309 volatile struct mlx4_cqe *cqe;
310 uint32_t completed;
311 uint32_t cons_index = cq->cons_index;
312 volatile uint32_t *first_txbb;
313
314
315
316
317
318 do {
319 cqe = (volatile struct mlx4_cqe *)mlx4_get_cqe(cq, cons_index);
320 if (unlikely(!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
321 !!(cons_index & cq->cqe_cnt)))
322 break;
323#ifdef RTE_LIBRTE_MLX4_DEBUG
324
325
326
327 rte_io_rmb();
328 if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
329 MLX4_CQE_OPCODE_ERROR)) {
330 volatile struct mlx4_err_cqe *cqe_err =
331 (volatile struct mlx4_err_cqe *)cqe;
332 ERROR("%p CQE error - vendor syndrome: 0x%x"
333 " syndrome: 0x%x\n",
334 (void *)txq, cqe_err->vendor_err,
335 cqe_err->syndrome);
336 break;
337 }
338#endif
339 cons_index++;
340 } while (1);
341 completed = (cons_index - cq->cons_index) * txq->elts_comp_cd_init;
342 if (unlikely(!completed))
343 return;
344
345 first_txbb = (&(*txq->elts)[elts_tail & elts_m])->eocb;
346 elts_tail += completed;
347
348 sq->remain_size += mlx4_txq_stamp_freed_wqe(sq, first_txbb,
349 (&(*txq->elts)[elts_tail & elts_m])->eocb);
350
351 cq->cons_index = cons_index;
352 *cq->set_ci_db = rte_cpu_to_be_32(cons_index & MLX4_CQ_DB_CI_MASK);
353 txq->elts_tail = elts_tail;
354}
355
356
357
358
359
360
361
362
363
364
365
366
367
368static inline void
369mlx4_fill_tx_data_seg(volatile struct mlx4_wqe_data_seg *dseg,
370 uint32_t lkey, uintptr_t addr, rte_be32_t byte_count)
371{
372 dseg->addr = rte_cpu_to_be_64(addr);
373 dseg->lkey = lkey;
374#if RTE_CACHE_LINE_SIZE < 64
375
376
377
378
379
380
381
382
383
384 rte_io_wmb();
385#endif
386 dseg->byte_count = byte_count;
387}
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402static inline int
403mlx4_tx_burst_tso_get_params(struct rte_mbuf *buf,
404 struct txq *txq,
405 struct tso_info *tinfo)
406{
407 struct mlx4_sq *sq = &txq->msq;
408 const uint8_t tunneled = txq->priv->hw_csum_l2tun &&
409 (buf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK);
410
411 tinfo->tso_header_size = buf->l2_len + buf->l3_len + buf->l4_len;
412 if (tunneled)
413 tinfo->tso_header_size +=
414 buf->outer_l2_len + buf->outer_l3_len;
415 if (unlikely(buf->tso_segsz == 0 ||
416 tinfo->tso_header_size == 0 ||
417 tinfo->tso_header_size > MLX4_MAX_TSO_HEADER ||
418 tinfo->tso_header_size > buf->data_len))
419 return -EINVAL;
420
421
422
423
424
425
426
427 tinfo->wqe_tso_seg_size = RTE_ALIGN(sizeof(struct mlx4_wqe_lso_seg) +
428 tinfo->tso_header_size,
429 sizeof(struct mlx4_wqe_data_seg));
430 tinfo->fence_size = ((sizeof(struct mlx4_wqe_ctrl_seg) +
431 tinfo->wqe_tso_seg_size) >> MLX4_SEG_SHIFT) +
432 buf->nb_segs;
433 tinfo->wqe_size =
434 RTE_ALIGN((uint32_t)(tinfo->fence_size << MLX4_SEG_SHIFT),
435 MLX4_TXBB_SIZE);
436
437 if (sq->remain_size < tinfo->wqe_size ||
438 tinfo->wqe_size > MLX4_MAX_WQE_SIZE)
439 return -ENOMEM;
440
441 tinfo->pv = (struct pv *)txq->bounce_buf;
442 tinfo->pv_counter = 0;
443 return 0;
444}
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463static inline volatile struct mlx4_wqe_ctrl_seg *
464mlx4_tx_burst_fill_tso_dsegs(struct rte_mbuf *buf,
465 struct txq *txq,
466 struct tso_info *tinfo,
467 volatile struct mlx4_wqe_data_seg *dseg,
468 volatile struct mlx4_wqe_ctrl_seg *ctrl)
469{
470 uint32_t lkey;
471 int nb_segs = buf->nb_segs;
472 int nb_segs_txbb;
473 struct mlx4_sq *sq = &txq->msq;
474 struct rte_mbuf *sbuf = buf;
475 struct pv *pv = tinfo->pv;
476 int *pv_counter = &tinfo->pv_counter;
477 volatile struct mlx4_wqe_ctrl_seg *ctrl_next =
478 (volatile struct mlx4_wqe_ctrl_seg *)
479 ((volatile uint8_t *)ctrl + tinfo->wqe_size);
480 uint16_t data_len = sbuf->data_len - tinfo->tso_header_size;
481 uintptr_t data_addr = rte_pktmbuf_mtod_offset(sbuf, uintptr_t,
482 tinfo->tso_header_size);
483
484 do {
485
486 nb_segs_txbb = (MLX4_TXBB_SIZE -
487 ((uintptr_t)dseg & (MLX4_TXBB_SIZE - 1))) >>
488 MLX4_SEG_SHIFT;
489 switch (nb_segs_txbb) {
490#ifdef RTE_LIBRTE_MLX4_DEBUG
491 default:
492
493 rte_panic("%p: Invalid number of SGEs(%d) for a TXBB",
494 (void *)txq, nb_segs_txbb);
495
496 break;
497#endif
498 case 4:
499
500 lkey = mlx4_tx_mb2mr(txq, sbuf);
501 if (unlikely(lkey == (uint32_t)-1))
502 goto err;
503 dseg->addr = rte_cpu_to_be_64(data_addr);
504 dseg->lkey = lkey;
505
506
507
508
509
510 pv[*pv_counter].dseg = dseg;
511
512
513
514
515 pv[(*pv_counter)++].val =
516 rte_cpu_to_be_32(data_len ?
517 data_len :
518 0x80000000);
519 if (--nb_segs == 0)
520 return ctrl_next;
521
522 sbuf = sbuf->next;
523 dseg++;
524 data_len = sbuf->data_len;
525 data_addr = rte_pktmbuf_mtod(sbuf, uintptr_t);
526
527 case 3:
528 lkey = mlx4_tx_mb2mr(txq, sbuf);
529 if (unlikely(lkey == (uint32_t)-1))
530 goto err;
531 mlx4_fill_tx_data_seg(dseg, lkey, data_addr,
532 rte_cpu_to_be_32(data_len ?
533 data_len :
534 0x80000000));
535 if (--nb_segs == 0)
536 return ctrl_next;
537
538 sbuf = sbuf->next;
539 dseg++;
540 data_len = sbuf->data_len;
541 data_addr = rte_pktmbuf_mtod(sbuf, uintptr_t);
542
543 case 2:
544 lkey = mlx4_tx_mb2mr(txq, sbuf);
545 if (unlikely(lkey == (uint32_t)-1))
546 goto err;
547 mlx4_fill_tx_data_seg(dseg, lkey, data_addr,
548 rte_cpu_to_be_32(data_len ?
549 data_len :
550 0x80000000));
551 if (--nb_segs == 0)
552 return ctrl_next;
553
554 sbuf = sbuf->next;
555 dseg++;
556 data_len = sbuf->data_len;
557 data_addr = rte_pktmbuf_mtod(sbuf, uintptr_t);
558
559 case 1:
560 lkey = mlx4_tx_mb2mr(txq, sbuf);
561 if (unlikely(lkey == (uint32_t)-1))
562 goto err;
563 mlx4_fill_tx_data_seg(dseg, lkey, data_addr,
564 rte_cpu_to_be_32(data_len ?
565 data_len :
566 0x80000000));
567 if (--nb_segs == 0)
568 return ctrl_next;
569
570 sbuf = sbuf->next;
571 dseg++;
572 data_len = sbuf->data_len;
573 data_addr = rte_pktmbuf_mtod(sbuf, uintptr_t);
574
575 }
576
577 if ((volatile uint8_t *)dseg >= sq->eob)
578 dseg = (volatile struct mlx4_wqe_data_seg *)
579 ((volatile uint8_t *)dseg - sq->size);
580 } while (true);
581err:
582 return NULL;
583}
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602static inline volatile struct mlx4_wqe_data_seg *
603mlx4_tx_burst_fill_tso_hdr(struct rte_mbuf *buf,
604 struct txq *txq,
605 struct tso_info *tinfo,
606 volatile struct mlx4_wqe_ctrl_seg *ctrl)
607{
608 volatile struct mlx4_wqe_lso_seg *tseg =
609 (volatile struct mlx4_wqe_lso_seg *)(ctrl + 1);
610 struct mlx4_sq *sq = &txq->msq;
611 struct pv *pv = tinfo->pv;
612 int *pv_counter = &tinfo->pv_counter;
613 int remain_size = tinfo->tso_header_size;
614 char *from = rte_pktmbuf_mtod(buf, char *);
615 uint16_t txbb_avail_space;
616
617 union {
618 volatile uint8_t *vto;
619 uint8_t *to;
620 } thdr = { .vto = (volatile uint8_t *)tseg->header, };
621
622
623
624
625
626
627
628 txbb_avail_space = MLX4_TXBB_SIZE -
629 (sizeof(struct mlx4_wqe_ctrl_seg) +
630 sizeof(struct mlx4_wqe_lso_seg));
631 while (remain_size >= (int)(txbb_avail_space + sizeof(uint32_t))) {
632
633 rte_memcpy(thdr.to, from, txbb_avail_space);
634 from += txbb_avail_space;
635 thdr.to += txbb_avail_space;
636
637 if (thdr.to >= sq->eob)
638 thdr.vto = sq->buf;
639
640 pv[*pv_counter].dst = (volatile uint32_t *)thdr.to;
641 pv[(*pv_counter)++].val = *(uint32_t *)from,
642 from += sizeof(uint32_t);
643 thdr.to += sizeof(uint32_t);
644 remain_size -= txbb_avail_space + sizeof(uint32_t);
645
646 txbb_avail_space = MLX4_TXBB_SIZE - sizeof(uint32_t);
647 }
648 if (remain_size > txbb_avail_space) {
649 rte_memcpy(thdr.to, from, txbb_avail_space);
650 from += txbb_avail_space;
651 thdr.to += txbb_avail_space;
652 remain_size -= txbb_avail_space;
653
654 if (thdr.to >= sq->eob)
655 thdr.vto = sq->buf;
656 pv[*pv_counter].dst = (volatile uint32_t *)thdr.to;
657 rte_memcpy(&pv[*pv_counter].val, from, remain_size);
658 (*pv_counter)++;
659 } else if (remain_size) {
660 rte_memcpy(thdr.to, from, remain_size);
661 }
662 tseg->mss_hdr_size = rte_cpu_to_be_32((buf->tso_segsz << 16) |
663 tinfo->tso_header_size);
664
665 return (volatile struct mlx4_wqe_data_seg *)
666 ((uintptr_t)tseg + tinfo->wqe_tso_seg_size);
667}
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682static volatile struct mlx4_wqe_ctrl_seg *
683mlx4_tx_burst_tso(struct rte_mbuf *buf, struct txq *txq,
684 volatile struct mlx4_wqe_ctrl_seg *ctrl)
685{
686 volatile struct mlx4_wqe_data_seg *dseg;
687 volatile struct mlx4_wqe_ctrl_seg *ctrl_next;
688 struct mlx4_sq *sq = &txq->msq;
689 struct tso_info tinfo;
690 struct pv *pv;
691 int pv_counter;
692 int ret;
693
694 ret = mlx4_tx_burst_tso_get_params(buf, txq, &tinfo);
695 if (unlikely(ret))
696 goto error;
697 dseg = mlx4_tx_burst_fill_tso_hdr(buf, txq, &tinfo, ctrl);
698 if (unlikely(dseg == NULL))
699 goto error;
700 if ((uintptr_t)dseg >= (uintptr_t)sq->eob)
701 dseg = (volatile struct mlx4_wqe_data_seg *)
702 ((uintptr_t)dseg - sq->size);
703 ctrl_next = mlx4_tx_burst_fill_tso_dsegs(buf, txq, &tinfo, dseg, ctrl);
704 if (unlikely(ctrl_next == NULL))
705 goto error;
706
707 if (likely(tinfo.pv_counter)) {
708 pv = tinfo.pv;
709 pv_counter = tinfo.pv_counter;
710
711 rte_io_wmb();
712 do {
713 --pv_counter;
714 *pv[pv_counter].dst = pv[pv_counter].val;
715 } while (pv_counter > 0);
716 }
717 ctrl->fence_size = tinfo.fence_size;
718 sq->remain_size -= tinfo.wqe_size;
719 return ctrl_next;
720error:
721 txq->stats.odropped++;
722 return NULL;
723}
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738static volatile struct mlx4_wqe_ctrl_seg *
739mlx4_tx_burst_segs(struct rte_mbuf *buf, struct txq *txq,
740 volatile struct mlx4_wqe_ctrl_seg *ctrl)
741{
742 struct pv *pv = (struct pv *)txq->bounce_buf;
743 struct mlx4_sq *sq = &txq->msq;
744 struct rte_mbuf *sbuf = buf;
745 uint32_t lkey;
746 int pv_counter = 0;
747 int nb_segs = buf->nb_segs;
748 uint32_t wqe_size;
749 volatile struct mlx4_wqe_data_seg *dseg =
750 (volatile struct mlx4_wqe_data_seg *)(ctrl + 1);
751
752 ctrl->fence_size = 1 + nb_segs;
753 wqe_size = RTE_ALIGN((uint32_t)(ctrl->fence_size << MLX4_SEG_SHIFT),
754 MLX4_TXBB_SIZE);
755
756 if (sq->remain_size < wqe_size ||
757 wqe_size > MLX4_MAX_WQE_SIZE)
758 return NULL;
759
760
761
762
763
764
765 goto txbb_tail_segs;
766txbb_head_seg:
767
768 lkey = mlx4_tx_mb2mr(txq, sbuf);
769 if (unlikely(lkey == (uint32_t)-1)) {
770 DEBUG("%p: unable to get MP <-> MR association",
771 (void *)txq);
772 return NULL;
773 }
774
775 if (dseg >=
776 (volatile struct mlx4_wqe_data_seg *)sq->eob)
777 dseg = (volatile struct mlx4_wqe_data_seg *)
778 sq->buf;
779 dseg->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(sbuf, uintptr_t));
780 dseg->lkey = lkey;
781
782
783
784
785
786 pv[pv_counter].dseg = dseg;
787
788
789
790
791 pv[pv_counter++].val = rte_cpu_to_be_32(sbuf->data_len ?
792 sbuf->data_len : 0x80000000);
793 sbuf = sbuf->next;
794 dseg++;
795 nb_segs--;
796txbb_tail_segs:
797
798 switch (nb_segs) {
799 default:
800 lkey = mlx4_tx_mb2mr(txq, sbuf);
801 if (unlikely(lkey == (uint32_t)-1)) {
802 DEBUG("%p: unable to get MP <-> MR association",
803 (void *)txq);
804 return NULL;
805 }
806 mlx4_fill_tx_data_seg(dseg, lkey,
807 rte_pktmbuf_mtod(sbuf, uintptr_t),
808 rte_cpu_to_be_32(sbuf->data_len ?
809 sbuf->data_len :
810 0x80000000));
811 sbuf = sbuf->next;
812 dseg++;
813 nb_segs--;
814
815 case 2:
816 lkey = mlx4_tx_mb2mr(txq, sbuf);
817 if (unlikely(lkey == (uint32_t)-1)) {
818 DEBUG("%p: unable to get MP <-> MR association",
819 (void *)txq);
820 return NULL;
821 }
822 mlx4_fill_tx_data_seg(dseg, lkey,
823 rte_pktmbuf_mtod(sbuf, uintptr_t),
824 rte_cpu_to_be_32(sbuf->data_len ?
825 sbuf->data_len :
826 0x80000000));
827 sbuf = sbuf->next;
828 dseg++;
829 nb_segs--;
830
831 case 1:
832 lkey = mlx4_tx_mb2mr(txq, sbuf);
833 if (unlikely(lkey == (uint32_t)-1)) {
834 DEBUG("%p: unable to get MP <-> MR association",
835 (void *)txq);
836 return NULL;
837 }
838 mlx4_fill_tx_data_seg(dseg, lkey,
839 rte_pktmbuf_mtod(sbuf, uintptr_t),
840 rte_cpu_to_be_32(sbuf->data_len ?
841 sbuf->data_len :
842 0x80000000));
843 nb_segs--;
844 if (nb_segs) {
845 sbuf = sbuf->next;
846 dseg++;
847 goto txbb_head_seg;
848 }
849
850 case 0:
851 break;
852 }
853
854 if (pv_counter) {
855
856 rte_io_wmb();
857 for (--pv_counter; pv_counter >= 0; pv_counter--)
858 pv[pv_counter].dseg->byte_count = pv[pv_counter].val;
859 }
860 sq->remain_size -= wqe_size;
861
862 return (volatile struct mlx4_wqe_ctrl_seg *)
863 ((volatile uint8_t *)ctrl + wqe_size);
864}
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879uint16_t
880mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
881{
882 struct txq *txq = (struct txq *)dpdk_txq;
883 unsigned int elts_head = txq->elts_head;
884 const unsigned int elts_n = txq->elts_n;
885 const unsigned int elts_m = elts_n - 1;
886 unsigned int bytes_sent = 0;
887 unsigned int i;
888 unsigned int max = elts_head - txq->elts_tail;
889 struct mlx4_sq *sq = &txq->msq;
890 volatile struct mlx4_wqe_ctrl_seg *ctrl;
891 struct txq_elt *elt;
892
893 MLX4_ASSERT(txq->elts_comp_cd != 0);
894 if (likely(max >= txq->elts_comp_cd_init))
895 mlx4_txq_complete(txq, elts_m, sq);
896 max = elts_n - max;
897 MLX4_ASSERT(max >= 1);
898 MLX4_ASSERT(max <= elts_n);
899
900 --max;
901 if (max > pkts_n)
902 max = pkts_n;
903 elt = &(*txq->elts)[elts_head & elts_m];
904
905 ctrl = elt->wqe;
906 for (i = 0; (i != max); ++i) {
907 struct rte_mbuf *buf = pkts[i];
908 struct txq_elt *elt_next = &(*txq->elts)[++elts_head & elts_m];
909 uint32_t owner_opcode = sq->owner_opcode;
910 volatile struct mlx4_wqe_data_seg *dseg =
911 (volatile struct mlx4_wqe_data_seg *)(ctrl + 1);
912 volatile struct mlx4_wqe_ctrl_seg *ctrl_next;
913 union {
914 uint32_t flags;
915 uint16_t flags16[2];
916 } srcrb;
917 uint32_t lkey;
918 bool tso = txq->priv->tso && (buf->ol_flags & RTE_MBUF_F_TX_TCP_SEG);
919
920
921 if (likely(elt->buf != NULL)) {
922 struct rte_mbuf *tmp = elt->buf;
923
924
925 do {
926 struct rte_mbuf *next = tmp->next;
927
928 rte_pktmbuf_free_seg(tmp);
929 tmp = next;
930 } while (tmp != NULL);
931 }
932 RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf);
933 if (tso) {
934
935 owner_opcode &= ~MLX4_OPCODE_CONFIG_CMD;
936 owner_opcode |= MLX4_OPCODE_LSO | MLX4_WQE_CTRL_RR;
937 ctrl_next = mlx4_tx_burst_tso(buf, txq, ctrl);
938 if (!ctrl_next) {
939 elt->buf = NULL;
940 break;
941 }
942 } else if (buf->nb_segs == 1) {
943
944 if (sq->remain_size < MLX4_TXBB_SIZE) {
945 elt->buf = NULL;
946 break;
947 }
948 lkey = mlx4_tx_mb2mr(txq, buf);
949 if (unlikely(lkey == (uint32_t)-1)) {
950
951 DEBUG("%p: unable to get MP <-> MR association",
952 (void *)txq);
953 elt->buf = NULL;
954 break;
955 }
956 mlx4_fill_tx_data_seg(dseg++, lkey,
957 rte_pktmbuf_mtod(buf, uintptr_t),
958 rte_cpu_to_be_32(buf->data_len));
959
960 ctrl->fence_size = 0x2;
961 sq->remain_size -= MLX4_TXBB_SIZE;
962
963 ctrl_next = ctrl + 0x4;
964 } else {
965 ctrl_next = mlx4_tx_burst_segs(buf, txq, ctrl);
966 if (!ctrl_next) {
967 elt->buf = NULL;
968 break;
969 }
970 }
971
972 if ((volatile uint8_t *)ctrl_next >= sq->eob) {
973 ctrl_next = (volatile struct mlx4_wqe_ctrl_seg *)
974 ((volatile uint8_t *)ctrl_next - sq->size);
975
976 sq->owner_opcode ^= 1u << MLX4_SQ_OWNER_BIT;
977 }
978
979
980
981
982 if (--txq->elts_comp_cd == 0) {
983
984 elt_next->eocb = (volatile uint32_t *)ctrl_next;
985 txq->elts_comp_cd = txq->elts_comp_cd_init;
986 srcrb.flags = RTE_BE32(MLX4_WQE_CTRL_SOLICIT |
987 MLX4_WQE_CTRL_CQ_UPDATE);
988 } else {
989 srcrb.flags = RTE_BE32(MLX4_WQE_CTRL_SOLICIT);
990 }
991
992 if (txq->csum &&
993 (buf->ol_flags &
994 (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_TCP_CKSUM | RTE_MBUF_F_TX_UDP_CKSUM))) {
995 const uint64_t is_tunneled = (buf->ol_flags &
996 (RTE_MBUF_F_TX_TUNNEL_GRE |
997 RTE_MBUF_F_TX_TUNNEL_VXLAN));
998
999 if (is_tunneled && txq->csum_l2tun) {
1000 owner_opcode |= MLX4_WQE_CTRL_IIP_HDR_CSUM |
1001 MLX4_WQE_CTRL_IL4_HDR_CSUM;
1002 if (buf->ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM)
1003 srcrb.flags |=
1004 RTE_BE32(MLX4_WQE_CTRL_IP_HDR_CSUM);
1005 } else {
1006 srcrb.flags |=
1007 RTE_BE32(MLX4_WQE_CTRL_IP_HDR_CSUM |
1008 MLX4_WQE_CTRL_TCP_UDP_CSUM);
1009 }
1010 }
1011 if (txq->lb) {
1012
1013
1014
1015
1016
1017 srcrb.flags16[0] = *(rte_pktmbuf_mtod(buf, uint16_t *));
1018 ctrl->imm = *(rte_pktmbuf_mtod_offset(buf, uint32_t *,
1019 sizeof(uint16_t)));
1020 } else {
1021 ctrl->imm = 0;
1022 }
1023 ctrl->srcrb_flags = srcrb.flags;
1024
1025
1026
1027
1028
1029 rte_io_wmb();
1030 ctrl->owner_opcode = rte_cpu_to_be_32(owner_opcode);
1031 elt->buf = buf;
1032 bytes_sent += buf->pkt_len;
1033 ctrl = ctrl_next;
1034 elt = elt_next;
1035 }
1036
1037 if (unlikely(i == 0))
1038 return 0;
1039
1040 elt->wqe = ctrl;
1041
1042 txq->stats.opackets += i;
1043 txq->stats.obytes += bytes_sent;
1044
1045 rte_wmb();
1046
1047 rte_write32(txq->msq.doorbell_qpn, MLX4_TX_BFREG(txq));
1048 txq->elts_head += i;
1049 return i;
1050}
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061static inline uint32_t
1062rxq_cq_to_pkt_type(volatile struct mlx4_cqe *cqe,
1063 uint32_t l2tun_offload)
1064{
1065 uint8_t idx = 0;
1066 uint32_t pinfo = rte_be_to_cpu_32(cqe->vlan_my_qpn);
1067 uint32_t status = rte_be_to_cpu_32(cqe->status);
1068
1069
1070
1071
1072
1073
1074 if (l2tun_offload && (pinfo & MLX4_CQE_L2_TUNNEL))
1075 idx |= ((pinfo & MLX4_CQE_L2_TUNNEL) >> 20) |
1076 ((pinfo & MLX4_CQE_L2_TUNNEL_IPV4) >> 19);
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 idx |= ((status & MLX4_CQE_STATUS_PTYPE_MASK) >> 22);
1088 if (status & MLX4_CQE_STATUS_IPV6)
1089 idx |= ((status & MLX4_CQE_STATUS_IPV6F) >> 11);
1090 return mlx4_ptype_table[idx];
1091}
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106static inline uint32_t
1107rxq_cq_to_ol_flags(uint32_t flags, int csum, int csum_l2tun)
1108{
1109 uint32_t ol_flags = 0;
1110
1111 if (csum)
1112 ol_flags |=
1113 mlx4_transpose(flags,
1114 MLX4_CQE_STATUS_IP_HDR_CSUM_OK,
1115 RTE_MBUF_F_RX_IP_CKSUM_GOOD) |
1116 mlx4_transpose(flags,
1117 MLX4_CQE_STATUS_TCP_UDP_CSUM_OK,
1118 RTE_MBUF_F_RX_L4_CKSUM_GOOD);
1119 if ((flags & MLX4_CQE_L2_TUNNEL) && csum_l2tun)
1120 ol_flags |=
1121 mlx4_transpose(flags,
1122 MLX4_CQE_L2_TUNNEL_IPOK,
1123 RTE_MBUF_F_RX_IP_CKSUM_GOOD) |
1124 mlx4_transpose(flags,
1125 MLX4_CQE_L2_TUNNEL_L4_CSUM,
1126 RTE_MBUF_F_RX_L4_CKSUM_GOOD);
1127 return ol_flags;
1128}
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143static inline uint32_t
1144mlx4_cqe_flags(volatile struct mlx4_cqe *cqe, int csum, int csum_l2tun)
1145{
1146 uint32_t flags = 0;
1147
1148
1149
1150
1151
1152
1153 if (csum)
1154 flags = (rte_be_to_cpu_32(cqe->status) &
1155 MLX4_CQE_STATUS_IPV4_CSUM_OK);
1156 if (csum_l2tun)
1157 flags |= (rte_be_to_cpu_32(cqe->vlan_my_qpn) &
1158 (MLX4_CQE_L2_TUNNEL |
1159 MLX4_CQE_L2_TUNNEL_IPOK |
1160 MLX4_CQE_L2_TUNNEL_L4_CSUM |
1161 MLX4_CQE_L2_TUNNEL_IPV4));
1162 return flags;
1163}
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176static unsigned int
1177mlx4_cq_poll_one(struct rxq *rxq, volatile struct mlx4_cqe **out)
1178{
1179 int ret = 0;
1180 volatile struct mlx4_cqe *cqe = NULL;
1181 struct mlx4_cq *cq = &rxq->mcq;
1182
1183 cqe = (volatile struct mlx4_cqe *)mlx4_get_cqe(cq, cq->cons_index);
1184 if (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
1185 !!(cq->cons_index & cq->cqe_cnt))
1186 goto out;
1187
1188
1189
1190
1191 rte_rmb();
1192 MLX4_ASSERT(!(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK));
1193 MLX4_ASSERT((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) !=
1194 MLX4_CQE_OPCODE_ERROR);
1195 ret = rte_be_to_cpu_32(cqe->byte_cnt);
1196 ++cq->cons_index;
1197out:
1198 *out = cqe;
1199 return ret;
1200}
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215uint16_t
1216mlx4_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1217{
1218 struct rxq *rxq = dpdk_rxq;
1219 const uint32_t wr_cnt = (1 << rxq->elts_n) - 1;
1220 const uint16_t sges_n = rxq->sges_n;
1221 struct rte_mbuf *pkt = NULL;
1222 struct rte_mbuf *seg = NULL;
1223 unsigned int i = 0;
1224 uint32_t rq_ci = rxq->rq_ci << sges_n;
1225 int len = 0;
1226
1227 while (pkts_n) {
1228 volatile struct mlx4_cqe *cqe;
1229 uint32_t idx = rq_ci & wr_cnt;
1230 struct rte_mbuf *rep = (*rxq->elts)[idx];
1231 volatile struct mlx4_wqe_data_seg *scat = &(*rxq->wqes)[idx];
1232
1233
1234 if (pkt)
1235 seg->next = rep;
1236 seg = rep;
1237 rte_prefetch0(seg);
1238 rte_prefetch0(scat);
1239 rep = rte_mbuf_raw_alloc(rxq->mp);
1240 if (unlikely(rep == NULL)) {
1241 ++rxq->stats.rx_nombuf;
1242 if (!pkt) {
1243
1244
1245
1246
1247 break;
1248 }
1249 while (pkt != seg) {
1250 MLX4_ASSERT(pkt != (*rxq->elts)[idx]);
1251 rep = pkt->next;
1252 pkt->next = NULL;
1253 pkt->nb_segs = 1;
1254 rte_mbuf_raw_free(pkt);
1255 pkt = rep;
1256 }
1257 break;
1258 }
1259 if (!pkt) {
1260
1261 len = mlx4_cq_poll_one(rxq, &cqe);
1262 if (!len) {
1263 rte_mbuf_raw_free(rep);
1264 break;
1265 }
1266 if (unlikely(len < 0)) {
1267
1268 rte_mbuf_raw_free(rep);
1269 ++rxq->stats.idropped;
1270 goto skip;
1271 }
1272 pkt = seg;
1273 MLX4_ASSERT(len >= (rxq->crc_present << 2));
1274
1275 pkt->packet_type =
1276 rxq_cq_to_pkt_type(cqe, rxq->l2tun_offload);
1277 pkt->ol_flags = RTE_MBUF_F_RX_RSS_HASH;
1278 pkt->hash.rss = cqe->immed_rss_invalid;
1279 if (rxq->crc_present)
1280 len -= RTE_ETHER_CRC_LEN;
1281 pkt->pkt_len = len;
1282 if (rxq->csum | rxq->csum_l2tun) {
1283 uint32_t flags =
1284 mlx4_cqe_flags(cqe,
1285 rxq->csum,
1286 rxq->csum_l2tun);
1287
1288 pkt->ol_flags =
1289 rxq_cq_to_ol_flags(flags,
1290 rxq->csum,
1291 rxq->csum_l2tun);
1292 }
1293 }
1294 rep->nb_segs = 1;
1295 rep->port = rxq->port_id;
1296 rep->data_len = seg->data_len;
1297 rep->data_off = seg->data_off;
1298 (*rxq->elts)[idx] = rep;
1299
1300
1301
1302
1303
1304 scat->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(rep, uintptr_t));
1305
1306 if (unlikely(mlx4_mr_btree_len(&rxq->mr_ctrl.cache_bh) > 1))
1307 scat->lkey = mlx4_rx_mb2mr(rxq, rep);
1308 if (len > seg->data_len) {
1309 len -= seg->data_len;
1310 ++pkt->nb_segs;
1311 ++rq_ci;
1312 continue;
1313 }
1314
1315 seg->data_len = len;
1316
1317 rxq->stats.ibytes += pkt->pkt_len;
1318
1319 *(pkts++) = pkt;
1320 pkt = NULL;
1321 --pkts_n;
1322 ++i;
1323skip:
1324
1325 rq_ci >>= sges_n;
1326 ++rq_ci;
1327 rq_ci <<= sges_n;
1328 }
1329 if (unlikely(i == 0 && (rq_ci >> sges_n) == rxq->rq_ci))
1330 return 0;
1331
1332 rxq->rq_ci = rq_ci >> sges_n;
1333 rte_wmb();
1334 *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
1335 *rxq->mcq.set_ci_db =
1336 rte_cpu_to_be_32(rxq->mcq.cons_index & MLX4_CQ_DB_CI_MASK);
1337
1338 rxq->stats.ipackets += i;
1339 return i;
1340}
1341