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