mlx5: refactor special flows handling
[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_MAC:
583                 return 1;
584         }
585         return 0;
586 }
587
588 /**
589  * Automatically enable/disable flows according to configuration.
590  *
591  * @param priv
592  *   Private structure.
593  *
594  * @return
595  *   0 on success, errno value on failure.
596  */
597 int
598 priv_rehash_flows(struct priv *priv)
599 {
600         unsigned int i;
601
602         for (i = 0; (i != RTE_DIM((*priv->hash_rxqs)[0].special_flow)); ++i)
603                 if (!priv_allow_flow_type(priv, i)) {
604                         priv_special_flow_disable(priv, i);
605                 } else {
606                         int ret = priv_special_flow_enable(priv, i);
607
608                         if (ret)
609                                 return ret;
610                 }
611         if (priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
612                 return priv_mac_addrs_enable(priv);
613         priv_mac_addrs_disable(priv);
614         return 0;
615 }
616
617 /**
618  * Allocate RX queue elements with scattered packets support.
619  *
620  * @param rxq
621  *   Pointer to RX queue structure.
622  * @param elts_n
623  *   Number of elements to allocate.
624  * @param[in] pool
625  *   If not NULL, fetch buffers from this array instead of allocating them
626  *   with rte_pktmbuf_alloc().
627  *
628  * @return
629  *   0 on success, errno value on failure.
630  */
631 static int
632 rxq_alloc_elts_sp(struct rxq *rxq, unsigned int elts_n,
633                   struct rte_mbuf **pool)
634 {
635         unsigned int i;
636         struct rxq_elt_sp (*elts)[elts_n] =
637                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
638                                   rxq->socket);
639         int ret = 0;
640
641         if (elts == NULL) {
642                 ERROR("%p: can't allocate packets array", (void *)rxq);
643                 ret = ENOMEM;
644                 goto error;
645         }
646         /* For each WR (packet). */
647         for (i = 0; (i != elts_n); ++i) {
648                 unsigned int j;
649                 struct rxq_elt_sp *elt = &(*elts)[i];
650                 struct ibv_sge (*sges)[RTE_DIM(elt->sges)] = &elt->sges;
651
652                 /* These two arrays must have the same size. */
653                 assert(RTE_DIM(elt->sges) == RTE_DIM(elt->bufs));
654                 /* For each SGE (segment). */
655                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
656                         struct ibv_sge *sge = &(*sges)[j];
657                         struct rte_mbuf *buf;
658
659                         if (pool != NULL) {
660                                 buf = *(pool++);
661                                 assert(buf != NULL);
662                                 rte_pktmbuf_reset(buf);
663                         } else
664                                 buf = rte_pktmbuf_alloc(rxq->mp);
665                         if (buf == NULL) {
666                                 assert(pool == NULL);
667                                 ERROR("%p: empty mbuf pool", (void *)rxq);
668                                 ret = ENOMEM;
669                                 goto error;
670                         }
671                         elt->bufs[j] = buf;
672                         /* Headroom is reserved by rte_pktmbuf_alloc(). */
673                         assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
674                         /* Buffer is supposed to be empty. */
675                         assert(rte_pktmbuf_data_len(buf) == 0);
676                         assert(rte_pktmbuf_pkt_len(buf) == 0);
677                         /* sge->addr must be able to store a pointer. */
678                         assert(sizeof(sge->addr) >= sizeof(uintptr_t));
679                         if (j == 0) {
680                                 /* The first SGE keeps its headroom. */
681                                 sge->addr = rte_pktmbuf_mtod(buf, uintptr_t);
682                                 sge->length = (buf->buf_len -
683                                                RTE_PKTMBUF_HEADROOM);
684                         } else {
685                                 /* Subsequent SGEs lose theirs. */
686                                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
687                                 SET_DATA_OFF(buf, 0);
688                                 sge->addr = (uintptr_t)buf->buf_addr;
689                                 sge->length = buf->buf_len;
690                         }
691                         sge->lkey = rxq->mr->lkey;
692                         /* Redundant check for tailroom. */
693                         assert(sge->length == rte_pktmbuf_tailroom(buf));
694                 }
695         }
696         DEBUG("%p: allocated and configured %u WRs (%zu segments)",
697               (void *)rxq, elts_n, (elts_n * RTE_DIM((*elts)[0].sges)));
698         rxq->elts_n = elts_n;
699         rxq->elts_head = 0;
700         rxq->elts.sp = elts;
701         assert(ret == 0);
702         return 0;
703 error:
704         if (elts != NULL) {
705                 assert(pool == NULL);
706                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
707                         unsigned int j;
708                         struct rxq_elt_sp *elt = &(*elts)[i];
709
710                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
711                                 struct rte_mbuf *buf = elt->bufs[j];
712
713                                 if (buf != NULL)
714                                         rte_pktmbuf_free_seg(buf);
715                         }
716                 }
717                 rte_free(elts);
718         }
719         DEBUG("%p: failed, freed everything", (void *)rxq);
720         assert(ret > 0);
721         return ret;
722 }
723
724 /**
725  * Free RX queue elements with scattered packets support.
726  *
727  * @param rxq
728  *   Pointer to RX queue structure.
729  */
730 static void
731 rxq_free_elts_sp(struct rxq *rxq)
732 {
733         unsigned int i;
734         unsigned int elts_n = rxq->elts_n;
735         struct rxq_elt_sp (*elts)[elts_n] = rxq->elts.sp;
736
737         DEBUG("%p: freeing WRs", (void *)rxq);
738         rxq->elts_n = 0;
739         rxq->elts.sp = NULL;
740         if (elts == NULL)
741                 return;
742         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
743                 unsigned int j;
744                 struct rxq_elt_sp *elt = &(*elts)[i];
745
746                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
747                         struct rte_mbuf *buf = elt->bufs[j];
748
749                         if (buf != NULL)
750                                 rte_pktmbuf_free_seg(buf);
751                 }
752         }
753         rte_free(elts);
754 }
755
756 /**
757  * Allocate RX queue elements.
758  *
759  * @param rxq
760  *   Pointer to RX queue structure.
761  * @param elts_n
762  *   Number of elements to allocate.
763  * @param[in] pool
764  *   If not NULL, fetch buffers from this array instead of allocating them
765  *   with rte_pktmbuf_alloc().
766  *
767  * @return
768  *   0 on success, errno value on failure.
769  */
770 static int
771 rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n, struct rte_mbuf **pool)
772 {
773         unsigned int i;
774         struct rxq_elt (*elts)[elts_n] =
775                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
776                                   rxq->socket);
777         int ret = 0;
778
779         if (elts == NULL) {
780                 ERROR("%p: can't allocate packets array", (void *)rxq);
781                 ret = ENOMEM;
782                 goto error;
783         }
784         /* For each WR (packet). */
785         for (i = 0; (i != elts_n); ++i) {
786                 struct rxq_elt *elt = &(*elts)[i];
787                 struct ibv_sge *sge = &(*elts)[i].sge;
788                 struct rte_mbuf *buf;
789
790                 if (pool != NULL) {
791                         buf = *(pool++);
792                         assert(buf != NULL);
793                         rte_pktmbuf_reset(buf);
794                 } else
795                         buf = rte_pktmbuf_alloc(rxq->mp);
796                 if (buf == NULL) {
797                         assert(pool == NULL);
798                         ERROR("%p: empty mbuf pool", (void *)rxq);
799                         ret = ENOMEM;
800                         goto error;
801                 }
802                 elt->buf = buf;
803                 /* Headroom is reserved by rte_pktmbuf_alloc(). */
804                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
805                 /* Buffer is supposed to be empty. */
806                 assert(rte_pktmbuf_data_len(buf) == 0);
807                 assert(rte_pktmbuf_pkt_len(buf) == 0);
808                 /* sge->addr must be able to store a pointer. */
809                 assert(sizeof(sge->addr) >= sizeof(uintptr_t));
810                 /* SGE keeps its headroom. */
811                 sge->addr = (uintptr_t)
812                         ((uint8_t *)buf->buf_addr + RTE_PKTMBUF_HEADROOM);
813                 sge->length = (buf->buf_len - RTE_PKTMBUF_HEADROOM);
814                 sge->lkey = rxq->mr->lkey;
815                 /* Redundant check for tailroom. */
816                 assert(sge->length == rte_pktmbuf_tailroom(buf));
817         }
818         DEBUG("%p: allocated and configured %u single-segment WRs",
819               (void *)rxq, elts_n);
820         rxq->elts_n = elts_n;
821         rxq->elts_head = 0;
822         rxq->elts.no_sp = elts;
823         assert(ret == 0);
824         return 0;
825 error:
826         if (elts != NULL) {
827                 assert(pool == NULL);
828                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
829                         struct rxq_elt *elt = &(*elts)[i];
830                         struct rte_mbuf *buf = elt->buf;
831
832                         if (buf != NULL)
833                                 rte_pktmbuf_free_seg(buf);
834                 }
835                 rte_free(elts);
836         }
837         DEBUG("%p: failed, freed everything", (void *)rxq);
838         assert(ret > 0);
839         return ret;
840 }
841
842 /**
843  * Free RX queue elements.
844  *
845  * @param rxq
846  *   Pointer to RX queue structure.
847  */
848 static void
849 rxq_free_elts(struct rxq *rxq)
850 {
851         unsigned int i;
852         unsigned int elts_n = rxq->elts_n;
853         struct rxq_elt (*elts)[elts_n] = rxq->elts.no_sp;
854
855         DEBUG("%p: freeing WRs", (void *)rxq);
856         rxq->elts_n = 0;
857         rxq->elts.no_sp = NULL;
858         if (elts == NULL)
859                 return;
860         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
861                 struct rxq_elt *elt = &(*elts)[i];
862                 struct rte_mbuf *buf = elt->buf;
863
864                 if (buf != NULL)
865                         rte_pktmbuf_free_seg(buf);
866         }
867         rte_free(elts);
868 }
869
870 /**
871  * Clean up a RX queue.
872  *
873  * Destroy objects, free allocated memory and reset the structure for reuse.
874  *
875  * @param rxq
876  *   Pointer to RX queue structure.
877  */
878 void
879 rxq_cleanup(struct rxq *rxq)
880 {
881         struct ibv_exp_release_intf_params params;
882
883         DEBUG("cleaning up %p", (void *)rxq);
884         if (rxq->sp)
885                 rxq_free_elts_sp(rxq);
886         else
887                 rxq_free_elts(rxq);
888         if (rxq->if_wq != NULL) {
889                 assert(rxq->priv != NULL);
890                 assert(rxq->priv->ctx != NULL);
891                 assert(rxq->wq != NULL);
892                 params = (struct ibv_exp_release_intf_params){
893                         .comp_mask = 0,
894                 };
895                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
896                                                 rxq->if_wq,
897                                                 &params));
898         }
899         if (rxq->if_cq != NULL) {
900                 assert(rxq->priv != NULL);
901                 assert(rxq->priv->ctx != NULL);
902                 assert(rxq->cq != NULL);
903                 params = (struct ibv_exp_release_intf_params){
904                         .comp_mask = 0,
905                 };
906                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
907                                                 rxq->if_cq,
908                                                 &params));
909         }
910         if (rxq->wq != NULL)
911                 claim_zero(ibv_exp_destroy_wq(rxq->wq));
912         if (rxq->cq != NULL)
913                 claim_zero(ibv_destroy_cq(rxq->cq));
914         if (rxq->rd != NULL) {
915                 struct ibv_exp_destroy_res_domain_attr attr = {
916                         .comp_mask = 0,
917                 };
918
919                 assert(rxq->priv != NULL);
920                 assert(rxq->priv->ctx != NULL);
921                 claim_zero(ibv_exp_destroy_res_domain(rxq->priv->ctx,
922                                                       rxq->rd,
923                                                       &attr));
924         }
925         if (rxq->mr != NULL)
926                 claim_zero(ibv_dereg_mr(rxq->mr));
927         memset(rxq, 0, sizeof(*rxq));
928 }
929
930 /**
931  * Reconfigure a RX queue with new parameters.
932  *
933  * rxq_rehash() does not allocate mbufs, which, if not done from the right
934  * thread (such as a control thread), may corrupt the pool.
935  * In case of failure, the queue is left untouched.
936  *
937  * @param dev
938  *   Pointer to Ethernet device structure.
939  * @param rxq
940  *   RX queue pointer.
941  *
942  * @return
943  *   0 on success, errno value on failure.
944  */
945 int
946 rxq_rehash(struct rte_eth_dev *dev, struct rxq *rxq)
947 {
948         struct priv *priv = rxq->priv;
949         struct rxq tmpl = *rxq;
950         unsigned int mbuf_n;
951         unsigned int desc_n;
952         struct rte_mbuf **pool;
953         unsigned int i, k;
954         struct ibv_exp_wq_attr mod;
955         int err;
956
957         DEBUG("%p: rehashing queue %p", (void *)dev, (void *)rxq);
958         /* Number of descriptors and mbufs currently allocated. */
959         desc_n = (tmpl.elts_n * (tmpl.sp ? MLX5_PMD_SGE_WR_N : 1));
960         mbuf_n = desc_n;
961         /* Toggle RX checksum offload if hardware supports it. */
962         if (priv->hw_csum) {
963                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
964                 rxq->csum = tmpl.csum;
965         }
966         if (priv->hw_csum_l2tun) {
967                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
968                 rxq->csum_l2tun = tmpl.csum_l2tun;
969         }
970         /* Enable scattered packets support for this queue if necessary. */
971         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
972             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
973              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
974                 tmpl.sp = 1;
975                 desc_n /= MLX5_PMD_SGE_WR_N;
976         } else
977                 tmpl.sp = 0;
978         DEBUG("%p: %s scattered packets support (%u WRs)",
979               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc_n);
980         /* If scatter mode is the same as before, nothing to do. */
981         if (tmpl.sp == rxq->sp) {
982                 DEBUG("%p: nothing to do", (void *)dev);
983                 return 0;
984         }
985         /* From now on, any failure will render the queue unusable.
986          * Reinitialize WQ. */
987         mod = (struct ibv_exp_wq_attr){
988                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
989                 .wq_state = IBV_EXP_WQS_RESET,
990         };
991         err = ibv_exp_modify_wq(tmpl.wq, &mod);
992         if (err) {
993                 ERROR("%p: cannot reset WQ: %s", (void *)dev, strerror(err));
994                 assert(err > 0);
995                 return err;
996         }
997         /* Allocate pool. */
998         pool = rte_malloc(__func__, (mbuf_n * sizeof(*pool)), 0);
999         if (pool == NULL) {
1000                 ERROR("%p: cannot allocate memory", (void *)dev);
1001                 return ENOBUFS;
1002         }
1003         /* Snatch mbufs from original queue. */
1004         k = 0;
1005         if (rxq->sp) {
1006                 struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp;
1007
1008                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1009                         struct rxq_elt_sp *elt = &(*elts)[i];
1010                         unsigned int j;
1011
1012                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
1013                                 assert(elt->bufs[j] != NULL);
1014                                 pool[k++] = elt->bufs[j];
1015                         }
1016                 }
1017         } else {
1018                 struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp;
1019
1020                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1021                         struct rxq_elt *elt = &(*elts)[i];
1022                         struct rte_mbuf *buf = elt->buf;
1023
1024                         pool[k++] = buf;
1025                 }
1026         }
1027         assert(k == mbuf_n);
1028         tmpl.elts_n = 0;
1029         tmpl.elts.sp = NULL;
1030         assert((void *)&tmpl.elts.sp == (void *)&tmpl.elts.no_sp);
1031         err = ((tmpl.sp) ?
1032                rxq_alloc_elts_sp(&tmpl, desc_n, pool) :
1033                rxq_alloc_elts(&tmpl, desc_n, pool));
1034         if (err) {
1035                 ERROR("%p: cannot reallocate WRs, aborting", (void *)dev);
1036                 rte_free(pool);
1037                 assert(err > 0);
1038                 return err;
1039         }
1040         assert(tmpl.elts_n == desc_n);
1041         assert(tmpl.elts.sp != NULL);
1042         rte_free(pool);
1043         /* Clean up original data. */
1044         rxq->elts_n = 0;
1045         rte_free(rxq->elts.sp);
1046         rxq->elts.sp = NULL;
1047         /* Change queue state to ready. */
1048         mod = (struct ibv_exp_wq_attr){
1049                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
1050                 .wq_state = IBV_EXP_WQS_RDY,
1051         };
1052         err = ibv_exp_modify_wq(tmpl.wq, &mod);
1053         if (err) {
1054                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
1055                       (void *)dev, strerror(err));
1056                 goto error;
1057         }
1058         /* Post SGEs. */
1059         assert(tmpl.if_wq != NULL);
1060         if (tmpl.sp) {
1061                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
1062
1063                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1064                         err = tmpl.if_wq->recv_sg_list
1065                                 (tmpl.wq,
1066                                  (*elts)[i].sges,
1067                                  RTE_DIM((*elts)[i].sges));
1068                         if (err)
1069                                 break;
1070                 }
1071         } else {
1072                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
1073
1074                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1075                         err = tmpl.if_wq->recv_burst(
1076                                 tmpl.wq,
1077                                 &(*elts)[i].sge,
1078                                 1);
1079                         if (err)
1080                                 break;
1081                 }
1082         }
1083         if (err) {
1084                 ERROR("%p: failed to post SGEs with error %d",
1085                       (void *)dev, err);
1086                 /* Set err because it does not contain a valid errno value. */
1087                 err = EIO;
1088                 goto error;
1089         }
1090 error:
1091         *rxq = tmpl;
1092         assert(err >= 0);
1093         return err;
1094 }
1095
1096 /**
1097  * Configure a RX queue.
1098  *
1099  * @param dev
1100  *   Pointer to Ethernet device structure.
1101  * @param rxq
1102  *   Pointer to RX queue structure.
1103  * @param desc
1104  *   Number of descriptors to configure in queue.
1105  * @param socket
1106  *   NUMA socket on which memory must be allocated.
1107  * @param[in] conf
1108  *   Thresholds parameters.
1109  * @param mp
1110  *   Memory pool for buffer allocations.
1111  *
1112  * @return
1113  *   0 on success, errno value on failure.
1114  */
1115 int
1116 rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,
1117           unsigned int socket, const struct rte_eth_rxconf *conf,
1118           struct rte_mempool *mp)
1119 {
1120         struct priv *priv = dev->data->dev_private;
1121         struct rxq tmpl = {
1122                 .priv = priv,
1123                 .mp = mp,
1124                 .socket = socket
1125         };
1126         struct ibv_exp_wq_attr mod;
1127         union {
1128                 struct ibv_exp_query_intf_params params;
1129                 struct ibv_exp_cq_init_attr cq;
1130                 struct ibv_exp_res_domain_init_attr rd;
1131                 struct ibv_exp_wq_init_attr wq;
1132         } attr;
1133         enum ibv_exp_query_intf_status status;
1134         struct rte_mbuf *buf;
1135         int ret = 0;
1136         unsigned int i;
1137         unsigned int cq_size = desc;
1138
1139         (void)conf; /* Thresholds configuration (ignored). */
1140         if ((desc == 0) || (desc % MLX5_PMD_SGE_WR_N)) {
1141                 ERROR("%p: invalid number of RX descriptors (must be a"
1142                       " multiple of %d)", (void *)dev, MLX5_PMD_SGE_WR_N);
1143                 return EINVAL;
1144         }
1145         /* Get mbuf length. */
1146         buf = rte_pktmbuf_alloc(mp);
1147         if (buf == NULL) {
1148                 ERROR("%p: unable to allocate mbuf", (void *)dev);
1149                 return ENOMEM;
1150         }
1151         tmpl.mb_len = buf->buf_len;
1152         assert((rte_pktmbuf_headroom(buf) +
1153                 rte_pktmbuf_tailroom(buf)) == tmpl.mb_len);
1154         assert(rte_pktmbuf_headroom(buf) == RTE_PKTMBUF_HEADROOM);
1155         rte_pktmbuf_free(buf);
1156         /* Toggle RX checksum offload if hardware supports it. */
1157         if (priv->hw_csum)
1158                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1159         if (priv->hw_csum_l2tun)
1160                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1161         /* Enable scattered packets support for this queue if necessary. */
1162         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
1163             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
1164              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
1165                 tmpl.sp = 1;
1166                 desc /= MLX5_PMD_SGE_WR_N;
1167         }
1168         DEBUG("%p: %s scattered packets support (%u WRs)",
1169               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc);
1170         /* Use the entire RX mempool as the memory region. */
1171         tmpl.mr = ibv_reg_mr(priv->pd,
1172                              (void *)mp->elt_va_start,
1173                              (mp->elt_va_end - mp->elt_va_start),
1174                              (IBV_ACCESS_LOCAL_WRITE |
1175                               IBV_ACCESS_REMOTE_WRITE));
1176         if (tmpl.mr == NULL) {
1177                 ret = EINVAL;
1178                 ERROR("%p: MR creation failure: %s",
1179                       (void *)dev, strerror(ret));
1180                 goto error;
1181         }
1182         attr.rd = (struct ibv_exp_res_domain_init_attr){
1183                 .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL |
1184                               IBV_EXP_RES_DOMAIN_MSG_MODEL),
1185                 .thread_model = IBV_EXP_THREAD_SINGLE,
1186                 .msg_model = IBV_EXP_MSG_HIGH_BW,
1187         };
1188         tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd);
1189         if (tmpl.rd == NULL) {
1190                 ret = ENOMEM;
1191                 ERROR("%p: RD creation failure: %s",
1192                       (void *)dev, strerror(ret));
1193                 goto error;
1194         }
1195         attr.cq = (struct ibv_exp_cq_init_attr){
1196                 .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN,
1197                 .res_domain = tmpl.rd,
1198         };
1199         tmpl.cq = ibv_exp_create_cq(priv->ctx, cq_size, NULL, NULL, 0,
1200                                     &attr.cq);
1201         if (tmpl.cq == NULL) {
1202                 ret = ENOMEM;
1203                 ERROR("%p: CQ creation failure: %s",
1204                       (void *)dev, strerror(ret));
1205                 goto error;
1206         }
1207         DEBUG("priv->device_attr.max_qp_wr is %d",
1208               priv->device_attr.max_qp_wr);
1209         DEBUG("priv->device_attr.max_sge is %d",
1210               priv->device_attr.max_sge);
1211         attr.wq = (struct ibv_exp_wq_init_attr){
1212                 .wq_context = NULL, /* Could be useful in the future. */
1213                 .wq_type = IBV_EXP_WQT_RQ,
1214                 /* Max number of outstanding WRs. */
1215                 .max_recv_wr = ((priv->device_attr.max_qp_wr < (int)cq_size) ?
1216                                 priv->device_attr.max_qp_wr :
1217                                 (int)cq_size),
1218                 /* Max number of scatter/gather elements in a WR. */
1219                 .max_recv_sge = ((priv->device_attr.max_sge <
1220                                   MLX5_PMD_SGE_WR_N) ?
1221                                  priv->device_attr.max_sge :
1222                                  MLX5_PMD_SGE_WR_N),
1223                 .pd = priv->pd,
1224                 .cq = tmpl.cq,
1225                 .comp_mask = IBV_EXP_CREATE_WQ_RES_DOMAIN,
1226                 .res_domain = tmpl.rd,
1227         };
1228         tmpl.wq = ibv_exp_create_wq(priv->ctx, &attr.wq);
1229         if (tmpl.wq == NULL) {
1230                 ret = (errno ? errno : EINVAL);
1231                 ERROR("%p: WQ creation failure: %s",
1232                       (void *)dev, strerror(ret));
1233                 goto error;
1234         }
1235         if (tmpl.sp)
1236                 ret = rxq_alloc_elts_sp(&tmpl, desc, NULL);
1237         else
1238                 ret = rxq_alloc_elts(&tmpl, desc, NULL);
1239         if (ret) {
1240                 ERROR("%p: RXQ allocation failed: %s",
1241                       (void *)dev, strerror(ret));
1242                 goto error;
1243         }
1244         /* Save port ID. */
1245         tmpl.port_id = dev->data->port_id;
1246         DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id);
1247         attr.params = (struct ibv_exp_query_intf_params){
1248                 .intf_scope = IBV_EXP_INTF_GLOBAL,
1249                 .intf = IBV_EXP_INTF_CQ,
1250                 .obj = tmpl.cq,
1251         };
1252         tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
1253         if (tmpl.if_cq == NULL) {
1254                 ERROR("%p: CQ interface family query failed with status %d",
1255                       (void *)dev, status);
1256                 goto error;
1257         }
1258         attr.params = (struct ibv_exp_query_intf_params){
1259                 .intf_scope = IBV_EXP_INTF_GLOBAL,
1260                 .intf = IBV_EXP_INTF_WQ,
1261                 .obj = tmpl.wq,
1262         };
1263         tmpl.if_wq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
1264         if (tmpl.if_wq == NULL) {
1265                 ERROR("%p: WQ interface family query failed with status %d",
1266                       (void *)dev, status);
1267                 goto error;
1268         }
1269         /* Change queue state to ready. */
1270         mod = (struct ibv_exp_wq_attr){
1271                 .attr_mask = IBV_EXP_WQ_ATTR_STATE,
1272                 .wq_state = IBV_EXP_WQS_RDY,
1273         };
1274         ret = ibv_exp_modify_wq(tmpl.wq, &mod);
1275         if (ret) {
1276                 ERROR("%p: WQ state to IBV_EXP_WQS_RDY failed: %s",
1277                       (void *)dev, strerror(ret));
1278                 goto error;
1279         }
1280         /* Post SGEs. */
1281         if (tmpl.sp) {
1282                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
1283
1284                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1285                         ret = tmpl.if_wq->recv_sg_list
1286                                 (tmpl.wq,
1287                                  (*elts)[i].sges,
1288                                  RTE_DIM((*elts)[i].sges));
1289                         if (ret)
1290                                 break;
1291                 }
1292         } else {
1293                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
1294
1295                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
1296                         ret = tmpl.if_wq->recv_burst(
1297                                 tmpl.wq,
1298                                 &(*elts)[i].sge,
1299                                 1);
1300                         if (ret)
1301                                 break;
1302                 }
1303         }
1304         if (ret) {
1305                 ERROR("%p: failed to post SGEs with error %d",
1306                       (void *)dev, ret);
1307                 /* Set ret because it does not contain a valid errno value. */
1308                 ret = EIO;
1309                 goto error;
1310         }
1311         /* Clean up rxq in case we're reinitializing it. */
1312         DEBUG("%p: cleaning-up old rxq just in case", (void *)rxq);
1313         rxq_cleanup(rxq);
1314         *rxq = tmpl;
1315         DEBUG("%p: rxq updated with %p", (void *)rxq, (void *)&tmpl);
1316         assert(ret == 0);
1317         return 0;
1318 error:
1319         rxq_cleanup(&tmpl);
1320         assert(ret > 0);
1321         return ret;
1322 }
1323
1324 /**
1325  * DPDK callback to configure a RX queue.
1326  *
1327  * @param dev
1328  *   Pointer to Ethernet device structure.
1329  * @param idx
1330  *   RX queue index.
1331  * @param desc
1332  *   Number of descriptors to configure in queue.
1333  * @param socket
1334  *   NUMA socket on which memory must be allocated.
1335  * @param[in] conf
1336  *   Thresholds parameters.
1337  * @param mp
1338  *   Memory pool for buffer allocations.
1339  *
1340  * @return
1341  *   0 on success, negative errno value on failure.
1342  */
1343 int
1344 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
1345                     unsigned int socket, const struct rte_eth_rxconf *conf,
1346                     struct rte_mempool *mp)
1347 {
1348         struct priv *priv = dev->data->dev_private;
1349         struct rxq *rxq = (*priv->rxqs)[idx];
1350         int ret;
1351
1352         priv_lock(priv);
1353         DEBUG("%p: configuring queue %u for %u descriptors",
1354               (void *)dev, idx, desc);
1355         if (idx >= priv->rxqs_n) {
1356                 ERROR("%p: queue index out of range (%u >= %u)",
1357                       (void *)dev, idx, priv->rxqs_n);
1358                 priv_unlock(priv);
1359                 return -EOVERFLOW;
1360         }
1361         if (rxq != NULL) {
1362                 DEBUG("%p: reusing already allocated queue index %u (%p)",
1363                       (void *)dev, idx, (void *)rxq);
1364                 if (priv->started) {
1365                         priv_unlock(priv);
1366                         return -EEXIST;
1367                 }
1368                 (*priv->rxqs)[idx] = NULL;
1369                 rxq_cleanup(rxq);
1370         } else {
1371                 rxq = rte_calloc_socket("RXQ", 1, sizeof(*rxq), 0, socket);
1372                 if (rxq == NULL) {
1373                         ERROR("%p: unable to allocate queue index %u",
1374                               (void *)dev, idx);
1375                         priv_unlock(priv);
1376                         return -ENOMEM;
1377                 }
1378         }
1379         ret = rxq_setup(dev, rxq, desc, socket, conf, mp);
1380         if (ret)
1381                 rte_free(rxq);
1382         else {
1383                 rxq->stats.idx = idx;
1384                 DEBUG("%p: adding RX queue %p to list",
1385                       (void *)dev, (void *)rxq);
1386                 (*priv->rxqs)[idx] = rxq;
1387                 /* Update receive callback. */
1388                 if (rxq->sp)
1389                         dev->rx_pkt_burst = mlx5_rx_burst_sp;
1390                 else
1391                         dev->rx_pkt_burst = mlx5_rx_burst;
1392         }
1393         priv_unlock(priv);
1394         return -ret;
1395 }
1396
1397 /**
1398  * DPDK callback to release a RX queue.
1399  *
1400  * @param dpdk_rxq
1401  *   Generic RX queue pointer.
1402  */
1403 void
1404 mlx5_rx_queue_release(void *dpdk_rxq)
1405 {
1406         struct rxq *rxq = (struct rxq *)dpdk_rxq;
1407         struct priv *priv;
1408         unsigned int i;
1409
1410         if (rxq == NULL)
1411                 return;
1412         priv = rxq->priv;
1413         priv_lock(priv);
1414         for (i = 0; (i != priv->rxqs_n); ++i)
1415                 if ((*priv->rxqs)[i] == rxq) {
1416                         DEBUG("%p: removing RX queue %p from list",
1417                               (void *)priv->dev, (void *)rxq);
1418                         (*priv->rxqs)[i] = NULL;
1419                         break;
1420                 }
1421         rxq_cleanup(rxq);
1422         rte_free(rxq);
1423         priv_unlock(priv);
1424 }