mlx5: remove one indirection level from Rx/Tx
[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         rxq->poll = NULL;
905         rxq->recv = NULL;
906         if (rxq->if_wq != NULL) {
907                 assert(rxq->priv != NULL);
908                 assert(rxq->priv->ctx != NULL);
909                 assert(rxq->wq != NULL);
910                 params = (struct ibv_exp_release_intf_params){
911                         .comp_mask = 0,
912                 };
913                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
914                                                 rxq->if_wq,
915                                                 &params));
916         }
917         if (rxq->if_cq != NULL) {
918                 assert(rxq->priv != NULL);
919                 assert(rxq->priv->ctx != NULL);
920                 assert(rxq->cq != NULL);
921                 params = (struct ibv_exp_release_intf_params){
922                         .comp_mask = 0,
923                 };
924                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
925                                                 rxq->if_cq,
926                                                 &params));
927         }
928         if (rxq->wq != NULL)
929                 claim_zero(ibv_exp_destroy_wq(rxq->wq));
930         if (rxq->cq != NULL)
931                 claim_zero(ibv_destroy_cq(rxq->cq));
932         if (rxq->rd != NULL) {
933                 struct ibv_exp_destroy_res_domain_attr attr = {
934                         .comp_mask = 0,
935                 };
936
937                 assert(rxq->priv != NULL);
938                 assert(rxq->priv->ctx != NULL);
939                 claim_zero(ibv_exp_destroy_res_domain(rxq->priv->ctx,
940                                                       rxq->rd,
941                                                       &attr));
942         }
943         if (rxq->mr != NULL)
944                 claim_zero(ibv_dereg_mr(rxq->mr));
945         memset(rxq, 0, sizeof(*rxq));
946 }
947
948 /**
949  * Reconfigure a RX queue with new parameters.
950  *
951  * rxq_rehash() does not allocate mbufs, which, if not done from the right
952  * thread (such as a control thread), may corrupt the pool.
953  * In case of failure, the queue is left untouched.
954  *
955  * @param dev
956  *   Pointer to Ethernet device structure.
957  * @param rxq
958  *   RX queue pointer.
959  *
960  * @return
961  *   0 on success, errno value on failure.
962  */
963 int
964 rxq_rehash(struct rte_eth_dev *dev, struct rxq *rxq)
965 {
966         struct priv *priv = rxq->priv;
967         struct rxq tmpl = *rxq;
968         unsigned int mbuf_n;
969         unsigned int desc_n;
970         struct rte_mbuf **pool;
971         unsigned int i, k;
972         struct ibv_exp_wq_attr mod;
973         int err;
974
975         DEBUG("%p: rehashing queue %p", (void *)dev, (void *)rxq);
976         /* Number of descriptors and mbufs currently allocated. */
977         desc_n = (tmpl.elts_n * (tmpl.sp ? MLX5_PMD_SGE_WR_N : 1));
978         mbuf_n = desc_n;
979         /* Toggle RX checksum offload if hardware supports it. */
980         if (priv->hw_csum) {
981                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
982                 rxq->csum = tmpl.csum;
983         }
984         if (priv->hw_csum_l2tun) {
985                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
986                 rxq->csum_l2tun = tmpl.csum_l2tun;
987         }
988         /* Enable scattered packets support for this queue if necessary. */
989         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
990             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
991              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
992                 tmpl.sp = 1;
993                 desc_n /= MLX5_PMD_SGE_WR_N;
994         } else
995                 tmpl.sp = 0;
996         DEBUG("%p: %s scattered packets support (%u WRs)",
997               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc_n);
998         /* If scatter mode is the same as before, nothing to do. */
999         if (tmpl.sp == rxq->sp) {
1000                 DEBUG("%p: nothing to do", (void *)dev);
1001                 return 0;
1002         }
1003         /* From now on, any failure will render the queue unusable.
1004          * Reinitialize WQ. */
1005         mod = (struct ibv_exp_wq_attr){
1006                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
1007                 .wq_state = IBV_EXP_WQS_RESET,
1008         };
1009         err = ibv_exp_modify_wq(tmpl.wq, &mod);
1010         if (err) {
1011                 ERROR("%p: cannot reset WQ: %s", (void *)dev, strerror(err));
1012                 assert(err > 0);
1013                 return err;
1014         }
1015         /* Allocate pool. */
1016         pool = rte_malloc(__func__, (mbuf_n * sizeof(*pool)), 0);
1017         if (pool == NULL) {
1018                 ERROR("%p: cannot allocate memory", (void *)dev);
1019                 return ENOBUFS;
1020         }
1021         /* Snatch mbufs from original queue. */
1022         k = 0;
1023         if (rxq->sp) {
1024                 struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp;
1025
1026                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1027                         struct rxq_elt_sp *elt = &(*elts)[i];
1028                         unsigned int j;
1029
1030                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
1031                                 assert(elt->bufs[j] != NULL);
1032                                 pool[k++] = elt->bufs[j];
1033                         }
1034                 }
1035         } else {
1036                 struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp;
1037
1038                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1039                         struct rxq_elt *elt = &(*elts)[i];
1040                         struct rte_mbuf *buf = elt->buf;
1041
1042                         pool[k++] = buf;
1043                 }
1044         }
1045         assert(k == mbuf_n);
1046         tmpl.elts_n = 0;
1047         tmpl.elts.sp = NULL;
1048         assert((void *)&tmpl.elts.sp == (void *)&tmpl.elts.no_sp);
1049         err = ((tmpl.sp) ?
1050                rxq_alloc_elts_sp(&tmpl, desc_n, pool) :
1051                rxq_alloc_elts(&tmpl, desc_n, pool));
1052         if (err) {
1053                 ERROR("%p: cannot reallocate WRs, aborting", (void *)dev);
1054                 rte_free(pool);
1055                 assert(err > 0);
1056                 return err;
1057         }
1058         assert(tmpl.elts_n == desc_n);
1059         assert(tmpl.elts.sp != NULL);
1060         rte_free(pool);
1061         /* Clean up original data. */
1062         rxq->elts_n = 0;
1063         rte_free(rxq->elts.sp);
1064         rxq->elts.sp = NULL;
1065         /* Change queue state to ready. */
1066         mod = (struct ibv_exp_wq_attr){
1067                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
1068                 .wq_state = IBV_EXP_WQS_RDY,
1069         };
1070         err = ibv_exp_modify_wq(tmpl.wq, &mod);
1071         if (err) {
1072                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
1073                       (void *)dev, strerror(err));
1074                 goto error;
1075         }
1076         /* Post SGEs. */
1077         assert(tmpl.if_wq != NULL);
1078         if (tmpl.sp) {
1079                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
1080
1081                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1082                         err = tmpl.if_wq->recv_sg_list
1083                                 (tmpl.wq,
1084                                  (*elts)[i].sges,
1085                                  RTE_DIM((*elts)[i].sges));
1086                         if (err)
1087                                 break;
1088                 }
1089         } else {
1090                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
1091
1092                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1093                         err = tmpl.if_wq->recv_burst(
1094                                 tmpl.wq,
1095                                 &(*elts)[i].sge,
1096                                 1);
1097                         if (err)
1098                                 break;
1099                 }
1100         }
1101         if (err) {
1102                 ERROR("%p: failed to post SGEs with error %d",
1103                       (void *)dev, err);
1104                 /* Set err because it does not contain a valid errno value. */
1105                 err = EIO;
1106                 goto error;
1107         }
1108         if (tmpl.sp)
1109                 tmpl.recv = tmpl.if_wq->recv_sg_list;
1110         else
1111                 tmpl.recv = tmpl.if_wq->recv_burst;
1112 error:
1113         *rxq = tmpl;
1114         assert(err >= 0);
1115         return err;
1116 }
1117
1118 /**
1119  * Configure a RX queue.
1120  *
1121  * @param dev
1122  *   Pointer to Ethernet device structure.
1123  * @param rxq
1124  *   Pointer to RX queue structure.
1125  * @param desc
1126  *   Number of descriptors to configure in queue.
1127  * @param socket
1128  *   NUMA socket on which memory must be allocated.
1129  * @param[in] conf
1130  *   Thresholds parameters.
1131  * @param mp
1132  *   Memory pool for buffer allocations.
1133  *
1134  * @return
1135  *   0 on success, errno value on failure.
1136  */
1137 int
1138 rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,
1139           unsigned int socket, const struct rte_eth_rxconf *conf,
1140           struct rte_mempool *mp)
1141 {
1142         struct priv *priv = dev->data->dev_private;
1143         struct rxq tmpl = {
1144                 .priv = priv,
1145                 .mp = mp,
1146                 .socket = socket
1147         };
1148         struct ibv_exp_wq_attr mod;
1149         union {
1150                 struct ibv_exp_query_intf_params params;
1151                 struct ibv_exp_cq_init_attr cq;
1152                 struct ibv_exp_res_domain_init_attr rd;
1153                 struct ibv_exp_wq_init_attr wq;
1154         } attr;
1155         enum ibv_exp_query_intf_status status;
1156         struct rte_mbuf *buf;
1157         int ret = 0;
1158         unsigned int i;
1159         unsigned int cq_size = desc;
1160
1161         (void)conf; /* Thresholds configuration (ignored). */
1162         if ((desc == 0) || (desc % MLX5_PMD_SGE_WR_N)) {
1163                 ERROR("%p: invalid number of RX descriptors (must be a"
1164                       " multiple of %d)", (void *)dev, MLX5_PMD_SGE_WR_N);
1165                 return EINVAL;
1166         }
1167         /* Get mbuf length. */
1168         buf = rte_pktmbuf_alloc(mp);
1169         if (buf == NULL) {
1170                 ERROR("%p: unable to allocate mbuf", (void *)dev);
1171                 return ENOMEM;
1172         }
1173         tmpl.mb_len = buf->buf_len;
1174         assert((rte_pktmbuf_headroom(buf) +
1175                 rte_pktmbuf_tailroom(buf)) == tmpl.mb_len);
1176         assert(rte_pktmbuf_headroom(buf) == RTE_PKTMBUF_HEADROOM);
1177         rte_pktmbuf_free(buf);
1178         /* Toggle RX checksum offload if hardware supports it. */
1179         if (priv->hw_csum)
1180                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1181         if (priv->hw_csum_l2tun)
1182                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1183         /* Enable scattered packets support for this queue if necessary. */
1184         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
1185             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
1186              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
1187                 tmpl.sp = 1;
1188                 desc /= MLX5_PMD_SGE_WR_N;
1189         }
1190         DEBUG("%p: %s scattered packets support (%u WRs)",
1191               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc);
1192         /* Use the entire RX mempool as the memory region. */
1193         tmpl.mr = ibv_reg_mr(priv->pd,
1194                              (void *)mp->elt_va_start,
1195                              (mp->elt_va_end - mp->elt_va_start),
1196                              (IBV_ACCESS_LOCAL_WRITE |
1197                               IBV_ACCESS_REMOTE_WRITE));
1198         if (tmpl.mr == NULL) {
1199                 ret = EINVAL;
1200                 ERROR("%p: MR creation failure: %s",
1201                       (void *)dev, strerror(ret));
1202                 goto error;
1203         }
1204         attr.rd = (struct ibv_exp_res_domain_init_attr){
1205                 .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL |
1206                               IBV_EXP_RES_DOMAIN_MSG_MODEL),
1207                 .thread_model = IBV_EXP_THREAD_SINGLE,
1208                 .msg_model = IBV_EXP_MSG_HIGH_BW,
1209         };
1210         tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd);
1211         if (tmpl.rd == NULL) {
1212                 ret = ENOMEM;
1213                 ERROR("%p: RD creation failure: %s",
1214                       (void *)dev, strerror(ret));
1215                 goto error;
1216         }
1217         attr.cq = (struct ibv_exp_cq_init_attr){
1218                 .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN,
1219                 .res_domain = tmpl.rd,
1220         };
1221         tmpl.cq = ibv_exp_create_cq(priv->ctx, cq_size, NULL, NULL, 0,
1222                                     &attr.cq);
1223         if (tmpl.cq == NULL) {
1224                 ret = ENOMEM;
1225                 ERROR("%p: CQ creation failure: %s",
1226                       (void *)dev, strerror(ret));
1227                 goto error;
1228         }
1229         DEBUG("priv->device_attr.max_qp_wr is %d",
1230               priv->device_attr.max_qp_wr);
1231         DEBUG("priv->device_attr.max_sge is %d",
1232               priv->device_attr.max_sge);
1233         /* Configure VLAN stripping. */
1234         tmpl.vlan_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
1235         attr.wq = (struct ibv_exp_wq_init_attr){
1236                 .wq_context = NULL, /* Could be useful in the future. */
1237                 .wq_type = IBV_EXP_WQT_RQ,
1238                 /* Max number of outstanding WRs. */
1239                 .max_recv_wr = ((priv->device_attr.max_qp_wr < (int)cq_size) ?
1240                                 priv->device_attr.max_qp_wr :
1241                                 (int)cq_size),
1242                 /* Max number of scatter/gather elements in a WR. */
1243                 .max_recv_sge = ((priv->device_attr.max_sge <
1244                                   MLX5_PMD_SGE_WR_N) ?
1245                                  priv->device_attr.max_sge :
1246                                  MLX5_PMD_SGE_WR_N),
1247                 .pd = priv->pd,
1248                 .cq = tmpl.cq,
1249                 .comp_mask =
1250                         IBV_EXP_CREATE_WQ_RES_DOMAIN |
1251 #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS
1252                         IBV_EXP_CREATE_WQ_VLAN_OFFLOADS |
1253 #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */
1254                         0,
1255                 .res_domain = tmpl.rd,
1256 #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS
1257                 .vlan_offloads = (tmpl.vlan_strip ?
1258                                   IBV_EXP_RECEIVE_WQ_CVLAN_STRIP :
1259                                   0),
1260 #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */
1261         };
1262         tmpl.wq = ibv_exp_create_wq(priv->ctx, &attr.wq);
1263         if (tmpl.wq == NULL) {
1264                 ret = (errno ? errno : EINVAL);
1265                 ERROR("%p: WQ creation failure: %s",
1266                       (void *)dev, strerror(ret));
1267                 goto error;
1268         }
1269         if (tmpl.sp)
1270                 ret = rxq_alloc_elts_sp(&tmpl, desc, NULL);
1271         else
1272                 ret = rxq_alloc_elts(&tmpl, desc, NULL);
1273         if (ret) {
1274                 ERROR("%p: RXQ allocation failed: %s",
1275                       (void *)dev, strerror(ret));
1276                 goto error;
1277         }
1278         /* Save port ID. */
1279         tmpl.port_id = dev->data->port_id;
1280         DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id);
1281         attr.params = (struct ibv_exp_query_intf_params){
1282                 .intf_scope = IBV_EXP_INTF_GLOBAL,
1283 #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS
1284                 .intf_version = 1,
1285 #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */
1286                 .intf = IBV_EXP_INTF_CQ,
1287                 .obj = tmpl.cq,
1288         };
1289         tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
1290         if (tmpl.if_cq == NULL) {
1291                 ERROR("%p: CQ interface family query failed with status %d",
1292                       (void *)dev, status);
1293                 goto error;
1294         }
1295         attr.params = (struct ibv_exp_query_intf_params){
1296                 .intf_scope = IBV_EXP_INTF_GLOBAL,
1297                 .intf = IBV_EXP_INTF_WQ,
1298                 .obj = tmpl.wq,
1299         };
1300         tmpl.if_wq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
1301         if (tmpl.if_wq == NULL) {
1302                 ERROR("%p: WQ interface family query failed with status %d",
1303                       (void *)dev, status);
1304                 goto error;
1305         }
1306         /* Change queue state to ready. */
1307         mod = (struct ibv_exp_wq_attr){
1308                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
1309                 .wq_state = IBV_EXP_WQS_RDY,
1310         };
1311         ret = ibv_exp_modify_wq(tmpl.wq, &mod);
1312         if (ret) {
1313                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
1314                       (void *)dev, strerror(ret));
1315                 goto error;
1316         }
1317         /* Post SGEs. */
1318         if (tmpl.sp) {
1319                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
1320
1321                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1322                         ret = tmpl.if_wq->recv_sg_list
1323                                 (tmpl.wq,
1324                                  (*elts)[i].sges,
1325                                  RTE_DIM((*elts)[i].sges));
1326                         if (ret)
1327                                 break;
1328                 }
1329         } else {
1330                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
1331
1332                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1333                         ret = tmpl.if_wq->recv_burst(
1334                                 tmpl.wq,
1335                                 &(*elts)[i].sge,
1336                                 1);
1337                         if (ret)
1338                                 break;
1339                 }
1340         }
1341         if (ret) {
1342                 ERROR("%p: failed to post SGEs with error %d",
1343                       (void *)dev, ret);
1344                 /* Set ret because it does not contain a valid errno value. */
1345                 ret = EIO;
1346                 goto error;
1347         }
1348         /* Clean up rxq in case we're reinitializing it. */
1349         DEBUG("%p: cleaning-up old rxq just in case", (void *)rxq);
1350         rxq_cleanup(rxq);
1351         *rxq = tmpl;
1352         DEBUG("%p: rxq updated with %p", (void *)rxq, (void *)&tmpl);
1353         assert(ret == 0);
1354         /* Assign function in queue. */
1355 #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS
1356         rxq->poll = rxq->if_cq->poll_length_flags_cvlan;
1357 #else /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */
1358         rxq->poll = rxq->if_cq->poll_length_flags;
1359 #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */
1360         if (rxq->sp)
1361                 rxq->recv = rxq->if_wq->recv_sg_list;
1362         else
1363                 rxq->recv = rxq->if_wq->recv_burst;
1364         return 0;
1365 error:
1366         rxq_cleanup(&tmpl);
1367         assert(ret > 0);
1368         return ret;
1369 }
1370
1371 /**
1372  * DPDK callback to configure a RX queue.
1373  *
1374  * @param dev
1375  *   Pointer to Ethernet device structure.
1376  * @param idx
1377  *   RX queue index.
1378  * @param desc
1379  *   Number of descriptors to configure in queue.
1380  * @param socket
1381  *   NUMA socket on which memory must be allocated.
1382  * @param[in] conf
1383  *   Thresholds parameters.
1384  * @param mp
1385  *   Memory pool for buffer allocations.
1386  *
1387  * @return
1388  *   0 on success, negative errno value on failure.
1389  */
1390 int
1391 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
1392                     unsigned int socket, const struct rte_eth_rxconf *conf,
1393                     struct rte_mempool *mp)
1394 {
1395         struct priv *priv = dev->data->dev_private;
1396         struct rxq *rxq = (*priv->rxqs)[idx];
1397         int ret;
1398
1399         priv_lock(priv);
1400         DEBUG("%p: configuring queue %u for %u descriptors",
1401               (void *)dev, idx, desc);
1402         if (idx >= priv->rxqs_n) {
1403                 ERROR("%p: queue index out of range (%u >= %u)",
1404                       (void *)dev, idx, priv->rxqs_n);
1405                 priv_unlock(priv);
1406                 return -EOVERFLOW;
1407         }
1408         if (rxq != NULL) {
1409                 DEBUG("%p: reusing already allocated queue index %u (%p)",
1410                       (void *)dev, idx, (void *)rxq);
1411                 if (priv->started) {
1412                         priv_unlock(priv);
1413                         return -EEXIST;
1414                 }
1415                 (*priv->rxqs)[idx] = NULL;
1416                 rxq_cleanup(rxq);
1417         } else {
1418                 rxq = rte_calloc_socket("RXQ", 1, sizeof(*rxq), 0, socket);
1419                 if (rxq == NULL) {
1420                         ERROR("%p: unable to allocate queue index %u",
1421                               (void *)dev, idx);
1422                         priv_unlock(priv);
1423                         return -ENOMEM;
1424                 }
1425         }
1426         ret = rxq_setup(dev, rxq, desc, socket, conf, mp);
1427         if (ret)
1428                 rte_free(rxq);
1429         else {
1430                 rxq->stats.idx = idx;
1431                 DEBUG("%p: adding RX queue %p to list",
1432                       (void *)dev, (void *)rxq);
1433                 (*priv->rxqs)[idx] = rxq;
1434                 /* Update receive callback. */
1435                 if (rxq->sp)
1436                         dev->rx_pkt_burst = mlx5_rx_burst_sp;
1437                 else
1438                         dev->rx_pkt_burst = mlx5_rx_burst;
1439         }
1440         priv_unlock(priv);
1441         return -ret;
1442 }
1443
1444 /**
1445  * DPDK callback to release a RX queue.
1446  *
1447  * @param dpdk_rxq
1448  *   Generic RX queue pointer.
1449  */
1450 void
1451 mlx5_rx_queue_release(void *dpdk_rxq)
1452 {
1453         struct rxq *rxq = (struct rxq *)dpdk_rxq;
1454         struct priv *priv;
1455         unsigned int i;
1456
1457         if (rxq == NULL)
1458                 return;
1459         priv = rxq->priv;
1460         priv_lock(priv);
1461         for (i = 0; (i != priv->rxqs_n); ++i)
1462                 if ((*priv->rxqs)[i] == rxq) {
1463                         DEBUG("%p: removing RX queue %p from list",
1464                               (void *)priv->dev, (void *)rxq);
1465                         (*priv->rxqs)[i] = NULL;
1466                         break;
1467                 }
1468         rxq_cleanup(rxq);
1469         rte_free(rxq);
1470         priv_unlock(priv);
1471 }