net/mlx4: separate Rx/Tx functions
[dpdk.git] / drivers / net / mlx4 / mlx4_rxtx.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2017 6WIND S.A.
5  *   Copyright 2017 Mellanox
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /**
35  * @file
36  * Data plane functions for mlx4 driver.
37  */
38
39 #include <assert.h>
40 #include <inttypes.h>
41 #include <stdint.h>
42 #include <string.h>
43
44 /* Verbs headers do not support -pedantic. */
45 #ifdef PEDANTIC
46 #pragma GCC diagnostic ignored "-Wpedantic"
47 #endif
48 #include <infiniband/verbs.h>
49 #ifdef PEDANTIC
50 #pragma GCC diagnostic error "-Wpedantic"
51 #endif
52
53 #include <rte_branch_prediction.h>
54 #include <rte_common.h>
55 #include <rte_mbuf.h>
56 #include <rte_mempool.h>
57 #include <rte_prefetch.h>
58
59 #include "mlx4.h"
60 #include "mlx4_rxtx.h"
61 #include "mlx4_utils.h"
62
63 /**
64  * Manage Tx completions.
65  *
66  * When sending a burst, mlx4_tx_burst() posts several WRs.
67  * To improve performance, a completion event is only required once every
68  * MLX4_PMD_TX_PER_COMP_REQ sends. Doing so discards completion information
69  * for other WRs, but this information would not be used anyway.
70  *
71  * @param txq
72  *   Pointer to Tx queue structure.
73  *
74  * @return
75  *   0 on success, -1 on failure.
76  */
77 static int
78 mlx4_txq_complete(struct txq *txq)
79 {
80         unsigned int elts_comp = txq->elts_comp;
81         unsigned int elts_tail = txq->elts_tail;
82         const unsigned int elts_n = txq->elts_n;
83         struct ibv_wc wcs[elts_comp];
84         int wcs_n;
85
86         if (unlikely(elts_comp == 0))
87                 return 0;
88         wcs_n = ibv_poll_cq(txq->cq, elts_comp, wcs);
89         if (unlikely(wcs_n == 0))
90                 return 0;
91         if (unlikely(wcs_n < 0)) {
92                 DEBUG("%p: ibv_poll_cq() failed (wcs_n=%d)",
93                       (void *)txq, wcs_n);
94                 return -1;
95         }
96         elts_comp -= wcs_n;
97         assert(elts_comp <= txq->elts_comp);
98         /*
99          * Assume WC status is successful as nothing can be done about it
100          * anyway.
101          */
102         elts_tail += wcs_n * txq->elts_comp_cd_init;
103         if (elts_tail >= elts_n)
104                 elts_tail -= elts_n;
105         txq->elts_tail = elts_tail;
106         txq->elts_comp = elts_comp;
107         return 0;
108 }
109
110 /**
111  * Get memory pool (MP) from mbuf. If mbuf is indirect, the pool from which
112  * the cloned mbuf is allocated is returned instead.
113  *
114  * @param buf
115  *   Pointer to mbuf.
116  *
117  * @return
118  *   Memory pool where data is located for given mbuf.
119  */
120 static struct rte_mempool *
121 mlx4_txq_mb2mp(struct rte_mbuf *buf)
122 {
123         if (unlikely(RTE_MBUF_INDIRECT(buf)))
124                 return rte_mbuf_from_indirect(buf)->pool;
125         return buf->pool;
126 }
127
128 /**
129  * Get memory region (MR) <-> memory pool (MP) association from txq->mp2mr[].
130  * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
131  * remove an entry first.
132  *
133  * @param txq
134  *   Pointer to Tx queue structure.
135  * @param[in] mp
136  *   Memory pool for which a memory region lkey must be returned.
137  *
138  * @return
139  *   mr->lkey on success, (uint32_t)-1 on failure.
140  */
141 uint32_t
142 mlx4_txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
143 {
144         unsigned int i;
145         struct ibv_mr *mr;
146
147         for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
148                 if (unlikely(txq->mp2mr[i].mp == NULL)) {
149                         /* Unknown MP, add a new MR for it. */
150                         break;
151                 }
152                 if (txq->mp2mr[i].mp == mp) {
153                         assert(txq->mp2mr[i].lkey != (uint32_t)-1);
154                         assert(txq->mp2mr[i].mr->lkey == txq->mp2mr[i].lkey);
155                         return txq->mp2mr[i].lkey;
156                 }
157         }
158         /* Add a new entry, register MR first. */
159         DEBUG("%p: discovered new memory pool \"%s\" (%p)",
160               (void *)txq, mp->name, (void *)mp);
161         mr = mlx4_mp2mr(txq->priv->pd, mp);
162         if (unlikely(mr == NULL)) {
163                 DEBUG("%p: unable to configure MR, ibv_reg_mr() failed.",
164                       (void *)txq);
165                 return (uint32_t)-1;
166         }
167         if (unlikely(i == RTE_DIM(txq->mp2mr))) {
168                 /* Table is full, remove oldest entry. */
169                 DEBUG("%p: MR <-> MP table full, dropping oldest entry.",
170                       (void *)txq);
171                 --i;
172                 claim_zero(ibv_dereg_mr(txq->mp2mr[0].mr));
173                 memmove(&txq->mp2mr[0], &txq->mp2mr[1],
174                         (sizeof(txq->mp2mr) - sizeof(txq->mp2mr[0])));
175         }
176         /* Store the new entry. */
177         txq->mp2mr[i].mp = mp;
178         txq->mp2mr[i].mr = mr;
179         txq->mp2mr[i].lkey = mr->lkey;
180         DEBUG("%p: new MR lkey for MP \"%s\" (%p): 0x%08" PRIu32,
181               (void *)txq, mp->name, (void *)mp, txq->mp2mr[i].lkey);
182         return txq->mp2mr[i].lkey;
183 }
184
185 /**
186  * DPDK callback for Tx.
187  *
188  * @param dpdk_txq
189  *   Generic pointer to Tx queue structure.
190  * @param[in] pkts
191  *   Packets to transmit.
192  * @param pkts_n
193  *   Number of packets in array.
194  *
195  * @return
196  *   Number of packets successfully transmitted (<= pkts_n).
197  */
198 uint16_t
199 mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
200 {
201         struct txq *txq = (struct txq *)dpdk_txq;
202         struct ibv_send_wr *wr_head = NULL;
203         struct ibv_send_wr **wr_next = &wr_head;
204         struct ibv_send_wr *wr_bad = NULL;
205         unsigned int elts_head = txq->elts_head;
206         const unsigned int elts_n = txq->elts_n;
207         unsigned int elts_comp_cd = txq->elts_comp_cd;
208         unsigned int elts_comp = 0;
209         unsigned int i;
210         unsigned int max;
211         int err;
212
213         assert(elts_comp_cd != 0);
214         mlx4_txq_complete(txq);
215         max = (elts_n - (elts_head - txq->elts_tail));
216         if (max > elts_n)
217                 max -= elts_n;
218         assert(max >= 1);
219         assert(max <= elts_n);
220         /* Always leave one free entry in the ring. */
221         --max;
222         if (max == 0)
223                 return 0;
224         if (max > pkts_n)
225                 max = pkts_n;
226         for (i = 0; (i != max); ++i) {
227                 struct rte_mbuf *buf = pkts[i];
228                 unsigned int elts_head_next =
229                         (((elts_head + 1) == elts_n) ? 0 : elts_head + 1);
230                 struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];
231                 struct txq_elt *elt = &(*txq->elts)[elts_head];
232                 struct ibv_send_wr *wr = &elt->wr;
233                 unsigned int segs = buf->nb_segs;
234                 unsigned int sent_size = 0;
235                 uint32_t send_flags = 0;
236
237                 /* Clean up old buffer. */
238                 if (likely(elt->buf != NULL)) {
239                         struct rte_mbuf *tmp = elt->buf;
240
241 #ifndef NDEBUG
242                         /* Poisoning. */
243                         memset(elt, 0x66, sizeof(*elt));
244 #endif
245                         /* Faster than rte_pktmbuf_free(). */
246                         do {
247                                 struct rte_mbuf *next = tmp->next;
248
249                                 rte_pktmbuf_free_seg(tmp);
250                                 tmp = next;
251                         } while (tmp != NULL);
252                 }
253                 /* Request Tx completion. */
254                 if (unlikely(--elts_comp_cd == 0)) {
255                         elts_comp_cd = txq->elts_comp_cd_init;
256                         ++elts_comp;
257                         send_flags |= IBV_SEND_SIGNALED;
258                 }
259                 if (likely(segs == 1)) {
260                         struct ibv_sge *sge = &elt->sge;
261                         uintptr_t addr;
262                         uint32_t length;
263                         uint32_t lkey;
264
265                         /* Retrieve buffer information. */
266                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
267                         length = buf->data_len;
268                         /* Retrieve memory region key for this memory pool. */
269                         lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(buf));
270                         if (unlikely(lkey == (uint32_t)-1)) {
271                                 /* MR does not exist. */
272                                 DEBUG("%p: unable to get MP <-> MR"
273                                       " association", (void *)txq);
274                                 /* Clean up Tx element. */
275                                 elt->buf = NULL;
276                                 goto stop;
277                         }
278                         /* Update element. */
279                         elt->buf = buf;
280                         if (txq->priv->vf)
281                                 rte_prefetch0((volatile void *)
282                                               (uintptr_t)addr);
283                         RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf);
284                         sge->addr = addr;
285                         sge->length = length;
286                         sge->lkey = lkey;
287                         sent_size += length;
288                 } else {
289                         err = -1;
290                         goto stop;
291                 }
292                 if (sent_size <= txq->max_inline)
293                         send_flags |= IBV_SEND_INLINE;
294                 elts_head = elts_head_next;
295                 /* Increment sent bytes counter. */
296                 txq->stats.obytes += sent_size;
297                 /* Set up WR. */
298                 wr->sg_list = &elt->sge;
299                 wr->num_sge = segs;
300                 wr->opcode = IBV_WR_SEND;
301                 wr->send_flags = send_flags;
302                 *wr_next = wr;
303                 wr_next = &wr->next;
304         }
305 stop:
306         /* Take a shortcut if nothing must be sent. */
307         if (unlikely(i == 0))
308                 return 0;
309         /* Increment sent packets counter. */
310         txq->stats.opackets += i;
311         /* Ring QP doorbell. */
312         *wr_next = NULL;
313         assert(wr_head);
314         err = ibv_post_send(txq->qp, wr_head, &wr_bad);
315         if (unlikely(err)) {
316                 uint64_t obytes = 0;
317                 uint64_t opackets = 0;
318
319                 /* Rewind bad WRs. */
320                 while (wr_bad != NULL) {
321                         int j;
322
323                         /* Force completion request if one was lost. */
324                         if (wr_bad->send_flags & IBV_SEND_SIGNALED) {
325                                 elts_comp_cd = 1;
326                                 --elts_comp;
327                         }
328                         ++opackets;
329                         for (j = 0; j < wr_bad->num_sge; ++j)
330                                 obytes += wr_bad->sg_list[j].length;
331                         elts_head = (elts_head ? elts_head : elts_n) - 1;
332                         wr_bad = wr_bad->next;
333                 }
334                 txq->stats.opackets -= opackets;
335                 txq->stats.obytes -= obytes;
336                 i -= opackets;
337                 DEBUG("%p: ibv_post_send() failed, %" PRIu64 " packets"
338                       " (%" PRIu64 " bytes) rejected: %s",
339                       (void *)txq,
340                       opackets,
341                       obytes,
342                       (err <= -1) ? "Internal error" : strerror(err));
343         }
344         txq->elts_head = elts_head;
345         txq->elts_comp += elts_comp;
346         txq->elts_comp_cd = elts_comp_cd;
347         return i;
348 }
349
350 /**
351  * DPDK callback for Rx.
352  *
353  * The following function doesn't manage scattered packets.
354  *
355  * @param dpdk_rxq
356  *   Generic pointer to Rx queue structure.
357  * @param[out] pkts
358  *   Array to store received packets.
359  * @param pkts_n
360  *   Maximum number of packets in array.
361  *
362  * @return
363  *   Number of packets successfully received (<= pkts_n).
364  */
365 uint16_t
366 mlx4_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
367 {
368         struct rxq *rxq = (struct rxq *)dpdk_rxq;
369         struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts;
370         const unsigned int elts_n = rxq->elts_n;
371         unsigned int elts_head = rxq->elts_head;
372         struct ibv_wc wcs[pkts_n];
373         struct ibv_recv_wr *wr_head = NULL;
374         struct ibv_recv_wr **wr_next = &wr_head;
375         struct ibv_recv_wr *wr_bad = NULL;
376         unsigned int i;
377         unsigned int pkts_ret = 0;
378         int ret;
379
380         ret = ibv_poll_cq(rxq->cq, pkts_n, wcs);
381         if (unlikely(ret == 0))
382                 return 0;
383         if (unlikely(ret < 0)) {
384                 DEBUG("rxq=%p, ibv_poll_cq() failed (wc_n=%d)",
385                       (void *)rxq, ret);
386                 return 0;
387         }
388         assert(ret <= (int)pkts_n);
389         /* For each work completion. */
390         for (i = 0; i != (unsigned int)ret; ++i) {
391                 struct ibv_wc *wc = &wcs[i];
392                 struct rxq_elt *elt = &(*elts)[elts_head];
393                 struct ibv_recv_wr *wr = &elt->wr;
394                 uint32_t len = wc->byte_len;
395                 struct rte_mbuf *seg = elt->buf;
396                 struct rte_mbuf *rep;
397
398                 /* Sanity checks. */
399                 assert(wr->sg_list == &elt->sge);
400                 assert(wr->num_sge == 1);
401                 assert(elts_head < rxq->elts_n);
402                 assert(rxq->elts_head < rxq->elts_n);
403                 /*
404                  * Fetch initial bytes of packet descriptor into a
405                  * cacheline while allocating rep.
406                  */
407                 rte_mbuf_prefetch_part1(seg);
408                 rte_mbuf_prefetch_part2(seg);
409                 /* Link completed WRs together for repost. */
410                 *wr_next = wr;
411                 wr_next = &wr->next;
412                 if (unlikely(wc->status != IBV_WC_SUCCESS)) {
413                         /* Whatever, just repost the offending WR. */
414                         DEBUG("rxq=%p: bad work completion status (%d): %s",
415                               (void *)rxq, wc->status,
416                               ibv_wc_status_str(wc->status));
417                         /* Increment dropped packets counter. */
418                         ++rxq->stats.idropped;
419                         goto repost;
420                 }
421                 rep = rte_mbuf_raw_alloc(rxq->mp);
422                 if (unlikely(rep == NULL)) {
423                         /*
424                          * Unable to allocate a replacement mbuf,
425                          * repost WR.
426                          */
427                         DEBUG("rxq=%p: can't allocate a new mbuf",
428                               (void *)rxq);
429                         /* Increase out of memory counters. */
430                         ++rxq->stats.rx_nombuf;
431                         ++rxq->priv->dev->data->rx_mbuf_alloc_failed;
432                         goto repost;
433                 }
434                 /* Reconfigure sge to use rep instead of seg. */
435                 elt->sge.addr = (uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM;
436                 assert(elt->sge.lkey == rxq->mr->lkey);
437                 elt->buf = rep;
438                 /* Update seg information. */
439                 seg->data_off = RTE_PKTMBUF_HEADROOM;
440                 seg->nb_segs = 1;
441                 seg->port = rxq->port_id;
442                 seg->next = NULL;
443                 seg->pkt_len = len;
444                 seg->data_len = len;
445                 seg->packet_type = 0;
446                 seg->ol_flags = 0;
447                 /* Return packet. */
448                 *(pkts++) = seg;
449                 ++pkts_ret;
450                 /* Increase bytes counter. */
451                 rxq->stats.ibytes += len;
452 repost:
453                 if (++elts_head >= elts_n)
454                         elts_head = 0;
455                 continue;
456         }
457         if (unlikely(i == 0))
458                 return 0;
459         /* Repost WRs. */
460         *wr_next = NULL;
461         assert(wr_head);
462         ret = ibv_post_recv(rxq->qp, wr_head, &wr_bad);
463         if (unlikely(ret)) {
464                 /* Inability to repost WRs is fatal. */
465                 DEBUG("%p: recv_burst(): failed (ret=%d)",
466                       (void *)rxq->priv,
467                       ret);
468                 abort();
469         }
470         rxq->elts_head = elts_head;
471         /* Increase packets counter. */
472         rxq->stats.ipackets += pkts_ret;
473         return pkts_ret;
474 }
475
476 /**
477  * Dummy DPDK callback for Tx.
478  *
479  * This function is used to temporarily replace the real callback during
480  * unsafe control operations on the queue, or in case of error.
481  *
482  * @param dpdk_txq
483  *   Generic pointer to Tx queue structure.
484  * @param[in] pkts
485  *   Packets to transmit.
486  * @param pkts_n
487  *   Number of packets in array.
488  *
489  * @return
490  *   Number of packets successfully transmitted (<= pkts_n).
491  */
492 uint16_t
493 mlx4_tx_burst_removed(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
494 {
495         (void)dpdk_txq;
496         (void)pkts;
497         (void)pkts_n;
498         return 0;
499 }
500
501 /**
502  * Dummy DPDK callback for Rx.
503  *
504  * This function is used to temporarily replace the real callback during
505  * unsafe control operations on the queue, or in case of error.
506  *
507  * @param dpdk_rxq
508  *   Generic pointer to Rx queue structure.
509  * @param[out] pkts
510  *   Array to store received packets.
511  * @param pkts_n
512  *   Maximum number of packets in array.
513  *
514  * @return
515  *   Number of packets successfully received (<= pkts_n).
516  */
517 uint16_t
518 mlx4_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
519 {
520         (void)dpdk_rxq;
521         (void)pkts;
522         (void)pkts_n;
523         return 0;
524 }