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