New upstream version 18.02
[deb_dpdk.git] / drivers / net / mlx4 / mlx4_rxtx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017 6WIND S.A.
3  * Copyright 2017 Mellanox
4  */
5
6 /**
7  * @file
8  * Data plane functions for mlx4 driver.
9  */
10
11 #include <assert.h>
12 #include <stdint.h>
13 #include <string.h>
14
15 /* Verbs headers do not support -pedantic. */
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  * Pointer-value pair structure used in tx_post_send for saving the first
38  * DWORD (32 byte) of a TXBB.
39  */
40 struct pv {
41         volatile struct mlx4_wqe_data_seg *dseg;
42         uint32_t val;
43 };
44
45 /** A table to translate Rx completion flags to packet type. */
46 uint32_t mlx4_ptype_table[0x100] __rte_cache_aligned = {
47         /*
48          * The index to the array should have:
49          *  bit[7] - MLX4_CQE_L2_TUNNEL
50          *  bit[6] - MLX4_CQE_L2_TUNNEL_IPV4
51          *  bit[5] - MLX4_CQE_STATUS_UDP
52          *  bit[4] - MLX4_CQE_STATUS_TCP
53          *  bit[3] - MLX4_CQE_STATUS_IPV4OPT
54          *  bit[2] - MLX4_CQE_STATUS_IPV6
55          *  bit[1] - MLX4_CQE_STATUS_IPV4F
56          *  bit[0] - MLX4_CQE_STATUS_IPV4
57          * giving a total of up to 256 entries.
58          */
59         [0x00] = RTE_PTYPE_L2_ETHER,
60         [0x01] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
61                      RTE_PTYPE_L4_NONFRAG,
62         [0x02] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
63                      RTE_PTYPE_L4_FRAG,
64         [0x03] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
65                      RTE_PTYPE_L4_FRAG,
66         [0x04] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
67         [0x09] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT,
68         [0x0a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
69                      RTE_PTYPE_L4_FRAG,
70         [0x11] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
71                      RTE_PTYPE_L4_TCP,
72         [0x12] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
73                      RTE_PTYPE_L4_TCP,
74         [0x14] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
75                      RTE_PTYPE_L4_TCP,
76         [0x18] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
77                      RTE_PTYPE_L4_TCP,
78         [0x19] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
79                      RTE_PTYPE_L4_TCP,
80         [0x1a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
81                      RTE_PTYPE_L4_TCP,
82         [0x21] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
83                      RTE_PTYPE_L4_UDP,
84         [0x22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
85                      RTE_PTYPE_L4_UDP,
86         [0x24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
87                      RTE_PTYPE_L4_UDP,
88         [0x28] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
89                      RTE_PTYPE_L4_UDP,
90         [0x29] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
91                      RTE_PTYPE_L4_UDP,
92         [0x2a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT |
93                      RTE_PTYPE_L4_UDP,
94         /* Tunneled - L3 IPV6 */
95         [0x80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
96         [0x81] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
97                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
98         [0x82] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
99                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
100                      RTE_PTYPE_INNER_L4_FRAG,
101         [0x83] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
102                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
103                      RTE_PTYPE_INNER_L4_FRAG,
104         [0x84] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
105                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
106         [0x88] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
107                      RTE_PTYPE_INNER_L3_IPV4_EXT,
108         [0x89] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
109                      RTE_PTYPE_INNER_L3_IPV4_EXT,
110         [0x8a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
111                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_FRAG,
112         /* Tunneled - L3 IPV6, TCP */
113         [0x91] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
114                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
115                      RTE_PTYPE_INNER_L4_TCP,
116         [0x92] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
117                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
118                      RTE_PTYPE_INNER_L4_FRAG |
119                      RTE_PTYPE_INNER_L4_TCP,
120         [0x93] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
121                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
122                      RTE_PTYPE_INNER_L4_FRAG |
123                      RTE_PTYPE_INNER_L4_TCP,
124         [0x94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
125                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
126                      RTE_PTYPE_INNER_L4_TCP,
127         [0x98] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
128                      RTE_PTYPE_INNER_L3_IPV4_EXT |
129                      RTE_PTYPE_INNER_L4_TCP,
130         [0x99] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
131                      RTE_PTYPE_INNER_L3_IPV4_EXT |
132                      RTE_PTYPE_INNER_L4_TCP,
133         [0x9a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
134                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_FRAG |
135                      RTE_PTYPE_INNER_L4_TCP,
136         /* Tunneled - L3 IPV6, UDP */
137         [0xa1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
138                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
139                      RTE_PTYPE_INNER_L4_UDP,
140         [0xa2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
141                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
142                      RTE_PTYPE_INNER_L4_FRAG |
143                      RTE_PTYPE_INNER_L4_UDP,
144         [0xa3] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
145                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
146                      RTE_PTYPE_INNER_L4_FRAG |
147                      RTE_PTYPE_INNER_L4_UDP,
148         [0xa4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
149                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
150                      RTE_PTYPE_INNER_L4_UDP,
151         [0xa8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
152                      RTE_PTYPE_INNER_L3_IPV4_EXT |
153                      RTE_PTYPE_INNER_L4_UDP,
154         [0xa9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
155                      RTE_PTYPE_INNER_L3_IPV4_EXT |
156                      RTE_PTYPE_INNER_L4_UDP,
157         [0xaa] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
158                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_FRAG |
159                      RTE_PTYPE_INNER_L4_UDP,
160         /* Tunneled - L3 IPV4 */
161         [0xc0] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
162         [0xc1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
163                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
164         [0xc2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
165                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
166                      RTE_PTYPE_INNER_L4_FRAG,
167         [0xc3] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
168                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
169                      RTE_PTYPE_INNER_L4_FRAG,
170         [0xc4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
171                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
172         [0xc8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
173                      RTE_PTYPE_INNER_L3_IPV4_EXT,
174         [0xc9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
175                      RTE_PTYPE_INNER_L3_IPV4_EXT,
176         [0xca] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
177                      RTE_PTYPE_INNER_L3_IPV4_EXT |
178                      RTE_PTYPE_INNER_L4_FRAG,
179         /* Tunneled - L3 IPV4, TCP */
180         [0xd0] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
181                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
182                      RTE_PTYPE_INNER_L4_TCP,
183         [0xd1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
184                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
185                      RTE_PTYPE_INNER_L4_TCP,
186         [0xd2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
187                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
188                      RTE_PTYPE_INNER_L4_FRAG |
189                      RTE_PTYPE_INNER_L4_TCP,
190         [0xd3] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
191                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
192                      RTE_PTYPE_INNER_L4_FRAG |
193                      RTE_PTYPE_INNER_L4_TCP,
194         [0xd4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
195                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
196                      RTE_PTYPE_INNER_L4_TCP,
197         [0xd8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
198                      RTE_PTYPE_INNER_L3_IPV4_EXT |
199                      RTE_PTYPE_INNER_L4_TCP,
200         [0xd9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
201                      RTE_PTYPE_INNER_L3_IPV4_EXT |
202                      RTE_PTYPE_INNER_L4_TCP,
203         [0xda] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
204                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_FRAG |
205                      RTE_PTYPE_INNER_L4_TCP,
206         /* Tunneled - L3 IPV4, UDP */
207         [0xe0] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
208                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
209                      RTE_PTYPE_INNER_L4_UDP,
210         [0xe1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
211                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
212                      RTE_PTYPE_INNER_L4_UDP,
213         [0xe2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
214                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
215                      RTE_PTYPE_INNER_L4_FRAG |
216                      RTE_PTYPE_INNER_L4_UDP,
217         [0xe3] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
218                      RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
219                      RTE_PTYPE_INNER_L4_FRAG |
220                      RTE_PTYPE_INNER_L4_UDP,
221         [0xe4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
222                      RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
223                      RTE_PTYPE_INNER_L4_UDP,
224         [0xe8] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
225                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_UDP,
226         [0xe9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
227                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_UDP,
228         [0xea] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
229                      RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_FRAG |
230                      RTE_PTYPE_INNER_L4_UDP,
231 };
232
233 /**
234  * Stamp TXBB burst so it won't be reused by the HW.
235  *
236  * Routine is used when freeing WQE used by the chip or when failing
237  * building an WQ entry has failed leaving partial information on the queue.
238  *
239  * @param sq
240  *   Pointer to the SQ structure.
241  * @param start
242  *   Pointer to the first TXBB to stamp.
243  * @param end
244  *   Pointer to the followed end TXBB to stamp.
245  *
246  * @return
247  *   Stamping burst size in byte units.
248  */
249 static uint32_t
250 mlx4_txq_stamp_freed_wqe(struct mlx4_sq *sq, volatile uint32_t *start,
251                          volatile uint32_t *end)
252 {
253         uint32_t stamp = sq->stamp;
254         int32_t size = (intptr_t)end - (intptr_t)start;
255
256         assert(start != end);
257         /* Hold SQ ring wrap around. */
258         if (size < 0) {
259                 size = (int32_t)sq->size + size;
260                 do {
261                         *start = stamp;
262                         start += MLX4_SQ_STAMP_DWORDS;
263                 } while (start != (volatile uint32_t *)sq->eob);
264                 start = (volatile uint32_t *)sq->buf;
265                 /* Flip invalid stamping ownership. */
266                 stamp ^= RTE_BE32(0x1 << MLX4_SQ_OWNER_BIT);
267                 sq->stamp = stamp;
268                 if (start == end)
269                         return size;
270         }
271         do {
272                 *start = stamp;
273                 start += MLX4_SQ_STAMP_DWORDS;
274         } while (start != end);
275         return (uint32_t)size;
276 }
277
278 /**
279  * Manage Tx completions.
280  *
281  * When sending a burst, mlx4_tx_burst() posts several WRs.
282  * To improve performance, a completion event is only required once every
283  * MLX4_PMD_TX_PER_COMP_REQ sends. Doing so discards completion information
284  * for other WRs, but this information would not be used anyway.
285  *
286  * @param txq
287  *   Pointer to Tx queue structure.
288  * @param elts_m
289  *   Tx elements number mask.
290  * @param sq
291  *   Pointer to the SQ structure.
292  */
293 static void
294 mlx4_txq_complete(struct txq *txq, const unsigned int elts_m,
295                   struct mlx4_sq *sq)
296 {
297         unsigned int elts_tail = txq->elts_tail;
298         struct mlx4_cq *cq = &txq->mcq;
299         volatile struct mlx4_cqe *cqe;
300         uint32_t completed;
301         uint32_t cons_index = cq->cons_index;
302         volatile uint32_t *first_txbb;
303
304         /*
305          * Traverse over all CQ entries reported and handle each WQ entry
306          * reported by them.
307          */
308         do {
309                 cqe = (volatile struct mlx4_cqe *)mlx4_get_cqe(cq, cons_index);
310                 if (unlikely(!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
311                     !!(cons_index & cq->cqe_cnt)))
312                         break;
313 #ifndef NDEBUG
314                 /*
315                  * Make sure we read the CQE after we read the ownership bit.
316                  */
317                 rte_io_rmb();
318                 if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
319                              MLX4_CQE_OPCODE_ERROR)) {
320                         volatile struct mlx4_err_cqe *cqe_err =
321                                 (volatile struct mlx4_err_cqe *)cqe;
322                         ERROR("%p CQE error - vendor syndrome: 0x%x"
323                               " syndrome: 0x%x\n",
324                               (void *)txq, cqe_err->vendor_err,
325                               cqe_err->syndrome);
326                         break;
327                 }
328 #endif /* NDEBUG */
329                 cons_index++;
330         } while (1);
331         completed = (cons_index - cq->cons_index) * txq->elts_comp_cd_init;
332         if (unlikely(!completed))
333                 return;
334         /* First stamping address is the end of the last one. */
335         first_txbb = (&(*txq->elts)[elts_tail & elts_m])->eocb;
336         elts_tail += completed;
337         /* The new tail element holds the end address. */
338         sq->remain_size += mlx4_txq_stamp_freed_wqe(sq, first_txbb,
339                 (&(*txq->elts)[elts_tail & elts_m])->eocb);
340         /* Update CQ consumer index. */
341         cq->cons_index = cons_index;
342         *cq->set_ci_db = rte_cpu_to_be_32(cons_index & MLX4_CQ_DB_CI_MASK);
343         txq->elts_tail = elts_tail;
344 }
345
346 /**
347  * Get memory pool (MP) from mbuf. If mbuf is indirect, the pool from which
348  * the cloned mbuf is allocated is returned instead.
349  *
350  * @param buf
351  *   Pointer to mbuf.
352  *
353  * @return
354  *   Memory pool where data is located for given mbuf.
355  */
356 static struct rte_mempool *
357 mlx4_txq_mb2mp(struct rte_mbuf *buf)
358 {
359         if (unlikely(RTE_MBUF_INDIRECT(buf)))
360                 return rte_mbuf_from_indirect(buf)->pool;
361         return buf->pool;
362 }
363
364 /**
365  * Write Tx data segment to the SQ.
366  *
367  * @param dseg
368  *   Pointer to data segment in SQ.
369  * @param lkey
370  *   Memory region lkey.
371  * @param addr
372  *   Data address.
373  * @param byte_count
374  *   Big endian bytes count of the data to send.
375  */
376 static inline void
377 mlx4_fill_tx_data_seg(volatile struct mlx4_wqe_data_seg *dseg,
378                        uint32_t lkey, uintptr_t addr, rte_be32_t  byte_count)
379 {
380         dseg->addr = rte_cpu_to_be_64(addr);
381         dseg->lkey = rte_cpu_to_be_32(lkey);
382 #if RTE_CACHE_LINE_SIZE < 64
383         /*
384          * Need a barrier here before writing the byte_count
385          * fields to make sure that all the data is visible
386          * before the byte_count field is set.
387          * Otherwise, if the segment begins a new cacheline,
388          * the HCA prefetcher could grab the 64-byte chunk and
389          * get a valid (!= 0xffffffff) byte count but stale
390          * data, and end up sending the wrong data.
391          */
392         rte_io_wmb();
393 #endif /* RTE_CACHE_LINE_SIZE */
394         dseg->byte_count = byte_count;
395 }
396
397 /**
398  * Write data segments of multi-segment packet.
399  *
400  * @param buf
401  *   Pointer to the first packet mbuf.
402  * @param txq
403  *   Pointer to Tx queue structure.
404  * @param ctrl
405  *   Pointer to the WQE control segment.
406  *
407  * @return
408  *   Pointer to the next WQE control segment on success, NULL otherwise.
409  */
410 static volatile struct mlx4_wqe_ctrl_seg *
411 mlx4_tx_burst_segs(struct rte_mbuf *buf, struct txq *txq,
412                    volatile struct mlx4_wqe_ctrl_seg *ctrl)
413 {
414         struct pv *pv = (struct pv *)txq->bounce_buf;
415         struct mlx4_sq *sq = &txq->msq;
416         struct rte_mbuf *sbuf = buf;
417         uint32_t lkey;
418         int pv_counter = 0;
419         int nb_segs = buf->nb_segs;
420         uint32_t wqe_size;
421         volatile struct mlx4_wqe_data_seg *dseg =
422                 (volatile struct mlx4_wqe_data_seg *)(ctrl + 1);
423
424         ctrl->fence_size = 1 + nb_segs;
425         wqe_size = RTE_ALIGN((uint32_t)(ctrl->fence_size << MLX4_SEG_SHIFT),
426                              MLX4_TXBB_SIZE);
427         /* Validate WQE size and WQE space in the send queue. */
428         if (sq->remain_size < wqe_size ||
429             wqe_size > MLX4_MAX_WQE_SIZE)
430                 return NULL;
431         /*
432          * Fill the data segments with buffer information.
433          * First WQE TXBB head segment is always control segment,
434          * so jump to tail TXBB data segments code for the first
435          * WQE data segments filling.
436          */
437         goto txbb_tail_segs;
438 txbb_head_seg:
439         /* Memory region key (big endian) for this memory pool. */
440         lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(sbuf));
441         if (unlikely(lkey == (uint32_t)-1)) {
442                 DEBUG("%p: unable to get MP <-> MR association",
443                       (void *)txq);
444                 return NULL;
445         }
446         /* Handle WQE wraparound. */
447         if (dseg >=
448                 (volatile struct mlx4_wqe_data_seg *)sq->eob)
449                 dseg = (volatile struct mlx4_wqe_data_seg *)
450                         sq->buf;
451         dseg->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(sbuf, uintptr_t));
452         dseg->lkey = rte_cpu_to_be_32(lkey);
453         /*
454          * This data segment starts at the beginning of a new
455          * TXBB, so we need to postpone its byte_count writing
456          * for later.
457          */
458         pv[pv_counter].dseg = dseg;
459         /*
460          * Zero length segment is treated as inline segment
461          * with zero data.
462          */
463         pv[pv_counter++].val = rte_cpu_to_be_32(sbuf->data_len ?
464                                                 sbuf->data_len : 0x80000000);
465         sbuf = sbuf->next;
466         dseg++;
467         nb_segs--;
468 txbb_tail_segs:
469         /* Jump to default if there are more than two segments remaining. */
470         switch (nb_segs) {
471         default:
472                 lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(sbuf));
473                 if (unlikely(lkey == (uint32_t)-1)) {
474                         DEBUG("%p: unable to get MP <-> MR association",
475                               (void *)txq);
476                         return NULL;
477                 }
478                 mlx4_fill_tx_data_seg(dseg, lkey,
479                                       rte_pktmbuf_mtod(sbuf, uintptr_t),
480                                       rte_cpu_to_be_32(sbuf->data_len ?
481                                                        sbuf->data_len :
482                                                        0x80000000));
483                 sbuf = sbuf->next;
484                 dseg++;
485                 nb_segs--;
486                 /* fallthrough */
487         case 2:
488                 lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(sbuf));
489                 if (unlikely(lkey == (uint32_t)-1)) {
490                         DEBUG("%p: unable to get MP <-> MR association",
491                               (void *)txq);
492                         return NULL;
493                 }
494                 mlx4_fill_tx_data_seg(dseg, lkey,
495                                       rte_pktmbuf_mtod(sbuf, uintptr_t),
496                                       rte_cpu_to_be_32(sbuf->data_len ?
497                                                        sbuf->data_len :
498                                                        0x80000000));
499                 sbuf = sbuf->next;
500                 dseg++;
501                 nb_segs--;
502                 /* fallthrough */
503         case 1:
504                 lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(sbuf));
505                 if (unlikely(lkey == (uint32_t)-1)) {
506                         DEBUG("%p: unable to get MP <-> MR association",
507                               (void *)txq);
508                         return NULL;
509                 }
510                 mlx4_fill_tx_data_seg(dseg, lkey,
511                                       rte_pktmbuf_mtod(sbuf, uintptr_t),
512                                       rte_cpu_to_be_32(sbuf->data_len ?
513                                                        sbuf->data_len :
514                                                        0x80000000));
515                 nb_segs--;
516                 if (nb_segs) {
517                         sbuf = sbuf->next;
518                         dseg++;
519                         goto txbb_head_seg;
520                 }
521                 /* fallthrough */
522         case 0:
523                 break;
524         }
525         /* Write the first DWORD of each TXBB save earlier. */
526         if (pv_counter) {
527                 /* Need a barrier here before writing the byte_count. */
528                 rte_io_wmb();
529                 for (--pv_counter; pv_counter  >= 0; pv_counter--)
530                         pv[pv_counter].dseg->byte_count = pv[pv_counter].val;
531         }
532         sq->remain_size -= wqe_size;
533         /* Align next WQE address to the next TXBB. */
534         return (volatile struct mlx4_wqe_ctrl_seg *)
535                 ((volatile uint8_t *)ctrl + wqe_size);
536 }
537
538 /**
539  * DPDK callback for Tx.
540  *
541  * @param dpdk_txq
542  *   Generic pointer to Tx queue structure.
543  * @param[in] pkts
544  *   Packets to transmit.
545  * @param pkts_n
546  *   Number of packets in array.
547  *
548  * @return
549  *   Number of packets successfully transmitted (<= pkts_n).
550  */
551 uint16_t
552 mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
553 {
554         struct txq *txq = (struct txq *)dpdk_txq;
555         unsigned int elts_head = txq->elts_head;
556         const unsigned int elts_n = txq->elts_n;
557         const unsigned int elts_m = elts_n - 1;
558         unsigned int bytes_sent = 0;
559         unsigned int i;
560         unsigned int max = elts_head - txq->elts_tail;
561         struct mlx4_sq *sq = &txq->msq;
562         volatile struct mlx4_wqe_ctrl_seg *ctrl;
563         struct txq_elt *elt;
564
565         assert(txq->elts_comp_cd != 0);
566         if (likely(max >= txq->elts_comp_cd_init))
567                 mlx4_txq_complete(txq, elts_m, sq);
568         max = elts_n - max;
569         assert(max >= 1);
570         assert(max <= elts_n);
571         /* Always leave one free entry in the ring. */
572         --max;
573         if (max > pkts_n)
574                 max = pkts_n;
575         elt = &(*txq->elts)[elts_head & elts_m];
576         /* First Tx burst element saves the next WQE control segment. */
577         ctrl = elt->wqe;
578         for (i = 0; (i != max); ++i) {
579                 struct rte_mbuf *buf = pkts[i];
580                 struct txq_elt *elt_next = &(*txq->elts)[++elts_head & elts_m];
581                 uint32_t owner_opcode = sq->owner_opcode;
582                 volatile struct mlx4_wqe_data_seg *dseg =
583                                 (volatile struct mlx4_wqe_data_seg *)(ctrl + 1);
584                 volatile struct mlx4_wqe_ctrl_seg *ctrl_next;
585                 union {
586                         uint32_t flags;
587                         uint16_t flags16[2];
588                 } srcrb;
589                 uint32_t lkey;
590
591                 /* Clean up old buffer. */
592                 if (likely(elt->buf != NULL)) {
593                         struct rte_mbuf *tmp = elt->buf;
594
595 #ifndef NDEBUG
596                         /* Poisoning. */
597                         memset(&elt->buf, 0x66, sizeof(struct rte_mbuf *));
598 #endif
599                         /* Faster than rte_pktmbuf_free(). */
600                         do {
601                                 struct rte_mbuf *next = tmp->next;
602
603                                 rte_pktmbuf_free_seg(tmp);
604                                 tmp = next;
605                         } while (tmp != NULL);
606                 }
607                 RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf);
608                 if (buf->nb_segs == 1) {
609                         /* Validate WQE space in the send queue. */
610                         if (sq->remain_size < MLX4_TXBB_SIZE) {
611                                 elt->buf = NULL;
612                                 break;
613                         }
614                         lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(buf));
615                         if (unlikely(lkey == (uint32_t)-1)) {
616                                 /* MR does not exist. */
617                                 DEBUG("%p: unable to get MP <-> MR association",
618                                       (void *)txq);
619                                 elt->buf = NULL;
620                                 break;
621                         }
622                         mlx4_fill_tx_data_seg(dseg++, lkey,
623                                               rte_pktmbuf_mtod(buf, uintptr_t),
624                                               rte_cpu_to_be_32(buf->data_len));
625                         /* Set WQE size in 16-byte units. */
626                         ctrl->fence_size = 0x2;
627                         sq->remain_size -= MLX4_TXBB_SIZE;
628                         /* Align next WQE address to the next TXBB. */
629                         ctrl_next = ctrl + 0x4;
630                 } else {
631                         ctrl_next = mlx4_tx_burst_segs(buf, txq, ctrl);
632                         if (!ctrl_next) {
633                                 elt->buf = NULL;
634                                 break;
635                         }
636                 }
637                 /* Hold SQ ring wrap around. */
638                 if ((volatile uint8_t *)ctrl_next >= sq->eob) {
639                         ctrl_next = (volatile struct mlx4_wqe_ctrl_seg *)
640                                 ((volatile uint8_t *)ctrl_next - sq->size);
641                         /* Flip HW valid ownership. */
642                         sq->owner_opcode ^= 0x1 << MLX4_SQ_OWNER_BIT;
643                 }
644                 /*
645                  * For raw Ethernet, the SOLICIT flag is used to indicate
646                  * that no ICRC should be calculated.
647                  */
648                 if (--txq->elts_comp_cd == 0) {
649                         /* Save the completion burst end address. */
650                         elt_next->eocb = (volatile uint32_t *)ctrl_next;
651                         txq->elts_comp_cd = txq->elts_comp_cd_init;
652                         srcrb.flags = RTE_BE32(MLX4_WQE_CTRL_SOLICIT |
653                                                MLX4_WQE_CTRL_CQ_UPDATE);
654                 } else {
655                         srcrb.flags = RTE_BE32(MLX4_WQE_CTRL_SOLICIT);
656                 }
657                 /* Enable HW checksum offload if requested */
658                 if (txq->csum &&
659                     (buf->ol_flags &
660                      (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))) {
661                         const uint64_t is_tunneled = (buf->ol_flags &
662                                                       (PKT_TX_TUNNEL_GRE |
663                                                        PKT_TX_TUNNEL_VXLAN));
664
665                         if (is_tunneled && txq->csum_l2tun) {
666                                 owner_opcode |= MLX4_WQE_CTRL_IIP_HDR_CSUM |
667                                                 MLX4_WQE_CTRL_IL4_HDR_CSUM;
668                                 if (buf->ol_flags & PKT_TX_OUTER_IP_CKSUM)
669                                         srcrb.flags |=
670                                             RTE_BE32(MLX4_WQE_CTRL_IP_HDR_CSUM);
671                         } else {
672                                 srcrb.flags |=
673                                         RTE_BE32(MLX4_WQE_CTRL_IP_HDR_CSUM |
674                                                 MLX4_WQE_CTRL_TCP_UDP_CSUM);
675                         }
676                 }
677                 if (txq->lb) {
678                         /*
679                          * Copy destination MAC address to the WQE, this allows
680                          * loopback in eSwitch, so that VFs and PF can
681                          * communicate with each other.
682                          */
683                         srcrb.flags16[0] = *(rte_pktmbuf_mtod(buf, uint16_t *));
684                         ctrl->imm = *(rte_pktmbuf_mtod_offset(buf, uint32_t *,
685                                               sizeof(uint16_t)));
686                 } else {
687                         ctrl->imm = 0;
688                 }
689                 ctrl->srcrb_flags = srcrb.flags;
690                 /*
691                  * Make sure descriptor is fully written before
692                  * setting ownership bit (because HW can start
693                  * executing as soon as we do).
694                  */
695                 rte_io_wmb();
696                 ctrl->owner_opcode = rte_cpu_to_be_32(owner_opcode);
697                 elt->buf = buf;
698                 bytes_sent += buf->pkt_len;
699                 ctrl = ctrl_next;
700                 elt = elt_next;
701         }
702         /* Take a shortcut if nothing must be sent. */
703         if (unlikely(i == 0))
704                 return 0;
705         /* Save WQE address of the next Tx burst element. */
706         elt->wqe = ctrl;
707         /* Increment send statistics counters. */
708         txq->stats.opackets += i;
709         txq->stats.obytes += bytes_sent;
710         /* Make sure that descriptors are written before doorbell record. */
711         rte_wmb();
712         /* Ring QP doorbell. */
713         rte_write32(txq->msq.doorbell_qpn, txq->msq.db);
714         txq->elts_head += i;
715         return i;
716 }
717
718 /**
719  * Translate Rx completion flags to packet type.
720  *
721  * @param[in] cqe
722  *   Pointer to CQE.
723  *
724  * @return
725  *   Packet type for struct rte_mbuf.
726  */
727 static inline uint32_t
728 rxq_cq_to_pkt_type(volatile struct mlx4_cqe *cqe,
729                    uint32_t l2tun_offload)
730 {
731         uint8_t idx = 0;
732         uint32_t pinfo = rte_be_to_cpu_32(cqe->vlan_my_qpn);
733         uint32_t status = rte_be_to_cpu_32(cqe->status);
734
735         /*
736          * The index to the array should have:
737          *  bit[7] - MLX4_CQE_L2_TUNNEL
738          *  bit[6] - MLX4_CQE_L2_TUNNEL_IPV4
739          */
740         if (l2tun_offload && (pinfo & MLX4_CQE_L2_TUNNEL))
741                 idx |= ((pinfo & MLX4_CQE_L2_TUNNEL) >> 20) |
742                        ((pinfo & MLX4_CQE_L2_TUNNEL_IPV4) >> 19);
743         /*
744          * The index to the array should have:
745          *  bit[5] - MLX4_CQE_STATUS_UDP
746          *  bit[4] - MLX4_CQE_STATUS_TCP
747          *  bit[3] - MLX4_CQE_STATUS_IPV4OPT
748          *  bit[2] - MLX4_CQE_STATUS_IPV6
749          *  bit[1] - MLX4_CQE_STATUS_IPV4F
750          *  bit[0] - MLX4_CQE_STATUS_IPV4
751          * giving a total of up to 256 entries.
752          */
753         idx |= ((status & MLX4_CQE_STATUS_PTYPE_MASK) >> 22);
754         return mlx4_ptype_table[idx];
755 }
756
757 /**
758  * Translate Rx completion flags to offload flags.
759  *
760  * @param flags
761  *   Rx completion flags returned by mlx4_cqe_flags().
762  * @param csum
763  *   Whether Rx checksums are enabled.
764  * @param csum_l2tun
765  *   Whether Rx L2 tunnel checksums are enabled.
766  *
767  * @return
768  *   Offload flags (ol_flags) in mbuf format.
769  */
770 static inline uint32_t
771 rxq_cq_to_ol_flags(uint32_t flags, int csum, int csum_l2tun)
772 {
773         uint32_t ol_flags = 0;
774
775         if (csum)
776                 ol_flags |=
777                         mlx4_transpose(flags,
778                                        MLX4_CQE_STATUS_IP_HDR_CSUM_OK,
779                                        PKT_RX_IP_CKSUM_GOOD) |
780                         mlx4_transpose(flags,
781                                        MLX4_CQE_STATUS_TCP_UDP_CSUM_OK,
782                                        PKT_RX_L4_CKSUM_GOOD);
783         if ((flags & MLX4_CQE_L2_TUNNEL) && csum_l2tun)
784                 ol_flags |=
785                         mlx4_transpose(flags,
786                                        MLX4_CQE_L2_TUNNEL_IPOK,
787                                        PKT_RX_IP_CKSUM_GOOD) |
788                         mlx4_transpose(flags,
789                                        MLX4_CQE_L2_TUNNEL_L4_CSUM,
790                                        PKT_RX_L4_CKSUM_GOOD);
791         return ol_flags;
792 }
793
794 /**
795  * Extract checksum information from CQE flags.
796  *
797  * @param cqe
798  *   Pointer to CQE structure.
799  * @param csum
800  *   Whether Rx checksums are enabled.
801  * @param csum_l2tun
802  *   Whether Rx L2 tunnel checksums are enabled.
803  *
804  * @return
805  *   CQE checksum information.
806  */
807 static inline uint32_t
808 mlx4_cqe_flags(volatile struct mlx4_cqe *cqe, int csum, int csum_l2tun)
809 {
810         uint32_t flags = 0;
811
812         /*
813          * The relevant bits are in different locations on their
814          * CQE fields therefore we can join them in one 32bit
815          * variable.
816          */
817         if (csum)
818                 flags = (rte_be_to_cpu_32(cqe->status) &
819                          MLX4_CQE_STATUS_IPV4_CSUM_OK);
820         if (csum_l2tun)
821                 flags |= (rte_be_to_cpu_32(cqe->vlan_my_qpn) &
822                           (MLX4_CQE_L2_TUNNEL |
823                            MLX4_CQE_L2_TUNNEL_IPOK |
824                            MLX4_CQE_L2_TUNNEL_L4_CSUM |
825                            MLX4_CQE_L2_TUNNEL_IPV4));
826         return flags;
827 }
828
829 /**
830  * Poll one CQE from CQ.
831  *
832  * @param rxq
833  *   Pointer to the receive queue structure.
834  * @param[out] out
835  *   Just polled CQE.
836  *
837  * @return
838  *   Number of bytes of the CQE, 0 in case there is no completion.
839  */
840 static unsigned int
841 mlx4_cq_poll_one(struct rxq *rxq, volatile struct mlx4_cqe **out)
842 {
843         int ret = 0;
844         volatile struct mlx4_cqe *cqe = NULL;
845         struct mlx4_cq *cq = &rxq->mcq;
846
847         cqe = (volatile struct mlx4_cqe *)mlx4_get_cqe(cq, cq->cons_index);
848         if (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
849             !!(cq->cons_index & cq->cqe_cnt))
850                 goto out;
851         /*
852          * Make sure we read CQ entry contents after we've checked the
853          * ownership bit.
854          */
855         rte_rmb();
856         assert(!(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK));
857         assert((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) !=
858                MLX4_CQE_OPCODE_ERROR);
859         ret = rte_be_to_cpu_32(cqe->byte_cnt);
860         ++cq->cons_index;
861 out:
862         *out = cqe;
863         return ret;
864 }
865
866 /**
867  * DPDK callback for Rx with scattered packets support.
868  *
869  * @param dpdk_rxq
870  *   Generic pointer to Rx queue structure.
871  * @param[out] pkts
872  *   Array to store received packets.
873  * @param pkts_n
874  *   Maximum number of packets in array.
875  *
876  * @return
877  *   Number of packets successfully received (<= pkts_n).
878  */
879 uint16_t
880 mlx4_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
881 {
882         struct rxq *rxq = dpdk_rxq;
883         const uint32_t wr_cnt = (1 << rxq->elts_n) - 1;
884         const uint16_t sges_n = rxq->sges_n;
885         struct rte_mbuf *pkt = NULL;
886         struct rte_mbuf *seg = NULL;
887         unsigned int i = 0;
888         uint32_t rq_ci = rxq->rq_ci << sges_n;
889         int len = 0;
890
891         while (pkts_n) {
892                 volatile struct mlx4_cqe *cqe;
893                 uint32_t idx = rq_ci & wr_cnt;
894                 struct rte_mbuf *rep = (*rxq->elts)[idx];
895                 volatile struct mlx4_wqe_data_seg *scat = &(*rxq->wqes)[idx];
896
897                 /* Update the 'next' pointer of the previous segment. */
898                 if (pkt)
899                         seg->next = rep;
900                 seg = rep;
901                 rte_prefetch0(seg);
902                 rte_prefetch0(scat);
903                 rep = rte_mbuf_raw_alloc(rxq->mp);
904                 if (unlikely(rep == NULL)) {
905                         ++rxq->stats.rx_nombuf;
906                         if (!pkt) {
907                                 /*
908                                  * No buffers before we even started,
909                                  * bail out silently.
910                                  */
911                                 break;
912                         }
913                         while (pkt != seg) {
914                                 assert(pkt != (*rxq->elts)[idx]);
915                                 rep = pkt->next;
916                                 pkt->next = NULL;
917                                 pkt->nb_segs = 1;
918                                 rte_mbuf_raw_free(pkt);
919                                 pkt = rep;
920                         }
921                         break;
922                 }
923                 if (!pkt) {
924                         /* Looking for the new packet. */
925                         len = mlx4_cq_poll_one(rxq, &cqe);
926                         if (!len) {
927                                 rte_mbuf_raw_free(rep);
928                                 break;
929                         }
930                         if (unlikely(len < 0)) {
931                                 /* Rx error, packet is likely too large. */
932                                 rte_mbuf_raw_free(rep);
933                                 ++rxq->stats.idropped;
934                                 goto skip;
935                         }
936                         pkt = seg;
937                         /* Update packet information. */
938                         pkt->packet_type =
939                                 rxq_cq_to_pkt_type(cqe, rxq->l2tun_offload);
940                         pkt->ol_flags = PKT_RX_RSS_HASH;
941                         pkt->hash.rss = cqe->immed_rss_invalid;
942                         pkt->pkt_len = len;
943                         if (rxq->csum | rxq->csum_l2tun) {
944                                 uint32_t flags =
945                                         mlx4_cqe_flags(cqe,
946                                                        rxq->csum,
947                                                        rxq->csum_l2tun);
948
949                                 pkt->ol_flags =
950                                         rxq_cq_to_ol_flags(flags,
951                                                            rxq->csum,
952                                                            rxq->csum_l2tun);
953                         }
954                 }
955                 rep->nb_segs = 1;
956                 rep->port = rxq->port_id;
957                 rep->data_len = seg->data_len;
958                 rep->data_off = seg->data_off;
959                 (*rxq->elts)[idx] = rep;
960                 /*
961                  * Fill NIC descriptor with the new buffer. The lkey and size
962                  * of the buffers are already known, only the buffer address
963                  * changes.
964                  */
965                 scat->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(rep, uintptr_t));
966                 if (len > seg->data_len) {
967                         len -= seg->data_len;
968                         ++pkt->nb_segs;
969                         ++rq_ci;
970                         continue;
971                 }
972                 /* The last segment. */
973                 seg->data_len = len;
974                 /* Increment bytes counter. */
975                 rxq->stats.ibytes += pkt->pkt_len;
976                 /* Return packet. */
977                 *(pkts++) = pkt;
978                 pkt = NULL;
979                 --pkts_n;
980                 ++i;
981 skip:
982                 /* Align consumer index to the next stride. */
983                 rq_ci >>= sges_n;
984                 ++rq_ci;
985                 rq_ci <<= sges_n;
986         }
987         if (unlikely(i == 0 && (rq_ci >> sges_n) == rxq->rq_ci))
988                 return 0;
989         /* Update the consumer index. */
990         rxq->rq_ci = rq_ci >> sges_n;
991         rte_wmb();
992         *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
993         *rxq->mcq.set_ci_db =
994                 rte_cpu_to_be_32(rxq->mcq.cons_index & MLX4_CQ_DB_CI_MASK);
995         /* Increment packets counter. */
996         rxq->stats.ipackets += i;
997         return i;
998 }
999
1000 /**
1001  * Dummy DPDK callback for Tx.
1002  *
1003  * This function is used to temporarily replace the real callback during
1004  * unsafe control operations on the queue, or in case of error.
1005  *
1006  * @param dpdk_txq
1007  *   Generic pointer to Tx queue structure.
1008  * @param[in] pkts
1009  *   Packets to transmit.
1010  * @param pkts_n
1011  *   Number of packets in array.
1012  *
1013  * @return
1014  *   Number of packets successfully transmitted (<= pkts_n).
1015  */
1016 uint16_t
1017 mlx4_tx_burst_removed(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
1018 {
1019         (void)dpdk_txq;
1020         (void)pkts;
1021         (void)pkts_n;
1022         return 0;
1023 }
1024
1025 /**
1026  * Dummy DPDK callback for Rx.
1027  *
1028  * This function is used to temporarily replace the real callback during
1029  * unsafe control operations on the queue, or in case of error.
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 mlx4_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
1043 {
1044         (void)dpdk_rxq;
1045         (void)pkts;
1046         (void)pkts_n;
1047         return 0;
1048 }