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