mlx5: define specific flow steering rules for each hash Rx QP
[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 /* Initialization data for hash RX queues. */
68 static const struct hash_rxq_init hash_rxq_init[] = {
69         [HASH_RXQ_TCPV4] = {
70                 .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 |
71                                 IBV_EXP_RX_HASH_DST_IPV4 |
72                                 IBV_EXP_RX_HASH_SRC_PORT_TCP |
73                                 IBV_EXP_RX_HASH_DST_PORT_TCP),
74                 .flow_priority = 0,
75                 .flow_spec.tcp_udp = {
76                         .type = IBV_FLOW_SPEC_TCP,
77                         .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp),
78                 },
79                 .underlayer = &hash_rxq_init[HASH_RXQ_IPV4],
80         },
81         [HASH_RXQ_UDPV4] = {
82                 .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 |
83                                 IBV_EXP_RX_HASH_DST_IPV4 |
84                                 IBV_EXP_RX_HASH_SRC_PORT_UDP |
85                                 IBV_EXP_RX_HASH_DST_PORT_UDP),
86                 .flow_priority = 0,
87                 .flow_spec.tcp_udp = {
88                         .type = IBV_FLOW_SPEC_UDP,
89                         .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp),
90                 },
91                 .underlayer = &hash_rxq_init[HASH_RXQ_IPV4],
92         },
93         [HASH_RXQ_IPV4] = {
94                 .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 |
95                                 IBV_EXP_RX_HASH_DST_IPV4),
96                 .flow_priority = 1,
97                 .flow_spec.ipv4 = {
98                         .type = IBV_FLOW_SPEC_IPV4,
99                         .size = sizeof(hash_rxq_init[0].flow_spec.ipv4),
100                 },
101                 .underlayer = &hash_rxq_init[HASH_RXQ_ETH],
102         },
103         [HASH_RXQ_ETH] = {
104                 .hash_fields = 0,
105                 .flow_priority = 2,
106                 .flow_spec.eth = {
107                         .type = IBV_FLOW_SPEC_ETH,
108                         .size = sizeof(hash_rxq_init[0].flow_spec.eth),
109                 },
110                 .underlayer = NULL,
111         },
112 };
113
114 /* Number of entries in hash_rxq_init[]. */
115 static const unsigned int hash_rxq_init_n = RTE_DIM(hash_rxq_init);
116
117 /* Initialization data for hash RX queue indirection tables. */
118 static const struct ind_table_init ind_table_init[] = {
119         {
120                 .max_size = -1u, /* Superseded by HW limitations. */
121                 .hash_types =
122                         1 << HASH_RXQ_TCPV4 |
123                         1 << HASH_RXQ_UDPV4 |
124                         1 << HASH_RXQ_IPV4 |
125                         0,
126                 .hash_types_n = 3,
127         },
128         {
129                 .max_size = 1,
130                 .hash_types = 1 << HASH_RXQ_ETH,
131                 .hash_types_n = 1,
132         },
133 };
134
135 #define IND_TABLE_INIT_N RTE_DIM(ind_table_init)
136
137 /* Default RSS hash key also used for ConnectX-3. */
138 static uint8_t hash_rxq_default_key[] = {
139         0x2c, 0xc6, 0x81, 0xd1,
140         0x5b, 0xdb, 0xf4, 0xf7,
141         0xfc, 0xa2, 0x83, 0x19,
142         0xdb, 0x1a, 0x3e, 0x94,
143         0x6b, 0x9e, 0x38, 0xd9,
144         0x2c, 0x9c, 0x03, 0xd1,
145         0xad, 0x99, 0x44, 0xa7,
146         0xd9, 0x56, 0x3d, 0x59,
147         0x06, 0x3c, 0x25, 0xf3,
148         0xfc, 0x1f, 0xdc, 0x2a,
149 };
150
151 /**
152  * Populate flow steering rule for a given hash RX queue type using
153  * information from hash_rxq_init[]. Nothing is written to flow_attr when
154  * flow_attr_size is not large enough, but the required size is still returned.
155  *
156  * @param[in] hash_rxq
157  *   Pointer to hash RX queue.
158  * @param[out] flow_attr
159  *   Pointer to flow attribute structure to fill. Note that the allocated
160  *   area must be larger and large enough to hold all flow specifications.
161  * @param flow_attr_size
162  *   Entire size of flow_attr and trailing room for flow specifications.
163  *
164  * @return
165  *   Total size of the flow attribute buffer. No errors are defined.
166  */
167 size_t
168 hash_rxq_flow_attr(const struct hash_rxq *hash_rxq,
169                    struct ibv_flow_attr *flow_attr,
170                    size_t flow_attr_size)
171 {
172         size_t offset = sizeof(*flow_attr);
173         enum hash_rxq_type type = hash_rxq->type;
174         const struct hash_rxq_init *init = &hash_rxq_init[type];
175
176         assert(hash_rxq->priv != NULL);
177         assert((size_t)type < RTE_DIM(hash_rxq_init));
178         do {
179                 offset += init->flow_spec.hdr.size;
180                 init = init->underlayer;
181         } while (init != NULL);
182         if (offset > flow_attr_size)
183                 return offset;
184         flow_attr_size = offset;
185         init = &hash_rxq_init[type];
186         *flow_attr = (struct ibv_flow_attr){
187                 .type = IBV_FLOW_ATTR_NORMAL,
188                 .priority = init->flow_priority,
189                 .num_of_specs = 0,
190                 .port = hash_rxq->priv->port,
191                 .flags = 0,
192         };
193         do {
194                 offset -= init->flow_spec.hdr.size;
195                 memcpy((void *)((uintptr_t)flow_attr + offset),
196                        &init->flow_spec,
197                        init->flow_spec.hdr.size);
198                 ++flow_attr->num_of_specs;
199                 init = init->underlayer;
200         } while (init != NULL);
201         return flow_attr_size;
202 }
203
204 /**
205  * Return nearest power of two above input value.
206  *
207  * @param v
208  *   Input value.
209  *
210  * @return
211  *   Nearest power of two above input value.
212  */
213 static unsigned int
214 log2above(unsigned int v)
215 {
216         unsigned int l;
217         unsigned int r;
218
219         for (l = 0, r = 0; (v >> 1); ++l, v >>= 1)
220                 r |= (v & 1);
221         return (l + r);
222 }
223
224 /**
225  * Return the type corresponding to the n'th bit set.
226  *
227  * @param table
228  *   The indirection table.
229  * @param n
230  *   The n'th bit set.
231  *
232  * @return
233  *   The corresponding hash_rxq_type.
234  */
235 static enum hash_rxq_type
236 hash_rxq_type_from_n(const struct ind_table_init *table, unsigned int n)
237 {
238         assert(n < table->hash_types_n);
239         while (((table->hash_types >> n) & 0x1) == 0)
240                 ++n;
241         return n;
242 }
243
244 /**
245  * Filter out disabled hash RX queue types from ind_table_init[].
246  *
247  * @param priv
248  *   Pointer to private structure.
249  * @param[out] table
250  *   Output table.
251  *
252  * @return
253  *   Number of table entries.
254  */
255 static unsigned int
256 priv_make_ind_table_init(struct priv *priv,
257                          struct ind_table_init (*table)[IND_TABLE_INIT_N])
258 {
259         unsigned int i;
260         unsigned int j;
261         unsigned int table_n = 0;
262         /* Mandatory to receive frames not handled by normal hash RX queues. */
263         unsigned int hash_types_sup = 1 << HASH_RXQ_ETH;
264
265         /* Process other protocols only if more than one queue. */
266         if (priv->rxqs_n > 1)
267                 for (i = 0; (i != hash_rxq_init_n); ++i)
268                         if (hash_rxq_init[i].hash_fields)
269                                 hash_types_sup |= (1 << i);
270
271         /* Filter out entries whose protocols are not in the set. */
272         for (i = 0, j = 0; (i != IND_TABLE_INIT_N); ++i) {
273                 unsigned int nb;
274                 unsigned int h;
275
276                 /* j is increased only if the table has valid protocols. */
277                 assert(j <= i);
278                 (*table)[j] = ind_table_init[i];
279                 (*table)[j].hash_types &= hash_types_sup;
280                 for (h = 0, nb = 0; (h != hash_rxq_init_n); ++h)
281                         if (((*table)[j].hash_types >> h) & 0x1)
282                                 ++nb;
283                 (*table)[i].hash_types_n = nb;
284                 if (nb) {
285                         ++table_n;
286                         ++j;
287                 }
288         }
289         return table_n;
290 }
291
292 /**
293  * Initialize hash RX queues and indirection table.
294  *
295  * @param priv
296  *   Pointer to private structure.
297  *
298  * @return
299  *   0 on success, errno value on failure.
300  */
301 int
302 priv_create_hash_rxqs(struct priv *priv)
303 {
304         /* If the requested number of WQs is not a power of two, use the
305          * maximum indirection table size for better balancing.
306          * The result is always rounded to the next power of two. */
307         unsigned int wqs_n =
308                 (1 << log2above((priv->rxqs_n & (priv->rxqs_n - 1)) ?
309                                 priv->ind_table_max_size :
310                                 priv->rxqs_n));
311         struct ibv_exp_wq *wqs[wqs_n];
312         struct ind_table_init ind_table_init[IND_TABLE_INIT_N];
313         unsigned int ind_tables_n =
314                 priv_make_ind_table_init(priv, &ind_table_init);
315         unsigned int hash_rxqs_n = 0;
316         struct hash_rxq (*hash_rxqs)[] = NULL;
317         struct ibv_exp_rwq_ind_table *(*ind_tables)[] = NULL;
318         unsigned int i;
319         unsigned int j;
320         unsigned int k;
321         int err = 0;
322
323         assert(priv->ind_tables == NULL);
324         assert(priv->ind_tables_n == 0);
325         assert(priv->hash_rxqs == NULL);
326         assert(priv->hash_rxqs_n == 0);
327         assert(priv->pd != NULL);
328         assert(priv->ctx != NULL);
329         if (priv->rxqs_n == 0)
330                 return EINVAL;
331         assert(priv->rxqs != NULL);
332         if (ind_tables_n == 0) {
333                 ERROR("all hash RX queue types have been filtered out,"
334                       " indirection table cannot be created");
335                 return EINVAL;
336         }
337         if ((wqs_n < priv->rxqs_n) || (wqs_n > priv->ind_table_max_size)) {
338                 ERROR("cannot handle this many RX queues (%u)", priv->rxqs_n);
339                 err = ERANGE;
340                 goto error;
341         }
342         if (wqs_n != priv->rxqs_n) {
343                 INFO("%u RX queues are configured, consider rounding this"
344                      " number to the next power of two for better balancing",
345                      priv->rxqs_n);
346                 DEBUG("indirection table extended to assume %u WQs", wqs_n);
347         }
348         /* When the number of RX queues is not a power of two, the remaining
349          * table entries are padded with reused WQs and hashes are not spread
350          * uniformly. */
351         for (i = 0, j = 0; (i != wqs_n); ++i) {
352                 wqs[i] = (*priv->rxqs)[j]->wq;
353                 if (++j == priv->rxqs_n)
354                         j = 0;
355         }
356         /* Get number of hash RX queues to configure. */
357         for (i = 0, hash_rxqs_n = 0; (i != ind_tables_n); ++i)
358                 hash_rxqs_n += ind_table_init[i].hash_types_n;
359         DEBUG("allocating %u hash RX queues for %u WQs, %u indirection tables",
360               hash_rxqs_n, priv->rxqs_n, ind_tables_n);
361         /* Create indirection tables. */
362         ind_tables = rte_calloc(__func__, ind_tables_n,
363                                 sizeof((*ind_tables)[0]), 0);
364         if (ind_tables == NULL) {
365                 err = ENOMEM;
366                 ERROR("cannot allocate indirection tables container: %s",
367                       strerror(err));
368                 goto error;
369         }
370         for (i = 0; (i != ind_tables_n); ++i) {
371                 struct ibv_exp_rwq_ind_table_init_attr ind_init_attr = {
372                         .pd = priv->pd,
373                         .log_ind_tbl_size = 0, /* Set below. */
374                         .ind_tbl = wqs,
375                         .comp_mask = 0,
376                 };
377                 unsigned int ind_tbl_size = ind_table_init[i].max_size;
378                 struct ibv_exp_rwq_ind_table *ind_table;
379
380                 if (wqs_n < ind_tbl_size)
381                         ind_tbl_size = wqs_n;
382                 ind_init_attr.log_ind_tbl_size = log2above(ind_tbl_size);
383                 errno = 0;
384                 ind_table = ibv_exp_create_rwq_ind_table(priv->ctx,
385                                                          &ind_init_attr);
386                 if (ind_table != NULL) {
387                         (*ind_tables)[i] = ind_table;
388                         continue;
389                 }
390                 /* Not clear whether errno is set. */
391                 err = (errno ? errno : EINVAL);
392                 ERROR("RX indirection table creation failed with error %d: %s",
393                       err, strerror(err));
394                 goto error;
395         }
396         /* Allocate array that holds hash RX queues and related data. */
397         hash_rxqs = rte_calloc(__func__, hash_rxqs_n,
398                                sizeof((*hash_rxqs)[0]), 0);
399         if (hash_rxqs == NULL) {
400                 err = ENOMEM;
401                 ERROR("cannot allocate hash RX queues container: %s",
402                       strerror(err));
403                 goto error;
404         }
405         for (i = 0, j = 0, k = 0;
406              ((i != hash_rxqs_n) && (j != ind_tables_n));
407              ++i) {
408                 struct hash_rxq *hash_rxq = &(*hash_rxqs)[i];
409                 enum hash_rxq_type type =
410                         hash_rxq_type_from_n(&ind_table_init[j], k);
411                 struct ibv_exp_rx_hash_conf hash_conf = {
412                         .rx_hash_function = IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
413                         .rx_hash_key_len = sizeof(hash_rxq_default_key),
414                         .rx_hash_key = hash_rxq_default_key,
415                         .rx_hash_fields_mask = hash_rxq_init[type].hash_fields,
416                         .rwq_ind_tbl = (*ind_tables)[j],
417                 };
418                 struct ibv_exp_qp_init_attr qp_init_attr = {
419                         .max_inl_recv = 0, /* Currently not supported. */
420                         .qp_type = IBV_QPT_RAW_PACKET,
421                         .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD |
422                                       IBV_EXP_QP_INIT_ATTR_RX_HASH),
423                         .pd = priv->pd,
424                         .rx_hash_conf = &hash_conf,
425                         .port_num = priv->port,
426                 };
427
428                 DEBUG("using indirection table %u for hash RX queue %u",
429                       j, i);
430                 *hash_rxq = (struct hash_rxq){
431                         .priv = priv,
432                         .qp = ibv_exp_create_qp(priv->ctx, &qp_init_attr),
433                         .type = type,
434                 };
435                 if (hash_rxq->qp == NULL) {
436                         err = (errno ? errno : EINVAL);
437                         ERROR("Hash RX QP creation failure: %s",
438                               strerror(err));
439                         goto error;
440                 }
441                 if (++k < ind_table_init[j].hash_types_n)
442                         continue;
443                 /* Switch to the next indirection table and reset hash RX
444                  * queue type array index. */
445                 ++j;
446                 k = 0;
447         }
448         priv->ind_tables = ind_tables;
449         priv->ind_tables_n = ind_tables_n;
450         priv->hash_rxqs = hash_rxqs;
451         priv->hash_rxqs_n = hash_rxqs_n;
452         assert(err == 0);
453         return 0;
454 error:
455         if (hash_rxqs != NULL) {
456                 for (i = 0; (i != hash_rxqs_n); ++i) {
457                         struct ibv_qp *qp = (*hash_rxqs)[i].qp;
458
459                         if (qp == NULL)
460                                 continue;
461                         claim_zero(ibv_destroy_qp(qp));
462                 }
463                 rte_free(hash_rxqs);
464         }
465         if (ind_tables != NULL) {
466                 for (j = 0; (j != ind_tables_n); ++j) {
467                         struct ibv_exp_rwq_ind_table *ind_table =
468                                 (*ind_tables)[j];
469
470                         if (ind_table == NULL)
471                                 continue;
472                         claim_zero(ibv_exp_destroy_rwq_ind_table(ind_table));
473                 }
474                 rte_free(ind_tables);
475         }
476         return err;
477 }
478
479 /**
480  * Clean up hash RX queues and indirection table.
481  *
482  * @param priv
483  *   Pointer to private structure.
484  */
485 void
486 priv_destroy_hash_rxqs(struct priv *priv)
487 {
488         unsigned int i;
489
490         DEBUG("destroying %u hash RX queues", priv->hash_rxqs_n);
491         if (priv->hash_rxqs_n == 0) {
492                 assert(priv->hash_rxqs == NULL);
493                 assert(priv->ind_tables == NULL);
494                 return;
495         }
496         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
497                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
498                 unsigned int j, k;
499
500                 assert(hash_rxq->priv == priv);
501                 assert(hash_rxq->qp != NULL);
502                 /* Also check that there are no remaining flows. */
503                 assert(hash_rxq->allmulti_flow == NULL);
504                 assert(hash_rxq->promisc_flow == NULL);
505                 for (j = 0; (j != RTE_DIM(hash_rxq->mac_flow)); ++j)
506                         for (k = 0; (k != RTE_DIM(hash_rxq->mac_flow[j])); ++k)
507                                 assert(hash_rxq->mac_flow[j][k] == NULL);
508                 claim_zero(ibv_destroy_qp(hash_rxq->qp));
509         }
510         priv->hash_rxqs_n = 0;
511         rte_free(priv->hash_rxqs);
512         priv->hash_rxqs = NULL;
513         for (i = 0; (i != priv->ind_tables_n); ++i) {
514                 struct ibv_exp_rwq_ind_table *ind_table =
515                         (*priv->ind_tables)[i];
516
517                 assert(ind_table != NULL);
518                 claim_zero(ibv_exp_destroy_rwq_ind_table(ind_table));
519         }
520         priv->ind_tables_n = 0;
521         rte_free(priv->ind_tables);
522         priv->ind_tables = NULL;
523 }
524
525 /**
526  * Allocate RX queue elements with scattered packets support.
527  *
528  * @param rxq
529  *   Pointer to RX queue structure.
530  * @param elts_n
531  *   Number of elements to allocate.
532  * @param[in] pool
533  *   If not NULL, fetch buffers from this array instead of allocating them
534  *   with rte_pktmbuf_alloc().
535  *
536  * @return
537  *   0 on success, errno value on failure.
538  */
539 static int
540 rxq_alloc_elts_sp(struct rxq *rxq, unsigned int elts_n,
541                   struct rte_mbuf **pool)
542 {
543         unsigned int i;
544         struct rxq_elt_sp (*elts)[elts_n] =
545                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
546                                   rxq->socket);
547         int ret = 0;
548
549         if (elts == NULL) {
550                 ERROR("%p: can't allocate packets array", (void *)rxq);
551                 ret = ENOMEM;
552                 goto error;
553         }
554         /* For each WR (packet). */
555         for (i = 0; (i != elts_n); ++i) {
556                 unsigned int j;
557                 struct rxq_elt_sp *elt = &(*elts)[i];
558                 struct ibv_sge (*sges)[RTE_DIM(elt->sges)] = &elt->sges;
559
560                 /* These two arrays must have the same size. */
561                 assert(RTE_DIM(elt->sges) == RTE_DIM(elt->bufs));
562                 /* For each SGE (segment). */
563                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
564                         struct ibv_sge *sge = &(*sges)[j];
565                         struct rte_mbuf *buf;
566
567                         if (pool != NULL) {
568                                 buf = *(pool++);
569                                 assert(buf != NULL);
570                                 rte_pktmbuf_reset(buf);
571                         } else
572                                 buf = rte_pktmbuf_alloc(rxq->mp);
573                         if (buf == NULL) {
574                                 assert(pool == NULL);
575                                 ERROR("%p: empty mbuf pool", (void *)rxq);
576                                 ret = ENOMEM;
577                                 goto error;
578                         }
579                         elt->bufs[j] = buf;
580                         /* Headroom is reserved by rte_pktmbuf_alloc(). */
581                         assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
582                         /* Buffer is supposed to be empty. */
583                         assert(rte_pktmbuf_data_len(buf) == 0);
584                         assert(rte_pktmbuf_pkt_len(buf) == 0);
585                         /* sge->addr must be able to store a pointer. */
586                         assert(sizeof(sge->addr) >= sizeof(uintptr_t));
587                         if (j == 0) {
588                                 /* The first SGE keeps its headroom. */
589                                 sge->addr = rte_pktmbuf_mtod(buf, uintptr_t);
590                                 sge->length = (buf->buf_len -
591                                                RTE_PKTMBUF_HEADROOM);
592                         } else {
593                                 /* Subsequent SGEs lose theirs. */
594                                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
595                                 SET_DATA_OFF(buf, 0);
596                                 sge->addr = (uintptr_t)buf->buf_addr;
597                                 sge->length = buf->buf_len;
598                         }
599                         sge->lkey = rxq->mr->lkey;
600                         /* Redundant check for tailroom. */
601                         assert(sge->length == rte_pktmbuf_tailroom(buf));
602                 }
603         }
604         DEBUG("%p: allocated and configured %u WRs (%zu segments)",
605               (void *)rxq, elts_n, (elts_n * RTE_DIM((*elts)[0].sges)));
606         rxq->elts_n = elts_n;
607         rxq->elts_head = 0;
608         rxq->elts.sp = elts;
609         assert(ret == 0);
610         return 0;
611 error:
612         if (elts != NULL) {
613                 assert(pool == NULL);
614                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
615                         unsigned int j;
616                         struct rxq_elt_sp *elt = &(*elts)[i];
617
618                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
619                                 struct rte_mbuf *buf = elt->bufs[j];
620
621                                 if (buf != NULL)
622                                         rte_pktmbuf_free_seg(buf);
623                         }
624                 }
625                 rte_free(elts);
626         }
627         DEBUG("%p: failed, freed everything", (void *)rxq);
628         assert(ret > 0);
629         return ret;
630 }
631
632 /**
633  * Free RX queue elements with scattered packets support.
634  *
635  * @param rxq
636  *   Pointer to RX queue structure.
637  */
638 static void
639 rxq_free_elts_sp(struct rxq *rxq)
640 {
641         unsigned int i;
642         unsigned int elts_n = rxq->elts_n;
643         struct rxq_elt_sp (*elts)[elts_n] = rxq->elts.sp;
644
645         DEBUG("%p: freeing WRs", (void *)rxq);
646         rxq->elts_n = 0;
647         rxq->elts.sp = NULL;
648         if (elts == NULL)
649                 return;
650         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
651                 unsigned int j;
652                 struct rxq_elt_sp *elt = &(*elts)[i];
653
654                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
655                         struct rte_mbuf *buf = elt->bufs[j];
656
657                         if (buf != NULL)
658                                 rte_pktmbuf_free_seg(buf);
659                 }
660         }
661         rte_free(elts);
662 }
663
664 /**
665  * Allocate RX queue elements.
666  *
667  * @param rxq
668  *   Pointer to RX queue structure.
669  * @param elts_n
670  *   Number of elements to allocate.
671  * @param[in] pool
672  *   If not NULL, fetch buffers from this array instead of allocating them
673  *   with rte_pktmbuf_alloc().
674  *
675  * @return
676  *   0 on success, errno value on failure.
677  */
678 static int
679 rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n, struct rte_mbuf **pool)
680 {
681         unsigned int i;
682         struct rxq_elt (*elts)[elts_n] =
683                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
684                                   rxq->socket);
685         int ret = 0;
686
687         if (elts == NULL) {
688                 ERROR("%p: can't allocate packets array", (void *)rxq);
689                 ret = ENOMEM;
690                 goto error;
691         }
692         /* For each WR (packet). */
693         for (i = 0; (i != elts_n); ++i) {
694                 struct rxq_elt *elt = &(*elts)[i];
695                 struct ibv_sge *sge = &(*elts)[i].sge;
696                 struct rte_mbuf *buf;
697
698                 if (pool != NULL) {
699                         buf = *(pool++);
700                         assert(buf != NULL);
701                         rte_pktmbuf_reset(buf);
702                 } else
703                         buf = rte_pktmbuf_alloc(rxq->mp);
704                 if (buf == NULL) {
705                         assert(pool == NULL);
706                         ERROR("%p: empty mbuf pool", (void *)rxq);
707                         ret = ENOMEM;
708                         goto error;
709                 }
710                 elt->buf = buf;
711                 /* Headroom is reserved by rte_pktmbuf_alloc(). */
712                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
713                 /* Buffer is supposed to be empty. */
714                 assert(rte_pktmbuf_data_len(buf) == 0);
715                 assert(rte_pktmbuf_pkt_len(buf) == 0);
716                 /* sge->addr must be able to store a pointer. */
717                 assert(sizeof(sge->addr) >= sizeof(uintptr_t));
718                 /* SGE keeps its headroom. */
719                 sge->addr = (uintptr_t)
720                         ((uint8_t *)buf->buf_addr + RTE_PKTMBUF_HEADROOM);
721                 sge->length = (buf->buf_len - RTE_PKTMBUF_HEADROOM);
722                 sge->lkey = rxq->mr->lkey;
723                 /* Redundant check for tailroom. */
724                 assert(sge->length == rte_pktmbuf_tailroom(buf));
725         }
726         DEBUG("%p: allocated and configured %u single-segment WRs",
727               (void *)rxq, elts_n);
728         rxq->elts_n = elts_n;
729         rxq->elts_head = 0;
730         rxq->elts.no_sp = elts;
731         assert(ret == 0);
732         return 0;
733 error:
734         if (elts != NULL) {
735                 assert(pool == NULL);
736                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
737                         struct rxq_elt *elt = &(*elts)[i];
738                         struct rte_mbuf *buf = elt->buf;
739
740                         if (buf != NULL)
741                                 rte_pktmbuf_free_seg(buf);
742                 }
743                 rte_free(elts);
744         }
745         DEBUG("%p: failed, freed everything", (void *)rxq);
746         assert(ret > 0);
747         return ret;
748 }
749
750 /**
751  * Free RX queue elements.
752  *
753  * @param rxq
754  *   Pointer to RX queue structure.
755  */
756 static void
757 rxq_free_elts(struct rxq *rxq)
758 {
759         unsigned int i;
760         unsigned int elts_n = rxq->elts_n;
761         struct rxq_elt (*elts)[elts_n] = rxq->elts.no_sp;
762
763         DEBUG("%p: freeing WRs", (void *)rxq);
764         rxq->elts_n = 0;
765         rxq->elts.no_sp = NULL;
766         if (elts == NULL)
767                 return;
768         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
769                 struct rxq_elt *elt = &(*elts)[i];
770                 struct rte_mbuf *buf = elt->buf;
771
772                 if (buf != NULL)
773                         rte_pktmbuf_free_seg(buf);
774         }
775         rte_free(elts);
776 }
777
778 /**
779  * Clean up a RX queue.
780  *
781  * Destroy objects, free allocated memory and reset the structure for reuse.
782  *
783  * @param rxq
784  *   Pointer to RX queue structure.
785  */
786 void
787 rxq_cleanup(struct rxq *rxq)
788 {
789         struct ibv_exp_release_intf_params params;
790
791         DEBUG("cleaning up %p", (void *)rxq);
792         if (rxq->sp)
793                 rxq_free_elts_sp(rxq);
794         else
795                 rxq_free_elts(rxq);
796         if (rxq->if_wq != NULL) {
797                 assert(rxq->priv != NULL);
798                 assert(rxq->priv->ctx != NULL);
799                 assert(rxq->wq != NULL);
800                 params = (struct ibv_exp_release_intf_params){
801                         .comp_mask = 0,
802                 };
803                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
804                                                 rxq->if_wq,
805                                                 &params));
806         }
807         if (rxq->if_cq != NULL) {
808                 assert(rxq->priv != NULL);
809                 assert(rxq->priv->ctx != NULL);
810                 assert(rxq->cq != NULL);
811                 params = (struct ibv_exp_release_intf_params){
812                         .comp_mask = 0,
813                 };
814                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
815                                                 rxq->if_cq,
816                                                 &params));
817         }
818         if (rxq->wq != NULL)
819                 claim_zero(ibv_exp_destroy_wq(rxq->wq));
820         if (rxq->cq != NULL)
821                 claim_zero(ibv_destroy_cq(rxq->cq));
822         if (rxq->rd != NULL) {
823                 struct ibv_exp_destroy_res_domain_attr attr = {
824                         .comp_mask = 0,
825                 };
826
827                 assert(rxq->priv != NULL);
828                 assert(rxq->priv->ctx != NULL);
829                 claim_zero(ibv_exp_destroy_res_domain(rxq->priv->ctx,
830                                                       rxq->rd,
831                                                       &attr));
832         }
833         if (rxq->mr != NULL)
834                 claim_zero(ibv_dereg_mr(rxq->mr));
835         memset(rxq, 0, sizeof(*rxq));
836 }
837
838 /**
839  * Reconfigure a RX queue with new parameters.
840  *
841  * rxq_rehash() does not allocate mbufs, which, if not done from the right
842  * thread (such as a control thread), may corrupt the pool.
843  * In case of failure, the queue is left untouched.
844  *
845  * @param dev
846  *   Pointer to Ethernet device structure.
847  * @param rxq
848  *   RX queue pointer.
849  *
850  * @return
851  *   0 on success, errno value on failure.
852  */
853 int
854 rxq_rehash(struct rte_eth_dev *dev, struct rxq *rxq)
855 {
856         struct priv *priv = rxq->priv;
857         struct rxq tmpl = *rxq;
858         unsigned int mbuf_n;
859         unsigned int desc_n;
860         struct rte_mbuf **pool;
861         unsigned int i, k;
862         struct ibv_exp_wq_attr mod;
863         int err;
864
865         DEBUG("%p: rehashing queue %p", (void *)dev, (void *)rxq);
866         /* Number of descriptors and mbufs currently allocated. */
867         desc_n = (tmpl.elts_n * (tmpl.sp ? MLX5_PMD_SGE_WR_N : 1));
868         mbuf_n = desc_n;
869         /* Toggle RX checksum offload if hardware supports it. */
870         if (priv->hw_csum) {
871                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
872                 rxq->csum = tmpl.csum;
873         }
874         if (priv->hw_csum_l2tun) {
875                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
876                 rxq->csum_l2tun = tmpl.csum_l2tun;
877         }
878         /* Enable scattered packets support for this queue if necessary. */
879         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
880             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
881              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
882                 tmpl.sp = 1;
883                 desc_n /= MLX5_PMD_SGE_WR_N;
884         } else
885                 tmpl.sp = 0;
886         DEBUG("%p: %s scattered packets support (%u WRs)",
887               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc_n);
888         /* If scatter mode is the same as before, nothing to do. */
889         if (tmpl.sp == rxq->sp) {
890                 DEBUG("%p: nothing to do", (void *)dev);
891                 return 0;
892         }
893         /* From now on, any failure will render the queue unusable.
894          * Reinitialize WQ. */
895         mod = (struct ibv_exp_wq_attr){
896                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
897                 .wq_state = IBV_EXP_WQS_RESET,
898         };
899         err = ibv_exp_modify_wq(tmpl.wq, &mod);
900         if (err) {
901                 ERROR("%p: cannot reset WQ: %s", (void *)dev, strerror(err));
902                 assert(err > 0);
903                 return err;
904         }
905         /* Allocate pool. */
906         pool = rte_malloc(__func__, (mbuf_n * sizeof(*pool)), 0);
907         if (pool == NULL) {
908                 ERROR("%p: cannot allocate memory", (void *)dev);
909                 return ENOBUFS;
910         }
911         /* Snatch mbufs from original queue. */
912         k = 0;
913         if (rxq->sp) {
914                 struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp;
915
916                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
917                         struct rxq_elt_sp *elt = &(*elts)[i];
918                         unsigned int j;
919
920                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
921                                 assert(elt->bufs[j] != NULL);
922                                 pool[k++] = elt->bufs[j];
923                         }
924                 }
925         } else {
926                 struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp;
927
928                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
929                         struct rxq_elt *elt = &(*elts)[i];
930                         struct rte_mbuf *buf = elt->buf;
931
932                         pool[k++] = buf;
933                 }
934         }
935         assert(k == mbuf_n);
936         tmpl.elts_n = 0;
937         tmpl.elts.sp = NULL;
938         assert((void *)&tmpl.elts.sp == (void *)&tmpl.elts.no_sp);
939         err = ((tmpl.sp) ?
940                rxq_alloc_elts_sp(&tmpl, desc_n, pool) :
941                rxq_alloc_elts(&tmpl, desc_n, pool));
942         if (err) {
943                 ERROR("%p: cannot reallocate WRs, aborting", (void *)dev);
944                 rte_free(pool);
945                 assert(err > 0);
946                 return err;
947         }
948         assert(tmpl.elts_n == desc_n);
949         assert(tmpl.elts.sp != NULL);
950         rte_free(pool);
951         /* Clean up original data. */
952         rxq->elts_n = 0;
953         rte_free(rxq->elts.sp);
954         rxq->elts.sp = NULL;
955         /* Change queue state to ready. */
956         mod = (struct ibv_exp_wq_attr){
957                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
958                 .wq_state = IBV_EXP_WQS_RDY,
959         };
960         err = ibv_exp_modify_wq(tmpl.wq, &mod);
961         if (err) {
962                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
963                       (void *)dev, strerror(err));
964                 goto error;
965         }
966         /* Post SGEs. */
967         assert(tmpl.if_wq != NULL);
968         if (tmpl.sp) {
969                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
970
971                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
972                         err = tmpl.if_wq->recv_sg_list
973                                 (tmpl.wq,
974                                  (*elts)[i].sges,
975                                  RTE_DIM((*elts)[i].sges));
976                         if (err)
977                                 break;
978                 }
979         } else {
980                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
981
982                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
983                         err = tmpl.if_wq->recv_burst(
984                                 tmpl.wq,
985                                 &(*elts)[i].sge,
986                                 1);
987                         if (err)
988                                 break;
989                 }
990         }
991         if (err) {
992                 ERROR("%p: failed to post SGEs with error %d",
993                       (void *)dev, err);
994                 /* Set err because it does not contain a valid errno value. */
995                 err = EIO;
996                 goto error;
997         }
998 error:
999         *rxq = tmpl;
1000         assert(err >= 0);
1001         return err;
1002 }
1003
1004 /**
1005  * Configure a RX queue.
1006  *
1007  * @param dev
1008  *   Pointer to Ethernet device structure.
1009  * @param rxq
1010  *   Pointer to RX queue structure.
1011  * @param desc
1012  *   Number of descriptors to configure in queue.
1013  * @param socket
1014  *   NUMA socket on which memory must be allocated.
1015  * @param[in] conf
1016  *   Thresholds parameters.
1017  * @param mp
1018  *   Memory pool for buffer allocations.
1019  *
1020  * @return
1021  *   0 on success, errno value on failure.
1022  */
1023 int
1024 rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,
1025           unsigned int socket, const struct rte_eth_rxconf *conf,
1026           struct rte_mempool *mp)
1027 {
1028         struct priv *priv = dev->data->dev_private;
1029         struct rxq tmpl = {
1030                 .priv = priv,
1031                 .mp = mp,
1032                 .socket = socket
1033         };
1034         struct ibv_exp_wq_attr mod;
1035         union {
1036                 struct ibv_exp_query_intf_params params;
1037                 struct ibv_exp_cq_init_attr cq;
1038                 struct ibv_exp_res_domain_init_attr rd;
1039                 struct ibv_exp_wq_init_attr wq;
1040         } attr;
1041         enum ibv_exp_query_intf_status status;
1042         struct rte_mbuf *buf;
1043         int ret = 0;
1044         unsigned int i;
1045         unsigned int cq_size = desc;
1046
1047         (void)conf; /* Thresholds configuration (ignored). */
1048         if ((desc == 0) || (desc % MLX5_PMD_SGE_WR_N)) {
1049                 ERROR("%p: invalid number of RX descriptors (must be a"
1050                       " multiple of %d)", (void *)dev, MLX5_PMD_SGE_WR_N);
1051                 return EINVAL;
1052         }
1053         /* Get mbuf length. */
1054         buf = rte_pktmbuf_alloc(mp);
1055         if (buf == NULL) {
1056                 ERROR("%p: unable to allocate mbuf", (void *)dev);
1057                 return ENOMEM;
1058         }
1059         tmpl.mb_len = buf->buf_len;
1060         assert((rte_pktmbuf_headroom(buf) +
1061                 rte_pktmbuf_tailroom(buf)) == tmpl.mb_len);
1062         assert(rte_pktmbuf_headroom(buf) == RTE_PKTMBUF_HEADROOM);
1063         rte_pktmbuf_free(buf);
1064         /* Toggle RX checksum offload if hardware supports it. */
1065         if (priv->hw_csum)
1066                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1067         if (priv->hw_csum_l2tun)
1068                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1069         /* Enable scattered packets support for this queue if necessary. */
1070         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
1071             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
1072              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
1073                 tmpl.sp = 1;
1074                 desc /= MLX5_PMD_SGE_WR_N;
1075         }
1076         DEBUG("%p: %s scattered packets support (%u WRs)",
1077               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc);
1078         /* Use the entire RX mempool as the memory region. */
1079         tmpl.mr = ibv_reg_mr(priv->pd,
1080                              (void *)mp->elt_va_start,
1081                              (mp->elt_va_end - mp->elt_va_start),
1082                              (IBV_ACCESS_LOCAL_WRITE |
1083                               IBV_ACCESS_REMOTE_WRITE));
1084         if (tmpl.mr == NULL) {
1085                 ret = EINVAL;
1086                 ERROR("%p: MR creation failure: %s",
1087                       (void *)dev, strerror(ret));
1088                 goto error;
1089         }
1090         attr.rd = (struct ibv_exp_res_domain_init_attr){
1091                 .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL |
1092                               IBV_EXP_RES_DOMAIN_MSG_MODEL),
1093                 .thread_model = IBV_EXP_THREAD_SINGLE,
1094                 .msg_model = IBV_EXP_MSG_HIGH_BW,
1095         };
1096         tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd);
1097         if (tmpl.rd == NULL) {
1098                 ret = ENOMEM;
1099                 ERROR("%p: RD creation failure: %s",
1100                       (void *)dev, strerror(ret));
1101                 goto error;
1102         }
1103         attr.cq = (struct ibv_exp_cq_init_attr){
1104                 .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN,
1105                 .res_domain = tmpl.rd,
1106         };
1107         tmpl.cq = ibv_exp_create_cq(priv->ctx, cq_size, NULL, NULL, 0,
1108                                     &attr.cq);
1109         if (tmpl.cq == NULL) {
1110                 ret = ENOMEM;
1111                 ERROR("%p: CQ creation failure: %s",
1112                       (void *)dev, strerror(ret));
1113                 goto error;
1114         }
1115         DEBUG("priv->device_attr.max_qp_wr is %d",
1116               priv->device_attr.max_qp_wr);
1117         DEBUG("priv->device_attr.max_sge is %d",
1118               priv->device_attr.max_sge);
1119         attr.wq = (struct ibv_exp_wq_init_attr){
1120                 .wq_context = NULL, /* Could be useful in the future. */
1121                 .wq_type = IBV_EXP_WQT_RQ,
1122                 /* Max number of outstanding WRs. */
1123                 .max_recv_wr = ((priv->device_attr.max_qp_wr < (int)cq_size) ?
1124                                 priv->device_attr.max_qp_wr :
1125                                 (int)cq_size),
1126                 /* Max number of scatter/gather elements in a WR. */
1127                 .max_recv_sge = ((priv->device_attr.max_sge <
1128                                   MLX5_PMD_SGE_WR_N) ?
1129                                  priv->device_attr.max_sge :
1130                                  MLX5_PMD_SGE_WR_N),
1131                 .pd = priv->pd,
1132                 .cq = tmpl.cq,
1133                 .comp_mask = IBV_EXP_CREATE_WQ_RES_DOMAIN,
1134                 .res_domain = tmpl.rd,
1135         };
1136         tmpl.wq = ibv_exp_create_wq(priv->ctx, &attr.wq);
1137         if (tmpl.wq == NULL) {
1138                 ret = (errno ? errno : EINVAL);
1139                 ERROR("%p: WQ creation failure: %s",
1140                       (void *)dev, strerror(ret));
1141                 goto error;
1142         }
1143         if (tmpl.sp)
1144                 ret = rxq_alloc_elts_sp(&tmpl, desc, NULL);
1145         else
1146                 ret = rxq_alloc_elts(&tmpl, desc, NULL);
1147         if (ret) {
1148                 ERROR("%p: RXQ allocation failed: %s",
1149                       (void *)dev, strerror(ret));
1150                 goto error;
1151         }
1152         /* Save port ID. */
1153         tmpl.port_id = dev->data->port_id;
1154         DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id);
1155         attr.params = (struct ibv_exp_query_intf_params){
1156                 .intf_scope = IBV_EXP_INTF_GLOBAL,
1157                 .intf = IBV_EXP_INTF_CQ,
1158                 .obj = tmpl.cq,
1159         };
1160         tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
1161         if (tmpl.if_cq == NULL) {
1162                 ERROR("%p: CQ interface family query failed with status %d",
1163                       (void *)dev, status);
1164                 goto error;
1165         }
1166         attr.params = (struct ibv_exp_query_intf_params){
1167                 .intf_scope = IBV_EXP_INTF_GLOBAL,
1168                 .intf = IBV_EXP_INTF_WQ,
1169                 .obj = tmpl.wq,
1170         };
1171         tmpl.if_wq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
1172         if (tmpl.if_wq == NULL) {
1173                 ERROR("%p: WQ interface family query failed with status %d",
1174                       (void *)dev, status);
1175                 goto error;
1176         }
1177         /* Change queue state to ready. */
1178         mod = (struct ibv_exp_wq_attr){
1179                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
1180                 .wq_state = IBV_EXP_WQS_RDY,
1181         };
1182         ret = ibv_exp_modify_wq(tmpl.wq, &mod);
1183         if (ret) {
1184                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
1185                       (void *)dev, strerror(ret));
1186                 goto error;
1187         }
1188         /* Post SGEs. */
1189         if (tmpl.sp) {
1190                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
1191
1192                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1193                         ret = tmpl.if_wq->recv_sg_list
1194                                 (tmpl.wq,
1195                                  (*elts)[i].sges,
1196                                  RTE_DIM((*elts)[i].sges));
1197                         if (ret)
1198                                 break;
1199                 }
1200         } else {
1201                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
1202
1203                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1204                         ret = tmpl.if_wq->recv_burst(
1205                                 tmpl.wq,
1206                                 &(*elts)[i].sge,
1207                                 1);
1208                         if (ret)
1209                                 break;
1210                 }
1211         }
1212         if (ret) {
1213                 ERROR("%p: failed to post SGEs with error %d",
1214                       (void *)dev, ret);
1215                 /* Set ret because it does not contain a valid errno value. */
1216                 ret = EIO;
1217                 goto error;
1218         }
1219         /* Clean up rxq in case we're reinitializing it. */
1220         DEBUG("%p: cleaning-up old rxq just in case", (void *)rxq);
1221         rxq_cleanup(rxq);
1222         *rxq = tmpl;
1223         DEBUG("%p: rxq updated with %p", (void *)rxq, (void *)&tmpl);
1224         assert(ret == 0);
1225         return 0;
1226 error:
1227         rxq_cleanup(&tmpl);
1228         assert(ret > 0);
1229         return ret;
1230 }
1231
1232 /**
1233  * DPDK callback to configure a RX queue.
1234  *
1235  * @param dev
1236  *   Pointer to Ethernet device structure.
1237  * @param idx
1238  *   RX queue index.
1239  * @param desc
1240  *   Number of descriptors to configure in queue.
1241  * @param socket
1242  *   NUMA socket on which memory must be allocated.
1243  * @param[in] conf
1244  *   Thresholds parameters.
1245  * @param mp
1246  *   Memory pool for buffer allocations.
1247  *
1248  * @return
1249  *   0 on success, negative errno value on failure.
1250  */
1251 int
1252 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
1253                     unsigned int socket, const struct rte_eth_rxconf *conf,
1254                     struct rte_mempool *mp)
1255 {
1256         struct priv *priv = dev->data->dev_private;
1257         struct rxq *rxq = (*priv->rxqs)[idx];
1258         int ret;
1259
1260         priv_lock(priv);
1261         DEBUG("%p: configuring queue %u for %u descriptors",
1262               (void *)dev, idx, desc);
1263         if (idx >= priv->rxqs_n) {
1264                 ERROR("%p: queue index out of range (%u >= %u)",
1265                       (void *)dev, idx, priv->rxqs_n);
1266                 priv_unlock(priv);
1267                 return -EOVERFLOW;
1268         }
1269         if (rxq != NULL) {
1270                 DEBUG("%p: reusing already allocated queue index %u (%p)",
1271                       (void *)dev, idx, (void *)rxq);
1272                 if (priv->started) {
1273                         priv_unlock(priv);
1274                         return -EEXIST;
1275                 }
1276                 (*priv->rxqs)[idx] = NULL;
1277                 rxq_cleanup(rxq);
1278         } else {
1279                 rxq = rte_calloc_socket("RXQ", 1, sizeof(*rxq), 0, socket);
1280                 if (rxq == NULL) {
1281                         ERROR("%p: unable to allocate queue index %u",
1282                               (void *)dev, idx);
1283                         priv_unlock(priv);
1284                         return -ENOMEM;
1285                 }
1286         }
1287         ret = rxq_setup(dev, rxq, desc, socket, conf, mp);
1288         if (ret)
1289                 rte_free(rxq);
1290         else {
1291                 rxq->stats.idx = idx;
1292                 DEBUG("%p: adding RX queue %p to list",
1293                       (void *)dev, (void *)rxq);
1294                 (*priv->rxqs)[idx] = rxq;
1295                 /* Update receive callback. */
1296                 if (rxq->sp)
1297                         dev->rx_pkt_burst = mlx5_rx_burst_sp;
1298                 else
1299                         dev->rx_pkt_burst = mlx5_rx_burst;
1300         }
1301         priv_unlock(priv);
1302         return -ret;
1303 }
1304
1305 /**
1306  * DPDK callback to release a RX queue.
1307  *
1308  * @param dpdk_rxq
1309  *   Generic RX queue pointer.
1310  */
1311 void
1312 mlx5_rx_queue_release(void *dpdk_rxq)
1313 {
1314         struct rxq *rxq = (struct rxq *)dpdk_rxq;
1315         struct priv *priv;
1316         unsigned int i;
1317
1318         if (rxq == NULL)
1319                 return;
1320         priv = rxq->priv;
1321         priv_lock(priv);
1322         for (i = 0; (i != priv->rxqs_n); ++i)
1323                 if ((*priv->rxqs)[i] == rxq) {
1324                         DEBUG("%p: removing RX queue %p from list",
1325                               (void *)priv->dev, (void *)rxq);
1326                         (*priv->rxqs)[i] = NULL;
1327                         break;
1328                 }
1329         rxq_cleanup(rxq);
1330         rte_free(rxq);
1331         priv_unlock(priv);
1332 }