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