mlx5: refactor Rx code for the new verbs RSS API
[dpdk.git] / drivers / net / mlx5 / mlx5_rxq.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2015 6WIND S.A.
5  *   Copyright 2015 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 #include <stddef.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <stdint.h>
39
40 /* Verbs header. */
41 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
42 #ifdef PEDANTIC
43 #pragma GCC diagnostic ignored "-pedantic"
44 #endif
45 #include <infiniband/verbs.h>
46 #ifdef PEDANTIC
47 #pragma GCC diagnostic error "-pedantic"
48 #endif
49
50 /* DPDK headers don't like -pedantic. */
51 #ifdef PEDANTIC
52 #pragma GCC diagnostic ignored "-pedantic"
53 #endif
54 #include <rte_mbuf.h>
55 #include <rte_malloc.h>
56 #include <rte_ethdev.h>
57 #include <rte_common.h>
58 #ifdef PEDANTIC
59 #pragma GCC diagnostic error "-pedantic"
60 #endif
61
62 #include "mlx5.h"
63 #include "mlx5_rxtx.h"
64 #include "mlx5_utils.h"
65 #include "mlx5_defs.h"
66
67 /* Default RSS hash key also used for ConnectX-3. */
68 static uint8_t hash_rxq_default_key[] = {
69         0x2c, 0xc6, 0x81, 0xd1,
70         0x5b, 0xdb, 0xf4, 0xf7,
71         0xfc, 0xa2, 0x83, 0x19,
72         0xdb, 0x1a, 0x3e, 0x94,
73         0x6b, 0x9e, 0x38, 0xd9,
74         0x2c, 0x9c, 0x03, 0xd1,
75         0xad, 0x99, 0x44, 0xa7,
76         0xd9, 0x56, 0x3d, 0x59,
77         0x06, 0x3c, 0x25, 0xf3,
78         0xfc, 0x1f, 0xdc, 0x2a,
79 };
80
81 /**
82  * Return nearest power of two above input value.
83  *
84  * @param v
85  *   Input value.
86  *
87  * @return
88  *   Nearest power of two above input value.
89  */
90 static unsigned int
91 log2above(unsigned int v)
92 {
93         unsigned int l;
94         unsigned int r;
95
96         for (l = 0, r = 0; (v >> 1); ++l, v >>= 1)
97                 r |= (v & 1);
98         return (l + r);
99 }
100
101 /**
102  * Initialize hash RX queues and indirection table.
103  *
104  * @param priv
105  *   Pointer to private structure.
106  *
107  * @return
108  *   0 on success, errno value on failure.
109  */
110 int
111 priv_create_hash_rxqs(struct priv *priv)
112 {
113         static const uint64_t rss_hash_table[] = {
114                 /* TCPv4. */
115                 (IBV_EXP_RX_HASH_SRC_IPV4 | IBV_EXP_RX_HASH_DST_IPV4 |
116                  IBV_EXP_RX_HASH_SRC_PORT_TCP | IBV_EXP_RX_HASH_DST_PORT_TCP),
117                 /* UDPv4. */
118                 (IBV_EXP_RX_HASH_SRC_IPV4 | IBV_EXP_RX_HASH_DST_IPV4 |
119                  IBV_EXP_RX_HASH_SRC_PORT_UDP | IBV_EXP_RX_HASH_DST_PORT_UDP),
120                 /* Other IPv4. */
121                 (IBV_EXP_RX_HASH_SRC_IPV4 | IBV_EXP_RX_HASH_DST_IPV4),
122                 /* None, used for everything else. */
123                 0,
124         };
125
126         DEBUG("allocating hash RX queues for %u WQs", priv->rxqs_n);
127         assert(priv->ind_table == NULL);
128         assert(priv->hash_rxqs == NULL);
129         assert(priv->hash_rxqs_n == 0);
130         assert(priv->pd != NULL);
131         assert(priv->ctx != NULL);
132         if (priv->rxqs_n == 0)
133                 return EINVAL;
134         assert(priv->rxqs != NULL);
135
136         /* FIXME: large data structures are allocated on the stack. */
137         unsigned int wqs_n = (1 << log2above(priv->rxqs_n));
138         struct ibv_exp_wq *wqs[wqs_n];
139         struct ibv_exp_rwq_ind_table_init_attr ind_init_attr = {
140                 .pd = priv->pd,
141                 .log_ind_tbl_size = log2above(priv->rxqs_n),
142                 .ind_tbl = wqs,
143                 .comp_mask = 0,
144         };
145         struct ibv_exp_rwq_ind_table *ind_table = NULL;
146         /* If only one RX queue is configured, RSS is not needed and a single
147          * empty hash entry is used (last rss_hash_table[] entry). */
148         unsigned int hash_rxqs_n =
149                 ((priv->rxqs_n == 1) ? 1 : RTE_DIM(rss_hash_table));
150         struct hash_rxq (*hash_rxqs)[hash_rxqs_n] = NULL;
151         unsigned int i;
152         unsigned int j;
153         int err = 0;
154
155         if (wqs_n < priv->rxqs_n) {
156                 ERROR("cannot handle this many RX queues (%u)", priv->rxqs_n);
157                 err = ERANGE;
158                 goto error;
159         }
160         if (wqs_n != priv->rxqs_n)
161                 WARN("%u RX queues are configured, consider rounding this"
162                      " number to the next power of two (%u) for optimal"
163                      " performance",
164                      priv->rxqs_n, wqs_n);
165         /* When the number of RX queues is not a power of two, the remaining
166          * table entries are padded with reused WQs and hashes are not spread
167          * uniformly. */
168         for (i = 0, j = 0; (i != wqs_n); ++i) {
169                 wqs[i] = (*priv->rxqs)[j]->wq;
170                 if (++j == priv->rxqs_n)
171                         j = 0;
172         }
173         errno = 0;
174         ind_table = ibv_exp_create_rwq_ind_table(priv->ctx, &ind_init_attr);
175         if (ind_table == NULL) {
176                 /* Not clear whether errno is set. */
177                 err = (errno ? errno : EINVAL);
178                 ERROR("RX indirection table creation failed with error %d: %s",
179                       err, strerror(err));
180                 goto error;
181         }
182         /* Allocate array that holds hash RX queues and related data. */
183         hash_rxqs = rte_malloc(__func__, sizeof(*hash_rxqs), 0);
184         if (hash_rxqs == NULL) {
185                 err = ENOMEM;
186                 ERROR("cannot allocate hash RX queues container: %s",
187                       strerror(err));
188                 goto error;
189         }
190         for (i = 0, j = (RTE_DIM(rss_hash_table) - hash_rxqs_n);
191              (j != RTE_DIM(rss_hash_table));
192              ++i, ++j) {
193                 struct hash_rxq *hash_rxq = &(*hash_rxqs)[i];
194
195                 struct ibv_exp_rx_hash_conf hash_conf = {
196                         .rx_hash_function = IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
197                         .rx_hash_key_len = sizeof(hash_rxq_default_key),
198                         .rx_hash_key = hash_rxq_default_key,
199                         .rx_hash_fields_mask = rss_hash_table[j],
200                         .rwq_ind_tbl = ind_table,
201                 };
202                 struct ibv_exp_qp_init_attr qp_init_attr = {
203                         .max_inl_recv = 0, /* Currently not supported. */
204                         .qp_type = IBV_QPT_RAW_PACKET,
205                         .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD |
206                                       IBV_EXP_QP_INIT_ATTR_RX_HASH),
207                         .pd = priv->pd,
208                         .rx_hash_conf = &hash_conf,
209                         .port_num = priv->port,
210                 };
211
212                 *hash_rxq = (struct hash_rxq){
213                         .priv = priv,
214                         .qp = ibv_exp_create_qp(priv->ctx, &qp_init_attr),
215                 };
216                 if (hash_rxq->qp == NULL) {
217                         err = (errno ? errno : EINVAL);
218                         ERROR("Hash RX QP creation failure: %s",
219                               strerror(err));
220                         while (i) {
221                                 hash_rxq = &(*hash_rxqs)[--i];
222                                 claim_zero(ibv_destroy_qp(hash_rxq->qp));
223                         }
224                         goto error;
225                 }
226         }
227         priv->ind_table = ind_table;
228         priv->hash_rxqs = hash_rxqs;
229         priv->hash_rxqs_n = hash_rxqs_n;
230         assert(err == 0);
231         return 0;
232 error:
233         rte_free(hash_rxqs);
234         if (ind_table != NULL)
235                 claim_zero(ibv_exp_destroy_rwq_ind_table(ind_table));
236         return err;
237 }
238
239 /**
240  * Clean up hash RX queues and indirection table.
241  *
242  * @param priv
243  *   Pointer to private structure.
244  */
245 void
246 priv_destroy_hash_rxqs(struct priv *priv)
247 {
248         unsigned int i;
249
250         DEBUG("destroying %u hash RX queues", priv->hash_rxqs_n);
251         if (priv->hash_rxqs_n == 0) {
252                 assert(priv->hash_rxqs == NULL);
253                 assert(priv->ind_table == NULL);
254                 return;
255         }
256         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
257                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
258                 unsigned int j, k;
259
260                 assert(hash_rxq->priv == priv);
261                 assert(hash_rxq->qp != NULL);
262                 /* Also check that there are no remaining flows. */
263                 assert(hash_rxq->allmulti_flow == NULL);
264                 assert(hash_rxq->promisc_flow == NULL);
265                 for (j = 0; (j != RTE_DIM(hash_rxq->mac_flow)); ++j)
266                         for (k = 0; (k != RTE_DIM(hash_rxq->mac_flow[j])); ++k)
267                                 assert(hash_rxq->mac_flow[j][k] == NULL);
268                 claim_zero(ibv_destroy_qp(hash_rxq->qp));
269         }
270         priv->hash_rxqs_n = 0;
271         rte_free(priv->hash_rxqs);
272         priv->hash_rxqs = NULL;
273         claim_zero(ibv_exp_destroy_rwq_ind_table(priv->ind_table));
274         priv->ind_table = NULL;
275 }
276
277 /**
278  * Allocate RX queue elements with scattered packets support.
279  *
280  * @param rxq
281  *   Pointer to RX queue structure.
282  * @param elts_n
283  *   Number of elements to allocate.
284  * @param[in] pool
285  *   If not NULL, fetch buffers from this array instead of allocating them
286  *   with rte_pktmbuf_alloc().
287  *
288  * @return
289  *   0 on success, errno value on failure.
290  */
291 static int
292 rxq_alloc_elts_sp(struct rxq *rxq, unsigned int elts_n,
293                   struct rte_mbuf **pool)
294 {
295         unsigned int i;
296         struct rxq_elt_sp (*elts)[elts_n] =
297                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
298                                   rxq->socket);
299         int ret = 0;
300
301         if (elts == NULL) {
302                 ERROR("%p: can't allocate packets array", (void *)rxq);
303                 ret = ENOMEM;
304                 goto error;
305         }
306         /* For each WR (packet). */
307         for (i = 0; (i != elts_n); ++i) {
308                 unsigned int j;
309                 struct rxq_elt_sp *elt = &(*elts)[i];
310                 struct ibv_sge (*sges)[RTE_DIM(elt->sges)] = &elt->sges;
311
312                 /* These two arrays must have the same size. */
313                 assert(RTE_DIM(elt->sges) == RTE_DIM(elt->bufs));
314                 /* For each SGE (segment). */
315                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
316                         struct ibv_sge *sge = &(*sges)[j];
317                         struct rte_mbuf *buf;
318
319                         if (pool != NULL) {
320                                 buf = *(pool++);
321                                 assert(buf != NULL);
322                                 rte_pktmbuf_reset(buf);
323                         } else
324                                 buf = rte_pktmbuf_alloc(rxq->mp);
325                         if (buf == NULL) {
326                                 assert(pool == NULL);
327                                 ERROR("%p: empty mbuf pool", (void *)rxq);
328                                 ret = ENOMEM;
329                                 goto error;
330                         }
331                         elt->bufs[j] = buf;
332                         /* Headroom is reserved by rte_pktmbuf_alloc(). */
333                         assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
334                         /* Buffer is supposed to be empty. */
335                         assert(rte_pktmbuf_data_len(buf) == 0);
336                         assert(rte_pktmbuf_pkt_len(buf) == 0);
337                         /* sge->addr must be able to store a pointer. */
338                         assert(sizeof(sge->addr) >= sizeof(uintptr_t));
339                         if (j == 0) {
340                                 /* The first SGE keeps its headroom. */
341                                 sge->addr = rte_pktmbuf_mtod(buf, uintptr_t);
342                                 sge->length = (buf->buf_len -
343                                                RTE_PKTMBUF_HEADROOM);
344                         } else {
345                                 /* Subsequent SGEs lose theirs. */
346                                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
347                                 SET_DATA_OFF(buf, 0);
348                                 sge->addr = (uintptr_t)buf->buf_addr;
349                                 sge->length = buf->buf_len;
350                         }
351                         sge->lkey = rxq->mr->lkey;
352                         /* Redundant check for tailroom. */
353                         assert(sge->length == rte_pktmbuf_tailroom(buf));
354                 }
355         }
356         DEBUG("%p: allocated and configured %u WRs (%zu segments)",
357               (void *)rxq, elts_n, (elts_n * RTE_DIM((*elts)[0].sges)));
358         rxq->elts_n = elts_n;
359         rxq->elts_head = 0;
360         rxq->elts.sp = elts;
361         assert(ret == 0);
362         return 0;
363 error:
364         if (elts != NULL) {
365                 assert(pool == NULL);
366                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
367                         unsigned int j;
368                         struct rxq_elt_sp *elt = &(*elts)[i];
369
370                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
371                                 struct rte_mbuf *buf = elt->bufs[j];
372
373                                 if (buf != NULL)
374                                         rte_pktmbuf_free_seg(buf);
375                         }
376                 }
377                 rte_free(elts);
378         }
379         DEBUG("%p: failed, freed everything", (void *)rxq);
380         assert(ret > 0);
381         return ret;
382 }
383
384 /**
385  * Free RX queue elements with scattered packets support.
386  *
387  * @param rxq
388  *   Pointer to RX queue structure.
389  */
390 static void
391 rxq_free_elts_sp(struct rxq *rxq)
392 {
393         unsigned int i;
394         unsigned int elts_n = rxq->elts_n;
395         struct rxq_elt_sp (*elts)[elts_n] = rxq->elts.sp;
396
397         DEBUG("%p: freeing WRs", (void *)rxq);
398         rxq->elts_n = 0;
399         rxq->elts.sp = NULL;
400         if (elts == NULL)
401                 return;
402         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
403                 unsigned int j;
404                 struct rxq_elt_sp *elt = &(*elts)[i];
405
406                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
407                         struct rte_mbuf *buf = elt->bufs[j];
408
409                         if (buf != NULL)
410                                 rte_pktmbuf_free_seg(buf);
411                 }
412         }
413         rte_free(elts);
414 }
415
416 /**
417  * Allocate RX queue elements.
418  *
419  * @param rxq
420  *   Pointer to RX queue structure.
421  * @param elts_n
422  *   Number of elements to allocate.
423  * @param[in] pool
424  *   If not NULL, fetch buffers from this array instead of allocating them
425  *   with rte_pktmbuf_alloc().
426  *
427  * @return
428  *   0 on success, errno value on failure.
429  */
430 static int
431 rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n, struct rte_mbuf **pool)
432 {
433         unsigned int i;
434         struct rxq_elt (*elts)[elts_n] =
435                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
436                                   rxq->socket);
437         int ret = 0;
438
439         if (elts == NULL) {
440                 ERROR("%p: can't allocate packets array", (void *)rxq);
441                 ret = ENOMEM;
442                 goto error;
443         }
444         /* For each WR (packet). */
445         for (i = 0; (i != elts_n); ++i) {
446                 struct rxq_elt *elt = &(*elts)[i];
447                 struct ibv_sge *sge = &(*elts)[i].sge;
448                 struct rte_mbuf *buf;
449
450                 if (pool != NULL) {
451                         buf = *(pool++);
452                         assert(buf != NULL);
453                         rte_pktmbuf_reset(buf);
454                 } else
455                         buf = rte_pktmbuf_alloc(rxq->mp);
456                 if (buf == NULL) {
457                         assert(pool == NULL);
458                         ERROR("%p: empty mbuf pool", (void *)rxq);
459                         ret = ENOMEM;
460                         goto error;
461                 }
462                 elt->buf = buf;
463                 /* Headroom is reserved by rte_pktmbuf_alloc(). */
464                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
465                 /* Buffer is supposed to be empty. */
466                 assert(rte_pktmbuf_data_len(buf) == 0);
467                 assert(rte_pktmbuf_pkt_len(buf) == 0);
468                 /* sge->addr must be able to store a pointer. */
469                 assert(sizeof(sge->addr) >= sizeof(uintptr_t));
470                 /* SGE keeps its headroom. */
471                 sge->addr = (uintptr_t)
472                         ((uint8_t *)buf->buf_addr + RTE_PKTMBUF_HEADROOM);
473                 sge->length = (buf->buf_len - RTE_PKTMBUF_HEADROOM);
474                 sge->lkey = rxq->mr->lkey;
475                 /* Redundant check for tailroom. */
476                 assert(sge->length == rte_pktmbuf_tailroom(buf));
477         }
478         DEBUG("%p: allocated and configured %u single-segment WRs",
479               (void *)rxq, elts_n);
480         rxq->elts_n = elts_n;
481         rxq->elts_head = 0;
482         rxq->elts.no_sp = elts;
483         assert(ret == 0);
484         return 0;
485 error:
486         if (elts != NULL) {
487                 assert(pool == NULL);
488                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
489                         struct rxq_elt *elt = &(*elts)[i];
490                         struct rte_mbuf *buf = elt->buf;
491
492                         if (buf != NULL)
493                                 rte_pktmbuf_free_seg(buf);
494                 }
495                 rte_free(elts);
496         }
497         DEBUG("%p: failed, freed everything", (void *)rxq);
498         assert(ret > 0);
499         return ret;
500 }
501
502 /**
503  * Free RX queue elements.
504  *
505  * @param rxq
506  *   Pointer to RX queue structure.
507  */
508 static void
509 rxq_free_elts(struct rxq *rxq)
510 {
511         unsigned int i;
512         unsigned int elts_n = rxq->elts_n;
513         struct rxq_elt (*elts)[elts_n] = rxq->elts.no_sp;
514
515         DEBUG("%p: freeing WRs", (void *)rxq);
516         rxq->elts_n = 0;
517         rxq->elts.no_sp = NULL;
518         if (elts == NULL)
519                 return;
520         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
521                 struct rxq_elt *elt = &(*elts)[i];
522                 struct rte_mbuf *buf = elt->buf;
523
524                 if (buf != NULL)
525                         rte_pktmbuf_free_seg(buf);
526         }
527         rte_free(elts);
528 }
529
530 /**
531  * Clean up a RX queue.
532  *
533  * Destroy objects, free allocated memory and reset the structure for reuse.
534  *
535  * @param rxq
536  *   Pointer to RX queue structure.
537  */
538 void
539 rxq_cleanup(struct rxq *rxq)
540 {
541         struct ibv_exp_release_intf_params params;
542
543         DEBUG("cleaning up %p", (void *)rxq);
544         if (rxq->sp)
545                 rxq_free_elts_sp(rxq);
546         else
547                 rxq_free_elts(rxq);
548         if (rxq->if_wq != NULL) {
549                 assert(rxq->priv != NULL);
550                 assert(rxq->priv->ctx != NULL);
551                 assert(rxq->wq != NULL);
552                 params = (struct ibv_exp_release_intf_params){
553                         .comp_mask = 0,
554                 };
555                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
556                                                 rxq->if_wq,
557                                                 &params));
558         }
559         if (rxq->if_cq != NULL) {
560                 assert(rxq->priv != NULL);
561                 assert(rxq->priv->ctx != NULL);
562                 assert(rxq->cq != NULL);
563                 params = (struct ibv_exp_release_intf_params){
564                         .comp_mask = 0,
565                 };
566                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
567                                                 rxq->if_cq,
568                                                 &params));
569         }
570         if (rxq->wq != NULL)
571                 claim_zero(ibv_exp_destroy_wq(rxq->wq));
572         if (rxq->cq != NULL)
573                 claim_zero(ibv_destroy_cq(rxq->cq));
574         if (rxq->rd != NULL) {
575                 struct ibv_exp_destroy_res_domain_attr attr = {
576                         .comp_mask = 0,
577                 };
578
579                 assert(rxq->priv != NULL);
580                 assert(rxq->priv->ctx != NULL);
581                 claim_zero(ibv_exp_destroy_res_domain(rxq->priv->ctx,
582                                                       rxq->rd,
583                                                       &attr));
584         }
585         if (rxq->mr != NULL)
586                 claim_zero(ibv_dereg_mr(rxq->mr));
587         memset(rxq, 0, sizeof(*rxq));
588 }
589
590 /**
591  * Reconfigure a RX queue with new parameters.
592  *
593  * rxq_rehash() does not allocate mbufs, which, if not done from the right
594  * thread (such as a control thread), may corrupt the pool.
595  * In case of failure, the queue is left untouched.
596  *
597  * @param dev
598  *   Pointer to Ethernet device structure.
599  * @param rxq
600  *   RX queue pointer.
601  *
602  * @return
603  *   0 on success, errno value on failure.
604  */
605 int
606 rxq_rehash(struct rte_eth_dev *dev, struct rxq *rxq)
607 {
608         struct priv *priv = rxq->priv;
609         struct rxq tmpl = *rxq;
610         unsigned int mbuf_n;
611         unsigned int desc_n;
612         struct rte_mbuf **pool;
613         unsigned int i, k;
614         struct ibv_exp_wq_attr mod;
615         int err;
616
617         DEBUG("%p: rehashing queue %p", (void *)dev, (void *)rxq);
618         /* Number of descriptors and mbufs currently allocated. */
619         desc_n = (tmpl.elts_n * (tmpl.sp ? MLX5_PMD_SGE_WR_N : 1));
620         mbuf_n = desc_n;
621         /* Toggle RX checksum offload if hardware supports it. */
622         if (priv->hw_csum) {
623                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
624                 rxq->csum = tmpl.csum;
625         }
626         if (priv->hw_csum_l2tun) {
627                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
628                 rxq->csum_l2tun = tmpl.csum_l2tun;
629         }
630         /* Enable scattered packets support for this queue if necessary. */
631         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
632             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
633              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
634                 tmpl.sp = 1;
635                 desc_n /= MLX5_PMD_SGE_WR_N;
636         } else
637                 tmpl.sp = 0;
638         DEBUG("%p: %s scattered packets support (%u WRs)",
639               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc_n);
640         /* If scatter mode is the same as before, nothing to do. */
641         if (tmpl.sp == rxq->sp) {
642                 DEBUG("%p: nothing to do", (void *)dev);
643                 return 0;
644         }
645         /* From now on, any failure will render the queue unusable.
646          * Reinitialize WQ. */
647         mod = (struct ibv_exp_wq_attr){
648                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
649                 .wq_state = IBV_EXP_WQS_RESET,
650         };
651         err = ibv_exp_modify_wq(tmpl.wq, &mod);
652         if (err) {
653                 ERROR("%p: cannot reset WQ: %s", (void *)dev, strerror(err));
654                 assert(err > 0);
655                 return err;
656         }
657         /* Allocate pool. */
658         pool = rte_malloc(__func__, (mbuf_n * sizeof(*pool)), 0);
659         if (pool == NULL) {
660                 ERROR("%p: cannot allocate memory", (void *)dev);
661                 return ENOBUFS;
662         }
663         /* Snatch mbufs from original queue. */
664         k = 0;
665         if (rxq->sp) {
666                 struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp;
667
668                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
669                         struct rxq_elt_sp *elt = &(*elts)[i];
670                         unsigned int j;
671
672                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
673                                 assert(elt->bufs[j] != NULL);
674                                 pool[k++] = elt->bufs[j];
675                         }
676                 }
677         } else {
678                 struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp;
679
680                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
681                         struct rxq_elt *elt = &(*elts)[i];
682                         struct rte_mbuf *buf = elt->buf;
683
684                         pool[k++] = buf;
685                 }
686         }
687         assert(k == mbuf_n);
688         tmpl.elts_n = 0;
689         tmpl.elts.sp = NULL;
690         assert((void *)&tmpl.elts.sp == (void *)&tmpl.elts.no_sp);
691         err = ((tmpl.sp) ?
692                rxq_alloc_elts_sp(&tmpl, desc_n, pool) :
693                rxq_alloc_elts(&tmpl, desc_n, pool));
694         if (err) {
695                 ERROR("%p: cannot reallocate WRs, aborting", (void *)dev);
696                 rte_free(pool);
697                 assert(err > 0);
698                 return err;
699         }
700         assert(tmpl.elts_n == desc_n);
701         assert(tmpl.elts.sp != NULL);
702         rte_free(pool);
703         /* Clean up original data. */
704         rxq->elts_n = 0;
705         rte_free(rxq->elts.sp);
706         rxq->elts.sp = NULL;
707         /* Change queue state to ready. */
708         mod = (struct ibv_exp_wq_attr){
709                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
710                 .wq_state = IBV_EXP_WQS_RDY,
711         };
712         err = ibv_exp_modify_wq(tmpl.wq, &mod);
713         if (err) {
714                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
715                       (void *)dev, strerror(err));
716                 goto error;
717         }
718         /* Post SGEs. */
719         assert(tmpl.if_wq != NULL);
720         if (tmpl.sp) {
721                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
722
723                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
724                         err = tmpl.if_wq->recv_sg_list
725                                 (tmpl.wq,
726                                  (*elts)[i].sges,
727                                  RTE_DIM((*elts)[i].sges));
728                         if (err)
729                                 break;
730                 }
731         } else {
732                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
733
734                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
735                         err = tmpl.if_wq->recv_burst(
736                                 tmpl.wq,
737                                 &(*elts)[i].sge,
738                                 1);
739                         if (err)
740                                 break;
741                 }
742         }
743         if (err) {
744                 ERROR("%p: failed to post SGEs with error %d",
745                       (void *)dev, err);
746                 /* Set err because it does not contain a valid errno value. */
747                 err = EIO;
748                 goto error;
749         }
750 error:
751         *rxq = tmpl;
752         assert(err >= 0);
753         return err;
754 }
755
756 /**
757  * Configure a RX queue.
758  *
759  * @param dev
760  *   Pointer to Ethernet device structure.
761  * @param rxq
762  *   Pointer to RX queue structure.
763  * @param desc
764  *   Number of descriptors to configure in queue.
765  * @param socket
766  *   NUMA socket on which memory must be allocated.
767  * @param[in] conf
768  *   Thresholds parameters.
769  * @param mp
770  *   Memory pool for buffer allocations.
771  *
772  * @return
773  *   0 on success, errno value on failure.
774  */
775 int
776 rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,
777           unsigned int socket, const struct rte_eth_rxconf *conf,
778           struct rte_mempool *mp)
779 {
780         struct priv *priv = dev->data->dev_private;
781         struct rxq tmpl = {
782                 .priv = priv,
783                 .mp = mp,
784                 .socket = socket
785         };
786         struct ibv_exp_wq_attr mod;
787         union {
788                 struct ibv_exp_query_intf_params params;
789                 struct ibv_exp_cq_init_attr cq;
790                 struct ibv_exp_res_domain_init_attr rd;
791                 struct ibv_exp_wq_init_attr wq;
792         } attr;
793         enum ibv_exp_query_intf_status status;
794         struct rte_mbuf *buf;
795         int ret = 0;
796         unsigned int i;
797         unsigned int cq_size = desc;
798
799         (void)conf; /* Thresholds configuration (ignored). */
800         if ((desc == 0) || (desc % MLX5_PMD_SGE_WR_N)) {
801                 ERROR("%p: invalid number of RX descriptors (must be a"
802                       " multiple of %d)", (void *)dev, MLX5_PMD_SGE_WR_N);
803                 return EINVAL;
804         }
805         /* Get mbuf length. */
806         buf = rte_pktmbuf_alloc(mp);
807         if (buf == NULL) {
808                 ERROR("%p: unable to allocate mbuf", (void *)dev);
809                 return ENOMEM;
810         }
811         tmpl.mb_len = buf->buf_len;
812         assert((rte_pktmbuf_headroom(buf) +
813                 rte_pktmbuf_tailroom(buf)) == tmpl.mb_len);
814         assert(rte_pktmbuf_headroom(buf) == RTE_PKTMBUF_HEADROOM);
815         rte_pktmbuf_free(buf);
816         /* Toggle RX checksum offload if hardware supports it. */
817         if (priv->hw_csum)
818                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
819         if (priv->hw_csum_l2tun)
820                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
821         /* Enable scattered packets support for this queue if necessary. */
822         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
823             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
824              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
825                 tmpl.sp = 1;
826                 desc /= MLX5_PMD_SGE_WR_N;
827         }
828         DEBUG("%p: %s scattered packets support (%u WRs)",
829               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc);
830         /* Use the entire RX mempool as the memory region. */
831         tmpl.mr = ibv_reg_mr(priv->pd,
832                              (void *)mp->elt_va_start,
833                              (mp->elt_va_end - mp->elt_va_start),
834                              (IBV_ACCESS_LOCAL_WRITE |
835                               IBV_ACCESS_REMOTE_WRITE));
836         if (tmpl.mr == NULL) {
837                 ret = EINVAL;
838                 ERROR("%p: MR creation failure: %s",
839                       (void *)dev, strerror(ret));
840                 goto error;
841         }
842         attr.rd = (struct ibv_exp_res_domain_init_attr){
843                 .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL |
844                               IBV_EXP_RES_DOMAIN_MSG_MODEL),
845                 .thread_model = IBV_EXP_THREAD_SINGLE,
846                 .msg_model = IBV_EXP_MSG_HIGH_BW,
847         };
848         tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd);
849         if (tmpl.rd == NULL) {
850                 ret = ENOMEM;
851                 ERROR("%p: RD creation failure: %s",
852                       (void *)dev, strerror(ret));
853                 goto error;
854         }
855         attr.cq = (struct ibv_exp_cq_init_attr){
856                 .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN,
857                 .res_domain = tmpl.rd,
858         };
859         tmpl.cq = ibv_exp_create_cq(priv->ctx, cq_size, NULL, NULL, 0,
860                                     &attr.cq);
861         if (tmpl.cq == NULL) {
862                 ret = ENOMEM;
863                 ERROR("%p: CQ creation failure: %s",
864                       (void *)dev, strerror(ret));
865                 goto error;
866         }
867         DEBUG("priv->device_attr.max_qp_wr is %d",
868               priv->device_attr.max_qp_wr);
869         DEBUG("priv->device_attr.max_sge is %d",
870               priv->device_attr.max_sge);
871         attr.wq = (struct ibv_exp_wq_init_attr){
872                 .wq_context = NULL, /* Could be useful in the future. */
873                 .wq_type = IBV_EXP_WQT_RQ,
874                 /* Max number of outstanding WRs. */
875                 .max_recv_wr = ((priv->device_attr.max_qp_wr < (int)cq_size) ?
876                                 priv->device_attr.max_qp_wr :
877                                 (int)cq_size),
878                 /* Max number of scatter/gather elements in a WR. */
879                 .max_recv_sge = ((priv->device_attr.max_sge <
880                                   MLX5_PMD_SGE_WR_N) ?
881                                  priv->device_attr.max_sge :
882                                  MLX5_PMD_SGE_WR_N),
883                 .pd = priv->pd,
884                 .cq = tmpl.cq,
885                 .comp_mask = IBV_EXP_CREATE_WQ_RES_DOMAIN,
886                 .res_domain = tmpl.rd,
887         };
888         tmpl.wq = ibv_exp_create_wq(priv->ctx, &attr.wq);
889         if (tmpl.wq == NULL) {
890                 ret = (errno ? errno : EINVAL);
891                 ERROR("%p: WQ creation failure: %s",
892                       (void *)dev, strerror(ret));
893                 goto error;
894         }
895         if (tmpl.sp)
896                 ret = rxq_alloc_elts_sp(&tmpl, desc, NULL);
897         else
898                 ret = rxq_alloc_elts(&tmpl, desc, NULL);
899         if (ret) {
900                 ERROR("%p: RXQ allocation failed: %s",
901                       (void *)dev, strerror(ret));
902                 goto error;
903         }
904         /* Save port ID. */
905         tmpl.port_id = dev->data->port_id;
906         DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id);
907         attr.params = (struct ibv_exp_query_intf_params){
908                 .intf_scope = IBV_EXP_INTF_GLOBAL,
909                 .intf = IBV_EXP_INTF_CQ,
910                 .obj = tmpl.cq,
911         };
912         tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
913         if (tmpl.if_cq == NULL) {
914                 ERROR("%p: CQ interface family query failed with status %d",
915                       (void *)dev, status);
916                 goto error;
917         }
918         attr.params = (struct ibv_exp_query_intf_params){
919                 .intf_scope = IBV_EXP_INTF_GLOBAL,
920                 .intf = IBV_EXP_INTF_WQ,
921                 .obj = tmpl.wq,
922         };
923         tmpl.if_wq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
924         if (tmpl.if_wq == NULL) {
925                 ERROR("%p: WQ interface family query failed with status %d",
926                       (void *)dev, status);
927                 goto error;
928         }
929         /* Change queue state to ready. */
930         mod = (struct ibv_exp_wq_attr){
931                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
932                 .wq_state = IBV_EXP_WQS_RDY,
933         };
934         ret = ibv_exp_modify_wq(tmpl.wq, &mod);
935         if (ret) {
936                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
937                       (void *)dev, strerror(ret));
938                 goto error;
939         }
940         /* Post SGEs. */
941         if (tmpl.sp) {
942                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
943
944                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
945                         ret = tmpl.if_wq->recv_sg_list
946                                 (tmpl.wq,
947                                  (*elts)[i].sges,
948                                  RTE_DIM((*elts)[i].sges));
949                         if (ret)
950                                 break;
951                 }
952         } else {
953                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
954
955                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
956                         ret = tmpl.if_wq->recv_burst(
957                                 tmpl.wq,
958                                 &(*elts)[i].sge,
959                                 1);
960                         if (ret)
961                                 break;
962                 }
963         }
964         if (ret) {
965                 ERROR("%p: failed to post SGEs with error %d",
966                       (void *)dev, ret);
967                 /* Set ret because it does not contain a valid errno value. */
968                 ret = EIO;
969                 goto error;
970         }
971         /* Clean up rxq in case we're reinitializing it. */
972         DEBUG("%p: cleaning-up old rxq just in case", (void *)rxq);
973         rxq_cleanup(rxq);
974         *rxq = tmpl;
975         DEBUG("%p: rxq updated with %p", (void *)rxq, (void *)&tmpl);
976         assert(ret == 0);
977         return 0;
978 error:
979         rxq_cleanup(&tmpl);
980         assert(ret > 0);
981         return ret;
982 }
983
984 /**
985  * DPDK callback to configure a RX queue.
986  *
987  * @param dev
988  *   Pointer to Ethernet device structure.
989  * @param idx
990  *   RX queue index.
991  * @param desc
992  *   Number of descriptors to configure in queue.
993  * @param socket
994  *   NUMA socket on which memory must be allocated.
995  * @param[in] conf
996  *   Thresholds parameters.
997  * @param mp
998  *   Memory pool for buffer allocations.
999  *
1000  * @return
1001  *   0 on success, negative errno value on failure.
1002  */
1003 int
1004 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
1005                     unsigned int socket, const struct rte_eth_rxconf *conf,
1006                     struct rte_mempool *mp)
1007 {
1008         struct priv *priv = dev->data->dev_private;
1009         struct rxq *rxq = (*priv->rxqs)[idx];
1010         int ret;
1011
1012         priv_lock(priv);
1013         DEBUG("%p: configuring queue %u for %u descriptors",
1014               (void *)dev, idx, desc);
1015         if (idx >= priv->rxqs_n) {
1016                 ERROR("%p: queue index out of range (%u >= %u)",
1017                       (void *)dev, idx, priv->rxqs_n);
1018                 priv_unlock(priv);
1019                 return -EOVERFLOW;
1020         }
1021         if (rxq != NULL) {
1022                 DEBUG("%p: reusing already allocated queue index %u (%p)",
1023                       (void *)dev, idx, (void *)rxq);
1024                 if (priv->started) {
1025                         priv_unlock(priv);
1026                         return -EEXIST;
1027                 }
1028                 (*priv->rxqs)[idx] = NULL;
1029                 rxq_cleanup(rxq);
1030         } else {
1031                 rxq = rte_calloc_socket("RXQ", 1, sizeof(*rxq), 0, socket);
1032                 if (rxq == NULL) {
1033                         ERROR("%p: unable to allocate queue index %u",
1034                               (void *)dev, idx);
1035                         priv_unlock(priv);
1036                         return -ENOMEM;
1037                 }
1038         }
1039         ret = rxq_setup(dev, rxq, desc, socket, conf, mp);
1040         if (ret)
1041                 rte_free(rxq);
1042         else {
1043                 rxq->stats.idx = idx;
1044                 DEBUG("%p: adding RX queue %p to list",
1045                       (void *)dev, (void *)rxq);
1046                 (*priv->rxqs)[idx] = rxq;
1047                 /* Update receive callback. */
1048                 if (rxq->sp)
1049                         dev->rx_pkt_burst = mlx5_rx_burst_sp;
1050                 else
1051                         dev->rx_pkt_burst = mlx5_rx_burst;
1052         }
1053         priv_unlock(priv);
1054         return -ret;
1055 }
1056
1057 /**
1058  * DPDK callback to release a RX queue.
1059  *
1060  * @param dpdk_rxq
1061  *   Generic RX queue pointer.
1062  */
1063 void
1064 mlx5_rx_queue_release(void *dpdk_rxq)
1065 {
1066         struct rxq *rxq = (struct rxq *)dpdk_rxq;
1067         struct priv *priv;
1068         unsigned int i;
1069
1070         if (rxq == NULL)
1071                 return;
1072         priv = rxq->priv;
1073         priv_lock(priv);
1074         for (i = 0; (i != priv->rxqs_n); ++i)
1075                 if ((*priv->rxqs)[i] == rxq) {
1076                         DEBUG("%p: removing RX queue %p from list",
1077                               (void *)priv->dev, (void *)rxq);
1078                         (*priv->rxqs)[i] = NULL;
1079                         break;
1080                 }
1081         rxq_cleanup(rxq);
1082         rte_free(rxq);
1083         priv_unlock(priv);
1084 }