net/mlx5: handle a single RSS hash key for all protocols
[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 #include <fcntl.h>
40 #include <sys/queue.h>
41
42 /* Verbs header. */
43 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
44 #ifdef PEDANTIC
45 #pragma GCC diagnostic ignored "-Wpedantic"
46 #endif
47 #include <infiniband/verbs.h>
48 #include <infiniband/mlx5dv.h>
49 #ifdef PEDANTIC
50 #pragma GCC diagnostic error "-Wpedantic"
51 #endif
52
53 #include <rte_mbuf.h>
54 #include <rte_malloc.h>
55 #include <rte_ethdev.h>
56 #include <rte_common.h>
57 #include <rte_interrupts.h>
58 #include <rte_debug.h>
59 #include <rte_io.h>
60
61 #include "mlx5.h"
62 #include "mlx5_rxtx.h"
63 #include "mlx5_utils.h"
64 #include "mlx5_autoconf.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_RX_HASH_SRC_IPV4 |
71                                 IBV_RX_HASH_DST_IPV4 |
72                                 IBV_RX_HASH_SRC_PORT_TCP |
73                                 IBV_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_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_RX_HASH_SRC_IPV4 |
84                                 IBV_RX_HASH_DST_IPV4 |
85                                 IBV_RX_HASH_SRC_PORT_UDP |
86                                 IBV_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_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_RX_HASH_SRC_IPV4 |
97                                 IBV_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_FLOW_SPEC_IPV4,
103                         .size = sizeof(hash_rxq_init[0].flow_spec.ipv4),
104                 },
105                 .underlayer = &hash_rxq_init[HASH_RXQ_ETH],
106         },
107         [HASH_RXQ_TCPV6] = {
108                 .hash_fields = (IBV_RX_HASH_SRC_IPV6 |
109                                 IBV_RX_HASH_DST_IPV6 |
110                                 IBV_RX_HASH_SRC_PORT_TCP |
111                                 IBV_RX_HASH_DST_PORT_TCP),
112                 .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_TCP,
113                 .flow_priority = 0,
114                 .flow_spec.tcp_udp = {
115                         .type = IBV_FLOW_SPEC_TCP,
116                         .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp),
117                 },
118                 .underlayer = &hash_rxq_init[HASH_RXQ_IPV6],
119         },
120         [HASH_RXQ_UDPV6] = {
121                 .hash_fields = (IBV_RX_HASH_SRC_IPV6 |
122                                 IBV_RX_HASH_DST_IPV6 |
123                                 IBV_RX_HASH_SRC_PORT_UDP |
124                                 IBV_RX_HASH_DST_PORT_UDP),
125                 .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_UDP,
126                 .flow_priority = 0,
127                 .flow_spec.tcp_udp = {
128                         .type = IBV_FLOW_SPEC_UDP,
129                         .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp),
130                 },
131                 .underlayer = &hash_rxq_init[HASH_RXQ_IPV6],
132         },
133         [HASH_RXQ_IPV6] = {
134                 .hash_fields = (IBV_RX_HASH_SRC_IPV6 |
135                                 IBV_RX_HASH_DST_IPV6),
136                 .dpdk_rss_hf = (ETH_RSS_IPV6 |
137                                 ETH_RSS_FRAG_IPV6),
138                 .flow_priority = 1,
139                 .flow_spec.ipv6 = {
140                         .type = IBV_FLOW_SPEC_IPV6,
141                         .size = sizeof(hash_rxq_init[0].flow_spec.ipv6),
142                 },
143                 .underlayer = &hash_rxq_init[HASH_RXQ_ETH],
144         },
145         [HASH_RXQ_ETH] = {
146                 .hash_fields = 0,
147                 .dpdk_rss_hf = 0,
148                 .flow_priority = 2,
149                 .flow_spec.eth = {
150                         .type = IBV_FLOW_SPEC_ETH,
151                         .size = sizeof(hash_rxq_init[0].flow_spec.eth),
152                 },
153                 .underlayer = NULL,
154         },
155 };
156
157 /* Number of entries in hash_rxq_init[]. */
158 const unsigned int hash_rxq_init_n = RTE_DIM(hash_rxq_init);
159
160 /* Initialization data for hash RX queue indirection tables. */
161 static const struct ind_table_init ind_table_init[] = {
162         {
163                 .max_size = -1u, /* Superseded by HW limitations. */
164                 .hash_types =
165                         1 << HASH_RXQ_TCPV4 |
166                         1 << HASH_RXQ_UDPV4 |
167                         1 << HASH_RXQ_IPV4 |
168                         1 << HASH_RXQ_TCPV6 |
169                         1 << HASH_RXQ_UDPV6 |
170                         1 << HASH_RXQ_IPV6 |
171                         0,
172                 .hash_types_n = 6,
173         },
174         {
175                 .max_size = 1,
176                 .hash_types = 1 << HASH_RXQ_ETH,
177                 .hash_types_n = 1,
178         },
179 };
180
181 #define IND_TABLE_INIT_N RTE_DIM(ind_table_init)
182
183 /* Default RSS hash key also used for ConnectX-3. */
184 uint8_t rss_hash_default_key[] = {
185         0x2c, 0xc6, 0x81, 0xd1,
186         0x5b, 0xdb, 0xf4, 0xf7,
187         0xfc, 0xa2, 0x83, 0x19,
188         0xdb, 0x1a, 0x3e, 0x94,
189         0x6b, 0x9e, 0x38, 0xd9,
190         0x2c, 0x9c, 0x03, 0xd1,
191         0xad, 0x99, 0x44, 0xa7,
192         0xd9, 0x56, 0x3d, 0x59,
193         0x06, 0x3c, 0x25, 0xf3,
194         0xfc, 0x1f, 0xdc, 0x2a,
195 };
196
197 /* Length of the default RSS hash key. */
198 const size_t rss_hash_default_key_len = sizeof(rss_hash_default_key);
199
200 /**
201  * Populate flow steering rule for a given hash RX queue type using
202  * information from hash_rxq_init[]. Nothing is written to flow_attr when
203  * flow_attr_size is not large enough, but the required size is still returned.
204  *
205  * @param priv
206  *   Pointer to private structure.
207  * @param[out] flow_attr
208  *   Pointer to flow attribute structure to fill. Note that the allocated
209  *   area must be larger and large enough to hold all flow specifications.
210  * @param flow_attr_size
211  *   Entire size of flow_attr and trailing room for flow specifications.
212  * @param type
213  *   Hash RX queue type to use for flow steering rule.
214  *
215  * @return
216  *   Total size of the flow attribute buffer. No errors are defined.
217  */
218 size_t
219 priv_flow_attr(struct priv *priv, struct ibv_flow_attr *flow_attr,
220                size_t flow_attr_size, enum hash_rxq_type type)
221 {
222         size_t offset = sizeof(*flow_attr);
223         const struct hash_rxq_init *init = &hash_rxq_init[type];
224
225         assert(priv != NULL);
226         assert((size_t)type < RTE_DIM(hash_rxq_init));
227         do {
228                 offset += init->flow_spec.hdr.size;
229                 init = init->underlayer;
230         } while (init != NULL);
231         if (offset > flow_attr_size)
232                 return offset;
233         flow_attr_size = offset;
234         init = &hash_rxq_init[type];
235         *flow_attr = (struct ibv_flow_attr){
236                 .type = IBV_FLOW_ATTR_NORMAL,
237                 /* Priorities < 3 are reserved for flow director. */
238                 .priority = init->flow_priority + 3,
239                 .num_of_specs = 0,
240                 .port = priv->port,
241                 .flags = 0,
242         };
243         do {
244                 offset -= init->flow_spec.hdr.size;
245                 memcpy((void *)((uintptr_t)flow_attr + offset),
246                        &init->flow_spec,
247                        init->flow_spec.hdr.size);
248                 ++flow_attr->num_of_specs;
249                 init = init->underlayer;
250         } while (init != NULL);
251         return flow_attr_size;
252 }
253
254 /**
255  * Convert hash type position in indirection table initializer to
256  * hash RX queue type.
257  *
258  * @param table
259  *   Indirection table initializer.
260  * @param pos
261  *   Hash type position.
262  *
263  * @return
264  *   Hash RX queue type.
265  */
266 static enum hash_rxq_type
267 hash_rxq_type_from_pos(const struct ind_table_init *table, unsigned int pos)
268 {
269         enum hash_rxq_type type = HASH_RXQ_TCPV4;
270
271         assert(pos < table->hash_types_n);
272         do {
273                 if ((table->hash_types & (1 << type)) && (pos-- == 0))
274                         break;
275                 ++type;
276         } while (1);
277         return type;
278 }
279
280 /**
281  * Filter out disabled hash RX queue types from ind_table_init[].
282  *
283  * @param priv
284  *   Pointer to private structure.
285  * @param[out] table
286  *   Output table.
287  *
288  * @return
289  *   Number of table entries.
290  */
291 static unsigned int
292 priv_make_ind_table_init(struct priv *priv,
293                          struct ind_table_init (*table)[IND_TABLE_INIT_N])
294 {
295         uint64_t rss_hf;
296         unsigned int i;
297         unsigned int j;
298         unsigned int table_n = 0;
299         /* Mandatory to receive frames not handled by normal hash RX queues. */
300         unsigned int hash_types_sup = 1 << HASH_RXQ_ETH;
301
302         rss_hf = priv->rss_conf.rss_hf;
303         /* Process other protocols only if more than one queue. */
304         if (priv->rxqs_n > 1)
305                 for (i = 0; (i != hash_rxq_init_n); ++i)
306                         if (rss_hf & hash_rxq_init[i].dpdk_rss_hf)
307                                 hash_types_sup |= (1 << i);
308
309         /* Filter out entries whose protocols are not in the set. */
310         for (i = 0, j = 0; (i != IND_TABLE_INIT_N); ++i) {
311                 unsigned int nb;
312                 unsigned int h;
313
314                 /* j is increased only if the table has valid protocols. */
315                 assert(j <= i);
316                 (*table)[j] = ind_table_init[i];
317                 (*table)[j].hash_types &= hash_types_sup;
318                 for (h = 0, nb = 0; (h != hash_rxq_init_n); ++h)
319                         if (((*table)[j].hash_types >> h) & 0x1)
320                                 ++nb;
321                 (*table)[i].hash_types_n = nb;
322                 if (nb) {
323                         ++table_n;
324                         ++j;
325                 }
326         }
327         return table_n;
328 }
329
330 /**
331  * Initialize hash RX queues and indirection table.
332  *
333  * @param priv
334  *   Pointer to private structure.
335  *
336  * @return
337  *   0 on success, errno value on failure.
338  */
339 int
340 priv_create_hash_rxqs(struct priv *priv)
341 {
342         struct ibv_wq *wqs[priv->reta_idx_n];
343         struct ind_table_init ind_table_init[IND_TABLE_INIT_N];
344         unsigned int ind_tables_n =
345                 priv_make_ind_table_init(priv, &ind_table_init);
346         unsigned int hash_rxqs_n = 0;
347         struct hash_rxq (*hash_rxqs)[] = NULL;
348         struct ibv_rwq_ind_table *(*ind_tables)[] = NULL;
349         unsigned int i;
350         unsigned int j;
351         unsigned int k;
352         int err = 0;
353
354         assert(priv->ind_tables == NULL);
355         assert(priv->ind_tables_n == 0);
356         assert(priv->hash_rxqs == NULL);
357         assert(priv->hash_rxqs_n == 0);
358         assert(priv->pd != NULL);
359         assert(priv->ctx != NULL);
360         if (priv->isolated)
361                 return 0;
362         if (priv->rxqs_n == 0)
363                 return EINVAL;
364         assert(priv->rxqs != NULL);
365         if (ind_tables_n == 0) {
366                 ERROR("all hash RX queue types have been filtered out,"
367                       " indirection table cannot be created");
368                 return EINVAL;
369         }
370         if (priv->rxqs_n & (priv->rxqs_n - 1)) {
371                 INFO("%u RX queues are configured, consider rounding this"
372                      " number to the next power of two for better balancing",
373                      priv->rxqs_n);
374                 DEBUG("indirection table extended to assume %u WQs",
375                       priv->reta_idx_n);
376         }
377         for (i = 0; (i != priv->reta_idx_n); ++i) {
378                 struct mlx5_rxq_ctrl *rxq_ctrl;
379
380                 rxq_ctrl = container_of((*priv->rxqs)[(*priv->reta_idx)[i]],
381                                         struct mlx5_rxq_ctrl, rxq);
382                 wqs[i] = rxq_ctrl->ibv->wq;
383         }
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_rwq_ind_table_init_attr ind_init_attr = {
400                         .log_ind_tbl_size = 0, /* Set below. */
401                         .ind_tbl = wqs,
402                         .comp_mask = 0,
403                 };
404                 unsigned int ind_tbl_size = ind_table_init[i].max_size;
405                 struct ibv_rwq_ind_table *ind_table;
406
407                 if (priv->reta_idx_n < ind_tbl_size)
408                         ind_tbl_size = priv->reta_idx_n;
409                 ind_init_attr.log_ind_tbl_size = log2above(ind_tbl_size);
410                 errno = 0;
411                 ind_table = ibv_create_rwq_ind_table(priv->ctx,
412                                                      &ind_init_attr);
413                 if (ind_table != NULL) {
414                         (*ind_tables)[i] = ind_table;
415                         continue;
416                 }
417                 /* Not clear whether errno is set. */
418                 err = (errno ? errno : EINVAL);
419                 ERROR("RX indirection table creation failed with error %d: %s",
420                       err, strerror(err));
421                 goto error;
422         }
423         /* Allocate array that holds hash RX queues and related data. */
424         hash_rxqs = rte_calloc(__func__, hash_rxqs_n,
425                                sizeof((*hash_rxqs)[0]), 0);
426         if (hash_rxqs == NULL) {
427                 err = ENOMEM;
428                 ERROR("cannot allocate hash RX queues container: %s",
429                       strerror(err));
430                 goto error;
431         }
432         for (i = 0, j = 0, k = 0;
433              ((i != hash_rxqs_n) && (j != ind_tables_n));
434              ++i) {
435                 struct hash_rxq *hash_rxq = &(*hash_rxqs)[i];
436                 enum hash_rxq_type type =
437                         hash_rxq_type_from_pos(&ind_table_init[j], k);
438                 struct rte_eth_rss_conf *priv_rss_conf = &priv->rss_conf;
439                 struct ibv_rx_hash_conf hash_conf = {
440                         .rx_hash_function = IBV_RX_HASH_FUNC_TOEPLITZ,
441                         .rx_hash_key_len = (priv_rss_conf ?
442                                             priv_rss_conf->rss_key_len :
443                                             rss_hash_default_key_len),
444                         .rx_hash_key = (priv_rss_conf ?
445                                         priv_rss_conf->rss_key :
446                                         rss_hash_default_key),
447                         .rx_hash_fields_mask = hash_rxq_init[type].hash_fields,
448                 };
449                 struct ibv_qp_init_attr_ex qp_init_attr = {
450                         .qp_type = IBV_QPT_RAW_PACKET,
451                         .comp_mask = (IBV_QP_INIT_ATTR_PD |
452                                       IBV_QP_INIT_ATTR_IND_TABLE |
453                                       IBV_QP_INIT_ATTR_RX_HASH),
454                         .rx_hash_conf = hash_conf,
455                         .rwq_ind_tbl = (*ind_tables)[j],
456                         .pd = priv->pd,
457                 };
458
459                 DEBUG("using indirection table %u for hash RX queue %u type %d",
460                       j, i, type);
461                 *hash_rxq = (struct hash_rxq){
462                         .priv = priv,
463                         .qp = ibv_create_qp_ex(priv->ctx, &qp_init_attr),
464                         .type = type,
465                 };
466                 if (hash_rxq->qp == NULL) {
467                         err = (errno ? errno : EINVAL);
468                         ERROR("Hash RX QP creation failure: %s",
469                               strerror(err));
470                         goto error;
471                 }
472                 if (++k < ind_table_init[j].hash_types_n)
473                         continue;
474                 /* Switch to the next indirection table and reset hash RX
475                  * queue type array index. */
476                 ++j;
477                 k = 0;
478         }
479         priv->ind_tables = ind_tables;
480         priv->ind_tables_n = ind_tables_n;
481         priv->hash_rxqs = hash_rxqs;
482         priv->hash_rxqs_n = hash_rxqs_n;
483         assert(err == 0);
484         return 0;
485 error:
486         if (hash_rxqs != NULL) {
487                 for (i = 0; (i != hash_rxqs_n); ++i) {
488                         struct ibv_qp *qp = (*hash_rxqs)[i].qp;
489
490                         if (qp == NULL)
491                                 continue;
492                         claim_zero(ibv_destroy_qp(qp));
493                 }
494                 rte_free(hash_rxqs);
495         }
496         if (ind_tables != NULL) {
497                 for (j = 0; (j != ind_tables_n); ++j) {
498                         struct ibv_rwq_ind_table *ind_table =
499                                 (*ind_tables)[j];
500
501                         if (ind_table == NULL)
502                                 continue;
503                         claim_zero(ibv_destroy_rwq_ind_table(ind_table));
504                 }
505                 rte_free(ind_tables);
506         }
507         return err;
508 }
509
510 /**
511  * Clean up hash RX queues and indirection table.
512  *
513  * @param priv
514  *   Pointer to private structure.
515  */
516 void
517 priv_destroy_hash_rxqs(struct priv *priv)
518 {
519         unsigned int i;
520
521         DEBUG("destroying %u hash RX queues", priv->hash_rxqs_n);
522         if (priv->hash_rxqs_n == 0) {
523                 assert(priv->hash_rxqs == NULL);
524                 assert(priv->ind_tables == NULL);
525                 return;
526         }
527         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
528                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
529                 unsigned int j, k;
530
531                 assert(hash_rxq->priv == priv);
532                 assert(hash_rxq->qp != NULL);
533                 for (j = 0; (j != RTE_DIM(hash_rxq->mac_flow)); ++j)
534                         for (k = 0; (k != RTE_DIM(hash_rxq->mac_flow[j])); ++k)
535                                 assert(hash_rxq->mac_flow[j][k] == NULL);
536                 claim_zero(ibv_destroy_qp(hash_rxq->qp));
537         }
538         priv->hash_rxqs_n = 0;
539         rte_free(priv->hash_rxqs);
540         priv->hash_rxqs = NULL;
541         for (i = 0; (i != priv->ind_tables_n); ++i) {
542                 struct ibv_rwq_ind_table *ind_table =
543                         (*priv->ind_tables)[i];
544
545                 assert(ind_table != NULL);
546                 claim_zero(ibv_destroy_rwq_ind_table(ind_table));
547         }
548         priv->ind_tables_n = 0;
549         rte_free(priv->ind_tables);
550         priv->ind_tables = NULL;
551 }
552
553 /**
554  * Allocate RX queue elements.
555  *
556  * @param rxq_ctrl
557  *   Pointer to RX queue structure.
558  *
559  * @return
560  *   0 on success, errno value on failure.
561  */
562 int
563 rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl)
564 {
565         const unsigned int sges_n = 1 << rxq_ctrl->rxq.sges_n;
566         unsigned int elts_n = 1 << rxq_ctrl->rxq.elts_n;
567         unsigned int i;
568         int ret = 0;
569
570         /* Iterate on segments. */
571         for (i = 0; (i != elts_n); ++i) {
572                 struct rte_mbuf *buf;
573
574                 buf = rte_pktmbuf_alloc(rxq_ctrl->rxq.mp);
575                 if (buf == NULL) {
576                         ERROR("%p: empty mbuf pool", (void *)rxq_ctrl);
577                         ret = ENOMEM;
578                         goto error;
579                 }
580                 /* Headroom is reserved by rte_pktmbuf_alloc(). */
581                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
582                 /* Buffer is supposed to be empty. */
583                 assert(rte_pktmbuf_data_len(buf) == 0);
584                 assert(rte_pktmbuf_pkt_len(buf) == 0);
585                 assert(!buf->next);
586                 /* Only the first segment keeps headroom. */
587                 if (i % sges_n)
588                         SET_DATA_OFF(buf, 0);
589                 PORT(buf) = rxq_ctrl->rxq.port_id;
590                 DATA_LEN(buf) = rte_pktmbuf_tailroom(buf);
591                 PKT_LEN(buf) = DATA_LEN(buf);
592                 NB_SEGS(buf) = 1;
593                 (*rxq_ctrl->rxq.elts)[i] = buf;
594         }
595         /* If Rx vector is activated. */
596         if (rxq_check_vec_support(&rxq_ctrl->rxq) > 0) {
597                 struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq;
598                 struct rte_mbuf *mbuf_init = &rxq->fake_mbuf;
599                 int j;
600
601                 /* Initialize default rearm_data for vPMD. */
602                 mbuf_init->data_off = RTE_PKTMBUF_HEADROOM;
603                 rte_mbuf_refcnt_set(mbuf_init, 1);
604                 mbuf_init->nb_segs = 1;
605                 mbuf_init->port = rxq->port_id;
606                 /*
607                  * prevent compiler reordering:
608                  * rearm_data covers previous fields.
609                  */
610                 rte_compiler_barrier();
611                 rxq->mbuf_initializer =
612                         *(uint64_t *)&mbuf_init->rearm_data;
613                 /* Padding with a fake mbuf for vectorized Rx. */
614                 for (j = 0; j < MLX5_VPMD_DESCS_PER_LOOP; ++j)
615                         (*rxq->elts)[elts_n + j] = &rxq->fake_mbuf;
616         }
617         DEBUG("%p: allocated and configured %u segments (max %u packets)",
618               (void *)rxq_ctrl, elts_n, elts_n / (1 << rxq_ctrl->rxq.sges_n));
619         assert(ret == 0);
620         return 0;
621 error:
622         elts_n = i;
623         for (i = 0; (i != elts_n); ++i) {
624                 if ((*rxq_ctrl->rxq.elts)[i] != NULL)
625                         rte_pktmbuf_free_seg((*rxq_ctrl->rxq.elts)[i]);
626                 (*rxq_ctrl->rxq.elts)[i] = NULL;
627         }
628         DEBUG("%p: failed, freed everything", (void *)rxq_ctrl);
629         assert(ret > 0);
630         return ret;
631 }
632
633 /**
634  * Free RX queue elements.
635  *
636  * @param rxq_ctrl
637  *   Pointer to RX queue structure.
638  */
639 static void
640 rxq_free_elts(struct mlx5_rxq_ctrl *rxq_ctrl)
641 {
642         struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq;
643         const uint16_t q_n = (1 << rxq->elts_n);
644         const uint16_t q_mask = q_n - 1;
645         uint16_t used = q_n - (rxq->rq_ci - rxq->rq_pi);
646         uint16_t i;
647
648         DEBUG("%p: freeing WRs", (void *)rxq_ctrl);
649         if (rxq->elts == NULL)
650                 return;
651         /**
652          * Some mbuf in the Ring belongs to the application.  They cannot be
653          * freed.
654          */
655         if (rxq_check_vec_support(rxq) > 0) {
656                 for (i = 0; i < used; ++i)
657                         (*rxq->elts)[(rxq->rq_ci + i) & q_mask] = NULL;
658                 rxq->rq_pi = rxq->rq_ci;
659         }
660         for (i = 0; (i != (1u << rxq->elts_n)); ++i) {
661                 if ((*rxq->elts)[i] != NULL)
662                         rte_pktmbuf_free_seg((*rxq->elts)[i]);
663                 (*rxq->elts)[i] = NULL;
664         }
665 }
666
667 /**
668  * Clean up a RX queue.
669  *
670  * Destroy objects, free allocated memory and reset the structure for reuse.
671  *
672  * @param rxq_ctrl
673  *   Pointer to RX queue structure.
674  */
675 void
676 mlx5_rxq_cleanup(struct mlx5_rxq_ctrl *rxq_ctrl)
677 {
678         DEBUG("cleaning up %p", (void *)rxq_ctrl);
679         if (rxq_ctrl->ibv)
680                 mlx5_priv_rxq_ibv_release(rxq_ctrl->priv, rxq_ctrl->ibv);
681         memset(rxq_ctrl, 0, sizeof(*rxq_ctrl));
682 }
683
684 /**
685  *
686  * @param dev
687  *   Pointer to Ethernet device structure.
688  * @param idx
689  *   RX queue index.
690  * @param desc
691  *   Number of descriptors to configure in queue.
692  * @param socket
693  *   NUMA socket on which memory must be allocated.
694  * @param[in] conf
695  *   Thresholds parameters.
696  * @param mp
697  *   Memory pool for buffer allocations.
698  *
699  * @return
700  *   0 on success, negative errno value on failure.
701  */
702 int
703 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
704                     unsigned int socket, const struct rte_eth_rxconf *conf,
705                     struct rte_mempool *mp)
706 {
707         struct priv *priv = dev->data->dev_private;
708         struct mlx5_rxq_data *rxq = (*priv->rxqs)[idx];
709         struct mlx5_rxq_ctrl *rxq_ctrl =
710                 container_of(rxq, struct mlx5_rxq_ctrl, rxq);
711         int ret = 0;
712
713         (void)conf;
714         if (mlx5_is_secondary())
715                 return -E_RTE_SECONDARY;
716         priv_lock(priv);
717         if (!rte_is_power_of_2(desc)) {
718                 desc = 1 << log2above(desc);
719                 WARN("%p: increased number of descriptors in RX queue %u"
720                      " to the next power of two (%d)",
721                      (void *)dev, idx, desc);
722         }
723         DEBUG("%p: configuring queue %u for %u descriptors",
724               (void *)dev, idx, desc);
725         if (idx >= priv->rxqs_n) {
726                 ERROR("%p: queue index out of range (%u >= %u)",
727                       (void *)dev, idx, priv->rxqs_n);
728                 priv_unlock(priv);
729                 return -EOVERFLOW;
730         }
731         if (!mlx5_priv_rxq_releasable(priv, idx)) {
732                 ret = EBUSY;
733                 ERROR("%p: unable to release queue index %u",
734                       (void *)dev, idx);
735                 goto out;
736         }
737         mlx5_priv_rxq_release(priv, idx);
738         rxq_ctrl = mlx5_priv_rxq_new(priv, idx, desc, socket, mp);
739         if (!rxq_ctrl) {
740                 ERROR("%p: unable to allocate queue index %u",
741                       (void *)dev, idx);
742                 ret = ENOMEM;
743                 goto out;
744         }
745         DEBUG("%p: adding RX queue %p to list",
746               (void *)dev, (void *)rxq_ctrl);
747         (*priv->rxqs)[idx] = &rxq_ctrl->rxq;
748 out:
749         priv_unlock(priv);
750         return -ret;
751 }
752
753 /**
754  * DPDK callback to release a RX queue.
755  *
756  * @param dpdk_rxq
757  *   Generic RX queue pointer.
758  */
759 void
760 mlx5_rx_queue_release(void *dpdk_rxq)
761 {
762         struct mlx5_rxq_data *rxq = (struct mlx5_rxq_data *)dpdk_rxq;
763         struct mlx5_rxq_ctrl *rxq_ctrl;
764         struct priv *priv;
765
766         if (mlx5_is_secondary())
767                 return;
768
769         if (rxq == NULL)
770                 return;
771         rxq_ctrl = container_of(rxq, struct mlx5_rxq_ctrl, rxq);
772         priv = rxq_ctrl->priv;
773         priv_lock(priv);
774         if (!mlx5_priv_rxq_releasable(priv, rxq_ctrl->rxq.stats.idx))
775                 rte_panic("Rx queue %p is still used by a flow and cannot be"
776                           " removed\n", (void *)rxq_ctrl);
777         mlx5_priv_rxq_release(priv, rxq_ctrl->rxq.stats.idx);
778         priv_unlock(priv);
779 }
780
781 /**
782  * Allocate queue vector and fill epoll fd list for Rx interrupts.
783  *
784  * @param priv
785  *   Pointer to private structure.
786  *
787  * @return
788  *   0 on success, negative on failure.
789  */
790 int
791 priv_rx_intr_vec_enable(struct priv *priv)
792 {
793         unsigned int i;
794         unsigned int rxqs_n = priv->rxqs_n;
795         unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
796         unsigned int count = 0;
797         struct rte_intr_handle *intr_handle = priv->dev->intr_handle;
798
799         assert(!mlx5_is_secondary());
800         if (!priv->dev->data->dev_conf.intr_conf.rxq)
801                 return 0;
802         priv_rx_intr_vec_disable(priv);
803         intr_handle->intr_vec = malloc(sizeof(intr_handle->intr_vec[rxqs_n]));
804         if (intr_handle->intr_vec == NULL) {
805                 ERROR("failed to allocate memory for interrupt vector,"
806                       " Rx interrupts will not be supported");
807                 return -ENOMEM;
808         }
809         intr_handle->type = RTE_INTR_HANDLE_EXT;
810         for (i = 0; i != n; ++i) {
811                 /* This rxq ibv must not be released in this function. */
812                 struct mlx5_rxq_ibv *rxq_ibv = mlx5_priv_rxq_ibv_get(priv, i);
813                 int fd;
814                 int flags;
815                 int rc;
816
817                 /* Skip queues that cannot request interrupts. */
818                 if (!rxq_ibv || !rxq_ibv->channel) {
819                         /* Use invalid intr_vec[] index to disable entry. */
820                         intr_handle->intr_vec[i] =
821                                 RTE_INTR_VEC_RXTX_OFFSET +
822                                 RTE_MAX_RXTX_INTR_VEC_ID;
823                         continue;
824                 }
825                 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) {
826                         ERROR("too many Rx queues for interrupt vector size"
827                               " (%d), Rx interrupts cannot be enabled",
828                               RTE_MAX_RXTX_INTR_VEC_ID);
829                         priv_rx_intr_vec_disable(priv);
830                         return -1;
831                 }
832                 fd = rxq_ibv->channel->fd;
833                 flags = fcntl(fd, F_GETFL);
834                 rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
835                 if (rc < 0) {
836                         ERROR("failed to make Rx interrupt file descriptor"
837                               " %d non-blocking for queue index %d", fd, i);
838                         priv_rx_intr_vec_disable(priv);
839                         return -1;
840                 }
841                 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count;
842                 intr_handle->efds[count] = fd;
843                 count++;
844         }
845         if (!count)
846                 priv_rx_intr_vec_disable(priv);
847         else
848                 intr_handle->nb_efd = count;
849         return 0;
850 }
851
852 /**
853  * Clean up Rx interrupts handler.
854  *
855  * @param priv
856  *   Pointer to private structure.
857  */
858 void
859 priv_rx_intr_vec_disable(struct priv *priv)
860 {
861         struct rte_intr_handle *intr_handle = priv->dev->intr_handle;
862         unsigned int i;
863         unsigned int rxqs_n = priv->rxqs_n;
864         unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
865
866         if (!priv->dev->data->dev_conf.intr_conf.rxq)
867                 return;
868         for (i = 0; i != n; ++i) {
869                 struct mlx5_rxq_ctrl *rxq_ctrl;
870                 struct mlx5_rxq_data *rxq_data;
871
872                 if (intr_handle->intr_vec[i] == RTE_INTR_VEC_RXTX_OFFSET +
873                     RTE_MAX_RXTX_INTR_VEC_ID)
874                         continue;
875                 /**
876                  * Need to access directly the queue to release the reference
877                  * kept in priv_rx_intr_vec_enable().
878                  */
879                 rxq_data = (*priv->rxqs)[i];
880                 rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
881                 mlx5_priv_rxq_ibv_release(priv, rxq_ctrl->ibv);
882         }
883         rte_intr_free_epoll_fd(intr_handle);
884         free(intr_handle->intr_vec);
885         intr_handle->nb_efd = 0;
886         intr_handle->intr_vec = NULL;
887 }
888
889 /**
890  *  MLX5 CQ notification .
891  *
892  *  @param rxq
893  *     Pointer to receive queue structure.
894  *  @param sq_n_rxq
895  *     Sequence number per receive queue .
896  */
897 static inline void
898 mlx5_arm_cq(struct mlx5_rxq_data *rxq, int sq_n_rxq)
899 {
900         int sq_n = 0;
901         uint32_t doorbell_hi;
902         uint64_t doorbell;
903         void *cq_db_reg = (char *)rxq->cq_uar + MLX5_CQ_DOORBELL;
904
905         sq_n = sq_n_rxq & MLX5_CQ_SQN_MASK;
906         doorbell_hi = sq_n << MLX5_CQ_SQN_OFFSET | (rxq->cq_ci & MLX5_CI_MASK);
907         doorbell = (uint64_t)doorbell_hi << 32;
908         doorbell |=  rxq->cqn;
909         rxq->cq_db[MLX5_CQ_ARM_DB] = rte_cpu_to_be_32(doorbell_hi);
910         rte_wmb();
911         rte_write64(rte_cpu_to_be_64(doorbell), cq_db_reg);
912 }
913
914 /**
915  * DPDK callback for Rx queue interrupt enable.
916  *
917  * @param dev
918  *   Pointer to Ethernet device structure.
919  * @param rx_queue_id
920  *   Rx queue number.
921  *
922  * @return
923  *   0 on success, negative on failure.
924  */
925 int
926 mlx5_rx_intr_enable(struct rte_eth_dev *dev, uint16_t rx_queue_id)
927 {
928         struct priv *priv = mlx5_get_priv(dev);
929         struct mlx5_rxq_data *rxq_data;
930         struct mlx5_rxq_ctrl *rxq_ctrl;
931         int ret = 0;
932
933         priv_lock(priv);
934         rxq_data = (*priv->rxqs)[rx_queue_id];
935         if (!rxq_data) {
936                 ret = EINVAL;
937                 goto exit;
938         }
939         rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
940         if (rxq_ctrl->irq) {
941                 struct mlx5_rxq_ibv *rxq_ibv;
942
943                 rxq_ibv = mlx5_priv_rxq_ibv_get(priv, rx_queue_id);
944                 if (!rxq_ibv) {
945                         ret = EINVAL;
946                         goto exit;
947                 }
948                 mlx5_arm_cq(rxq_data, rxq_data->cq_arm_sn);
949                 mlx5_priv_rxq_ibv_release(priv, rxq_ibv);
950         }
951 exit:
952         priv_unlock(priv);
953         if (ret)
954                 WARN("unable to arm interrupt on rx queue %d", rx_queue_id);
955         return -ret;
956 }
957
958 /**
959  * DPDK callback for Rx queue interrupt disable.
960  *
961  * @param dev
962  *   Pointer to Ethernet device structure.
963  * @param rx_queue_id
964  *   Rx queue number.
965  *
966  * @return
967  *   0 on success, negative on failure.
968  */
969 int
970 mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id)
971 {
972         struct priv *priv = mlx5_get_priv(dev);
973         struct mlx5_rxq_data *rxq_data;
974         struct mlx5_rxq_ctrl *rxq_ctrl;
975         struct mlx5_rxq_ibv *rxq_ibv = NULL;
976         struct ibv_cq *ev_cq;
977         void *ev_ctx;
978         int ret = 0;
979
980         priv_lock(priv);
981         rxq_data = (*priv->rxqs)[rx_queue_id];
982         if (!rxq_data) {
983                 ret = EINVAL;
984                 goto exit;
985         }
986         rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
987         if (!rxq_ctrl->irq)
988                 goto exit;
989         rxq_ibv = mlx5_priv_rxq_ibv_get(priv, rx_queue_id);
990         if (!rxq_ibv) {
991                 ret = EINVAL;
992                 goto exit;
993         }
994         ret = ibv_get_cq_event(rxq_ibv->channel, &ev_cq, &ev_ctx);
995         if (ret || ev_cq != rxq_ibv->cq) {
996                 ret = EINVAL;
997                 goto exit;
998         }
999         rxq_data->cq_arm_sn++;
1000         ibv_ack_cq_events(rxq_ibv->cq, 1);
1001 exit:
1002         if (rxq_ibv)
1003                 mlx5_priv_rxq_ibv_release(priv, rxq_ibv);
1004         priv_unlock(priv);
1005         if (ret)
1006                 WARN("unable to disable interrupt on rx queue %d",
1007                      rx_queue_id);
1008         return -ret;
1009 }
1010
1011 /**
1012  * Create the Rx queue Verbs object.
1013  *
1014  * @param priv
1015  *   Pointer to private structure.
1016  * @param idx
1017  *   Queue index in DPDK Rx queue array
1018  *
1019  * @return
1020  *   The Verbs object initialised if it can be created.
1021  */
1022 struct mlx5_rxq_ibv*
1023 mlx5_priv_rxq_ibv_new(struct priv *priv, uint16_t idx)
1024 {
1025         struct mlx5_rxq_data *rxq_data = (*priv->rxqs)[idx];
1026         struct mlx5_rxq_ctrl *rxq_ctrl =
1027                 container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
1028         struct ibv_wq_attr mod;
1029         union {
1030                 struct ibv_cq_init_attr_ex cq;
1031                 struct ibv_wq_init_attr wq;
1032                 struct ibv_cq_ex cq_attr;
1033         } attr;
1034         unsigned int cqe_n = (1 << rxq_data->elts_n) - 1;
1035         struct mlx5_rxq_ibv *tmpl;
1036         struct mlx5dv_cq cq_info;
1037         struct mlx5dv_rwq rwq;
1038         unsigned int i;
1039         int ret = 0;
1040         struct mlx5dv_obj obj;
1041
1042         assert(rxq_data);
1043         assert(!rxq_ctrl->ibv);
1044         tmpl = rte_calloc_socket(__func__, 1, sizeof(*tmpl), 0,
1045                                  rxq_ctrl->socket);
1046         if (!tmpl) {
1047                 ERROR("%p: cannot allocate verbs resources",
1048                        (void *)rxq_ctrl);
1049                 goto error;
1050         }
1051         tmpl->rxq_ctrl = rxq_ctrl;
1052         /* Use the entire RX mempool as the memory region. */
1053         tmpl->mr = priv_mr_get(priv, rxq_data->mp);
1054         if (!tmpl->mr) {
1055                 tmpl->mr = priv_mr_new(priv, rxq_data->mp);
1056                 if (!tmpl->mr) {
1057                         ERROR("%p: MR creation failure", (void *)rxq_ctrl);
1058                         goto error;
1059                 }
1060         }
1061         if (rxq_ctrl->irq) {
1062                 tmpl->channel = ibv_create_comp_channel(priv->ctx);
1063                 if (!tmpl->channel) {
1064                         ERROR("%p: Comp Channel creation failure",
1065                               (void *)rxq_ctrl);
1066                         goto error;
1067                 }
1068         }
1069         attr.cq = (struct ibv_cq_init_attr_ex){
1070                 .comp_mask = 0,
1071         };
1072         if (priv->cqe_comp) {
1073                 attr.cq.comp_mask |= IBV_CQ_INIT_ATTR_MASK_FLAGS;
1074                 attr.cq.flags |= MLX5DV_CQ_INIT_ATTR_MASK_COMPRESSED_CQE;
1075                 /*
1076                  * For vectorized Rx, it must not be doubled in order to
1077                  * make cq_ci and rq_ci aligned.
1078                  */
1079                 if (rxq_check_vec_support(rxq_data) < 0)
1080                         cqe_n *= 2;
1081         }
1082         tmpl->cq = ibv_create_cq(priv->ctx, cqe_n, NULL, tmpl->channel, 0);
1083         if (tmpl->cq == NULL) {
1084                 ERROR("%p: CQ creation failure", (void *)rxq_ctrl);
1085                 goto error;
1086         }
1087         DEBUG("priv->device_attr.max_qp_wr is %d",
1088               priv->device_attr.orig_attr.max_qp_wr);
1089         DEBUG("priv->device_attr.max_sge is %d",
1090               priv->device_attr.orig_attr.max_sge);
1091         attr.wq = (struct ibv_wq_init_attr){
1092                 .wq_context = NULL, /* Could be useful in the future. */
1093                 .wq_type = IBV_WQT_RQ,
1094                 /* Max number of outstanding WRs. */
1095                 .max_wr = (1 << rxq_data->elts_n) >> rxq_data->sges_n,
1096                 /* Max number of scatter/gather elements in a WR. */
1097                 .max_sge = 1 << rxq_data->sges_n,
1098                 .pd = priv->pd,
1099                 .cq = tmpl->cq,
1100                 .comp_mask =
1101                         IBV_WQ_FLAGS_CVLAN_STRIPPING |
1102                         0,
1103                 .create_flags = (rxq_data->vlan_strip ?
1104                                  IBV_WQ_FLAGS_CVLAN_STRIPPING :
1105                                  0),
1106         };
1107         /* By default, FCS (CRC) is stripped by hardware. */
1108         if (rxq_data->crc_present) {
1109                 attr.wq.create_flags |= IBV_WQ_FLAGS_SCATTER_FCS;
1110                 attr.wq.comp_mask |= IBV_WQ_INIT_ATTR_FLAGS;
1111         }
1112 #ifdef HAVE_IBV_WQ_FLAG_RX_END_PADDING
1113         if (priv->hw_padding) {
1114                 attr.wq.create_flags |= IBV_WQ_FLAG_RX_END_PADDING;
1115                 attr.wq.comp_mask |= IBV_WQ_INIT_ATTR_FLAGS;
1116         }
1117 #endif
1118         tmpl->wq = ibv_create_wq(priv->ctx, &attr.wq);
1119         if (tmpl->wq == NULL) {
1120                 ERROR("%p: WQ creation failure", (void *)rxq_ctrl);
1121                 goto error;
1122         }
1123         /*
1124          * Make sure number of WRs*SGEs match expectations since a queue
1125          * cannot allocate more than "desc" buffers.
1126          */
1127         if (((int)attr.wq.max_wr !=
1128              ((1 << rxq_data->elts_n) >> rxq_data->sges_n)) ||
1129             ((int)attr.wq.max_sge != (1 << rxq_data->sges_n))) {
1130                 ERROR("%p: requested %u*%u but got %u*%u WRs*SGEs",
1131                       (void *)rxq_ctrl,
1132                       ((1 << rxq_data->elts_n) >> rxq_data->sges_n),
1133                       (1 << rxq_data->sges_n),
1134                       attr.wq.max_wr, attr.wq.max_sge);
1135                 goto error;
1136         }
1137         /* Change queue state to ready. */
1138         mod = (struct ibv_wq_attr){
1139                 .attr_mask = IBV_WQ_ATTR_STATE,
1140                 .wq_state = IBV_WQS_RDY,
1141         };
1142         ret = ibv_modify_wq(tmpl->wq, &mod);
1143         if (ret) {
1144                 ERROR("%p: WQ state to IBV_WQS_RDY failed",
1145                       (void *)rxq_ctrl);
1146                 goto error;
1147         }
1148         obj.cq.in = tmpl->cq;
1149         obj.cq.out = &cq_info;
1150         obj.rwq.in = tmpl->wq;
1151         obj.rwq.out = &rwq;
1152         ret = mlx5dv_init_obj(&obj, MLX5DV_OBJ_CQ | MLX5DV_OBJ_RWQ);
1153         if (ret != 0)
1154                 goto error;
1155         if (cq_info.cqe_size != RTE_CACHE_LINE_SIZE) {
1156                 ERROR("Wrong MLX5_CQE_SIZE environment variable value: "
1157                       "it should be set to %u", RTE_CACHE_LINE_SIZE);
1158                 goto error;
1159         }
1160         /* Fill the rings. */
1161         rxq_data->wqes = (volatile struct mlx5_wqe_data_seg (*)[])
1162                 (uintptr_t)rwq.buf;
1163         for (i = 0; (i != (unsigned int)(1 << rxq_data->elts_n)); ++i) {
1164                 struct rte_mbuf *buf = (*rxq_data->elts)[i];
1165                 volatile struct mlx5_wqe_data_seg *scat = &(*rxq_data->wqes)[i];
1166
1167                 /* scat->addr must be able to store a pointer. */
1168                 assert(sizeof(scat->addr) >= sizeof(uintptr_t));
1169                 *scat = (struct mlx5_wqe_data_seg){
1170                         .addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(buf,
1171                                                                   uintptr_t)),
1172                         .byte_count = rte_cpu_to_be_32(DATA_LEN(buf)),
1173                         .lkey = tmpl->mr->lkey,
1174                 };
1175         }
1176         rxq_data->rq_db = rwq.dbrec;
1177         rxq_data->cqe_n = log2above(cq_info.cqe_cnt);
1178         rxq_data->cq_ci = 0;
1179         rxq_data->rq_ci = 0;
1180         rxq_data->rq_pi = 0;
1181         rxq_data->zip = (struct rxq_zip){
1182                 .ai = 0,
1183         };
1184         rxq_data->cq_db = cq_info.dbrec;
1185         rxq_data->cqes = (volatile struct mlx5_cqe (*)[])(uintptr_t)cq_info.buf;
1186         /* Update doorbell counter. */
1187         rxq_data->rq_ci = (1 << rxq_data->elts_n) >> rxq_data->sges_n;
1188         rte_wmb();
1189         *rxq_data->rq_db = rte_cpu_to_be_32(rxq_data->rq_ci);
1190         DEBUG("%p: rxq updated with %p", (void *)rxq_ctrl, (void *)&tmpl);
1191         rte_atomic32_inc(&tmpl->refcnt);
1192         DEBUG("%p: Verbs Rx queue %p: refcnt %d", (void *)priv,
1193               (void *)tmpl, rte_atomic32_read(&tmpl->refcnt));
1194         LIST_INSERT_HEAD(&priv->rxqsibv, tmpl, next);
1195         return tmpl;
1196 error:
1197         if (tmpl->wq)
1198                 claim_zero(ibv_destroy_wq(tmpl->wq));
1199         if (tmpl->cq)
1200                 claim_zero(ibv_destroy_cq(tmpl->cq));
1201         if (tmpl->channel)
1202                 claim_zero(ibv_destroy_comp_channel(tmpl->channel));
1203         if (tmpl->mr)
1204                 priv_mr_release(priv, tmpl->mr);
1205         return NULL;
1206 }
1207
1208 /**
1209  * Get an Rx queue Verbs object.
1210  *
1211  * @param priv
1212  *   Pointer to private structure.
1213  * @param idx
1214  *   Queue index in DPDK Rx queue array
1215  *
1216  * @return
1217  *   The Verbs object if it exists.
1218  */
1219 struct mlx5_rxq_ibv*
1220 mlx5_priv_rxq_ibv_get(struct priv *priv, uint16_t idx)
1221 {
1222         struct mlx5_rxq_data *rxq_data = (*priv->rxqs)[idx];
1223         struct mlx5_rxq_ctrl *rxq_ctrl;
1224
1225         if (idx >= priv->rxqs_n)
1226                 return NULL;
1227         if (!rxq_data)
1228                 return NULL;
1229         rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
1230         if (rxq_ctrl->ibv) {
1231                 priv_mr_get(priv, rxq_data->mp);
1232                 rte_atomic32_inc(&rxq_ctrl->ibv->refcnt);
1233                 DEBUG("%p: Verbs Rx queue %p: refcnt %d", (void *)priv,
1234                       (void *)rxq_ctrl->ibv,
1235                       rte_atomic32_read(&rxq_ctrl->ibv->refcnt));
1236         }
1237         return rxq_ctrl->ibv;
1238 }
1239
1240 /**
1241  * Release an Rx verbs queue object.
1242  *
1243  * @param priv
1244  *   Pointer to private structure.
1245  * @param rxq_ibv
1246  *   Verbs Rx queue object.
1247  *
1248  * @return
1249  *   0 on success, errno value on failure.
1250  */
1251 int
1252 mlx5_priv_rxq_ibv_release(struct priv *priv, struct mlx5_rxq_ibv *rxq_ibv)
1253 {
1254         int ret;
1255
1256         assert(rxq_ibv);
1257         assert(rxq_ibv->wq);
1258         assert(rxq_ibv->cq);
1259         assert(rxq_ibv->mr);
1260         ret = priv_mr_release(priv, rxq_ibv->mr);
1261         if (!ret)
1262                 rxq_ibv->mr = NULL;
1263         DEBUG("%p: Verbs Rx queue %p: refcnt %d", (void *)priv,
1264               (void *)rxq_ibv, rte_atomic32_read(&rxq_ibv->refcnt));
1265         if (rte_atomic32_dec_and_test(&rxq_ibv->refcnt)) {
1266                 rxq_free_elts(rxq_ibv->rxq_ctrl);
1267                 claim_zero(ibv_destroy_wq(rxq_ibv->wq));
1268                 claim_zero(ibv_destroy_cq(rxq_ibv->cq));
1269                 if (rxq_ibv->channel)
1270                         claim_zero(ibv_destroy_comp_channel(rxq_ibv->channel));
1271                 LIST_REMOVE(rxq_ibv, next);
1272                 rte_free(rxq_ibv);
1273                 return 0;
1274         }
1275         return EBUSY;
1276 }
1277
1278 /**
1279  * Verify the Verbs Rx queue list is empty
1280  *
1281  * @param priv
1282  *  Pointer to private structure.
1283  *
1284  * @return the number of object not released.
1285  */
1286 int
1287 mlx5_priv_rxq_ibv_verify(struct priv *priv)
1288 {
1289         int ret = 0;
1290         struct mlx5_rxq_ibv *rxq_ibv;
1291
1292         LIST_FOREACH(rxq_ibv, &priv->rxqsibv, next) {
1293                 DEBUG("%p: Verbs Rx queue %p still referenced", (void *)priv,
1294                       (void *)rxq_ibv);
1295                 ++ret;
1296         }
1297         return ret;
1298 }
1299
1300 /**
1301  * Return true if a single reference exists on the object.
1302  *
1303  * @param priv
1304  *   Pointer to private structure.
1305  * @param rxq_ibv
1306  *   Verbs Rx queue object.
1307  */
1308 int
1309 mlx5_priv_rxq_ibv_releasable(struct priv *priv, struct mlx5_rxq_ibv *rxq_ibv)
1310 {
1311         (void)priv;
1312         assert(rxq_ibv);
1313         return (rte_atomic32_read(&rxq_ibv->refcnt) == 1);
1314 }
1315
1316 /**
1317  * Create a DPDK Rx queue.
1318  *
1319  * @param priv
1320  *   Pointer to private structure.
1321  * @param idx
1322  *   TX queue index.
1323  * @param desc
1324  *   Number of descriptors to configure in queue.
1325  * @param socket
1326  *   NUMA socket on which memory must be allocated.
1327  *
1328  * @return
1329  *   A DPDK queue object on success.
1330  */
1331 struct mlx5_rxq_ctrl*
1332 mlx5_priv_rxq_new(struct priv *priv, uint16_t idx, uint16_t desc,
1333                   unsigned int socket, struct rte_mempool *mp)
1334 {
1335         struct rte_eth_dev *dev = priv->dev;
1336         struct mlx5_rxq_ctrl *tmpl;
1337         const uint16_t desc_n =
1338                 desc + priv->rx_vec_en * MLX5_VPMD_DESCS_PER_LOOP;
1339         unsigned int mb_len = rte_pktmbuf_data_room_size(mp);
1340
1341         tmpl = rte_calloc_socket("RXQ", 1,
1342                                  sizeof(*tmpl) +
1343                                  desc_n * sizeof(struct rte_mbuf *),
1344                                  0, socket);
1345         if (!tmpl)
1346                 return NULL;
1347         if (priv->dev->data->dev_conf.intr_conf.rxq)
1348                 tmpl->irq = 1;
1349         /* Enable scattered packets support for this queue if necessary. */
1350         assert(mb_len >= RTE_PKTMBUF_HEADROOM);
1351         if (dev->data->dev_conf.rxmode.max_rx_pkt_len <=
1352             (mb_len - RTE_PKTMBUF_HEADROOM)) {
1353                 tmpl->rxq.sges_n = 0;
1354         } else if (dev->data->dev_conf.rxmode.enable_scatter) {
1355                 unsigned int size =
1356                         RTE_PKTMBUF_HEADROOM +
1357                         dev->data->dev_conf.rxmode.max_rx_pkt_len;
1358                 unsigned int sges_n;
1359
1360                 /*
1361                  * Determine the number of SGEs needed for a full packet
1362                  * and round it to the next power of two.
1363                  */
1364                 sges_n = log2above((size / mb_len) + !!(size % mb_len));
1365                 tmpl->rxq.sges_n = sges_n;
1366                 /* Make sure rxq.sges_n did not overflow. */
1367                 size = mb_len * (1 << tmpl->rxq.sges_n);
1368                 size -= RTE_PKTMBUF_HEADROOM;
1369                 if (size < dev->data->dev_conf.rxmode.max_rx_pkt_len) {
1370                         ERROR("%p: too many SGEs (%u) needed to handle"
1371                               " requested maximum packet size %u",
1372                               (void *)dev,
1373                               1 << sges_n,
1374                               dev->data->dev_conf.rxmode.max_rx_pkt_len);
1375                         goto error;
1376                 }
1377         } else {
1378                 WARN("%p: the requested maximum Rx packet size (%u) is"
1379                      " larger than a single mbuf (%u) and scattered"
1380                      " mode has not been requested",
1381                      (void *)dev,
1382                      dev->data->dev_conf.rxmode.max_rx_pkt_len,
1383                      mb_len - RTE_PKTMBUF_HEADROOM);
1384         }
1385         DEBUG("%p: maximum number of segments per packet: %u",
1386               (void *)dev, 1 << tmpl->rxq.sges_n);
1387         if (desc % (1 << tmpl->rxq.sges_n)) {
1388                 ERROR("%p: number of RX queue descriptors (%u) is not a"
1389                       " multiple of SGEs per packet (%u)",
1390                       (void *)dev,
1391                       desc,
1392                       1 << tmpl->rxq.sges_n);
1393                 goto error;
1394         }
1395         /* Toggle RX checksum offload if hardware supports it. */
1396         if (priv->hw_csum)
1397                 tmpl->rxq.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1398         if (priv->hw_csum_l2tun)
1399                 tmpl->rxq.csum_l2tun =
1400                         !!dev->data->dev_conf.rxmode.hw_ip_checksum;
1401         /* Configure VLAN stripping. */
1402         tmpl->rxq.vlan_strip = (priv->hw_vlan_strip &&
1403                                !!dev->data->dev_conf.rxmode.hw_vlan_strip);
1404         /* By default, FCS (CRC) is stripped by hardware. */
1405         if (dev->data->dev_conf.rxmode.hw_strip_crc) {
1406                 tmpl->rxq.crc_present = 0;
1407         } else if (priv->hw_fcs_strip) {
1408                 tmpl->rxq.crc_present = 1;
1409         } else {
1410                 WARN("%p: CRC stripping has been disabled but will still"
1411                      " be performed by hardware, make sure MLNX_OFED and"
1412                      " firmware are up to date",
1413                      (void *)dev);
1414                 tmpl->rxq.crc_present = 0;
1415         }
1416         DEBUG("%p: CRC stripping is %s, %u bytes will be subtracted from"
1417               " incoming frames to hide it",
1418               (void *)dev,
1419               tmpl->rxq.crc_present ? "disabled" : "enabled",
1420               tmpl->rxq.crc_present << 2);
1421         /* Save port ID. */
1422         tmpl->rxq.rss_hash = priv->rxqs_n > 1;
1423         tmpl->rxq.port_id = dev->data->port_id;
1424         tmpl->priv = priv;
1425         tmpl->rxq.mp = mp;
1426         tmpl->rxq.stats.idx = idx;
1427         tmpl->rxq.elts_n = log2above(desc);
1428         tmpl->rxq.elts =
1429                 (struct rte_mbuf *(*)[1 << tmpl->rxq.elts_n])(tmpl + 1);
1430         rte_atomic32_inc(&tmpl->refcnt);
1431         DEBUG("%p: Rx queue %p: refcnt %d", (void *)priv,
1432               (void *)tmpl, rte_atomic32_read(&tmpl->refcnt));
1433         LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next);
1434         return tmpl;
1435 error:
1436         rte_free(tmpl);
1437         return NULL;
1438 }
1439
1440 /**
1441  * Get a Rx queue.
1442  *
1443  * @param priv
1444  *   Pointer to private structure.
1445  * @param idx
1446  *   TX queue index.
1447  *
1448  * @return
1449  *   A pointer to the queue if it exists.
1450  */
1451 struct mlx5_rxq_ctrl*
1452 mlx5_priv_rxq_get(struct priv *priv, uint16_t idx)
1453 {
1454         struct mlx5_rxq_ctrl *rxq_ctrl = NULL;
1455
1456         if ((*priv->rxqs)[idx]) {
1457                 rxq_ctrl = container_of((*priv->rxqs)[idx],
1458                                         struct mlx5_rxq_ctrl,
1459                                         rxq);
1460
1461                 mlx5_priv_rxq_ibv_get(priv, idx);
1462                 rte_atomic32_inc(&rxq_ctrl->refcnt);
1463                 DEBUG("%p: Rx queue %p: refcnt %d", (void *)priv,
1464                       (void *)rxq_ctrl, rte_atomic32_read(&rxq_ctrl->refcnt));
1465         }
1466         return rxq_ctrl;
1467 }
1468
1469 /**
1470  * Release a Rx queue.
1471  *
1472  * @param priv
1473  *   Pointer to private structure.
1474  * @param idx
1475  *   TX queue index.
1476  *
1477  * @return
1478  *   0 on success, errno value on failure.
1479  */
1480 int
1481 mlx5_priv_rxq_release(struct priv *priv, uint16_t idx)
1482 {
1483         struct mlx5_rxq_ctrl *rxq_ctrl;
1484
1485         if (!(*priv->rxqs)[idx])
1486                 return 0;
1487         rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq);
1488         assert(rxq_ctrl->priv);
1489         if (rxq_ctrl->ibv) {
1490                 int ret;
1491
1492                 ret = mlx5_priv_rxq_ibv_release(rxq_ctrl->priv, rxq_ctrl->ibv);
1493                 if (!ret)
1494                         rxq_ctrl->ibv = NULL;
1495         }
1496         DEBUG("%p: Rx queue %p: refcnt %d", (void *)priv,
1497               (void *)rxq_ctrl, rte_atomic32_read(&rxq_ctrl->refcnt));
1498         if (rte_atomic32_dec_and_test(&rxq_ctrl->refcnt)) {
1499                 LIST_REMOVE(rxq_ctrl, next);
1500                 rte_free(rxq_ctrl);
1501                 (*priv->rxqs)[idx] = NULL;
1502                 return 0;
1503         }
1504         return EBUSY;
1505 }
1506
1507 /**
1508  * Verify if the queue can be released.
1509  *
1510  * @param priv
1511  *   Pointer to private structure.
1512  * @param idx
1513  *   TX queue index.
1514  *
1515  * @return
1516  *   1 if the queue can be released.
1517  */
1518 int
1519 mlx5_priv_rxq_releasable(struct priv *priv, uint16_t idx)
1520 {
1521         struct mlx5_rxq_ctrl *rxq_ctrl;
1522
1523         if (!(*priv->rxqs)[idx])
1524                 return -1;
1525         rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq);
1526         return (rte_atomic32_read(&rxq_ctrl->refcnt) == 1);
1527 }
1528
1529 /**
1530  * Verify the Rx Queue list is empty
1531  *
1532  * @param priv
1533  *  Pointer to private structure.
1534  *
1535  * @return the number of object not released.
1536  */
1537 int
1538 mlx5_priv_rxq_verify(struct priv *priv)
1539 {
1540         struct mlx5_rxq_ctrl *rxq_ctrl;
1541         int ret = 0;
1542
1543         LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) {
1544                 DEBUG("%p: Rx Queue %p still referenced", (void *)priv,
1545                       (void *)rxq_ctrl);
1546                 ++ret;
1547         }
1548         return ret;
1549 }
1550
1551 /**
1552  * Create an indirection table.
1553  *
1554  * @param priv
1555  *   Pointer to private structure.
1556  * @param queues
1557  *   Queues entering in the indirection table.
1558  * @param queues_n
1559  *   Number of queues in the array.
1560  *
1561  * @return
1562  *   A new indirection table.
1563  */
1564 struct mlx5_ind_table_ibv*
1565 mlx5_priv_ind_table_ibv_new(struct priv *priv, uint16_t queues[],
1566                             uint16_t queues_n)
1567 {
1568         struct mlx5_ind_table_ibv *ind_tbl;
1569         const unsigned int wq_n = rte_is_power_of_2(queues_n) ?
1570                 log2above(queues_n) :
1571                 priv->ind_table_max_size;
1572         struct ibv_wq *wq[1 << wq_n];
1573         unsigned int i;
1574         unsigned int j;
1575
1576         ind_tbl = rte_calloc(__func__, 1, sizeof(*ind_tbl) +
1577                              queues_n * sizeof(uint16_t), 0);
1578         if (!ind_tbl)
1579                 return NULL;
1580         for (i = 0; i != queues_n; ++i) {
1581                 struct mlx5_rxq_ctrl *rxq =
1582                         mlx5_priv_rxq_get(priv, queues[i]);
1583
1584                 if (!rxq)
1585                         goto error;
1586                 wq[i] = rxq->ibv->wq;
1587                 ind_tbl->queues[i] = queues[i];
1588         }
1589         ind_tbl->queues_n = queues_n;
1590         /* Finalise indirection table. */
1591         for (j = 0; i != (unsigned int)(1 << wq_n); ++i, ++j)
1592                 wq[i] = wq[j];
1593         ind_tbl->ind_table = ibv_create_rwq_ind_table(
1594                 priv->ctx,
1595                 &(struct ibv_rwq_ind_table_init_attr){
1596                         .log_ind_tbl_size = wq_n,
1597                         .ind_tbl = wq,
1598                         .comp_mask = 0,
1599                 });
1600         if (!ind_tbl->ind_table)
1601                 goto error;
1602         rte_atomic32_inc(&ind_tbl->refcnt);
1603         LIST_INSERT_HEAD(&priv->ind_tbls, ind_tbl, next);
1604         DEBUG("%p: Indirection table %p: refcnt %d", (void *)priv,
1605               (void *)ind_tbl, rte_atomic32_read(&ind_tbl->refcnt));
1606         return ind_tbl;
1607 error:
1608         rte_free(ind_tbl);
1609         DEBUG("%p cannot create indirection table", (void *)priv);
1610         return NULL;
1611 }
1612
1613 /**
1614  * Get an indirection table.
1615  *
1616  * @param priv
1617  *   Pointer to private structure.
1618  * @param queues
1619  *   Queues entering in the indirection table.
1620  * @param queues_n
1621  *   Number of queues in the array.
1622  *
1623  * @return
1624  *   An indirection table if found.
1625  */
1626 struct mlx5_ind_table_ibv*
1627 mlx5_priv_ind_table_ibv_get(struct priv *priv, uint16_t queues[],
1628                             uint16_t queues_n)
1629 {
1630         struct mlx5_ind_table_ibv *ind_tbl;
1631
1632         LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) {
1633                 if ((ind_tbl->queues_n == queues_n) &&
1634                     (memcmp(ind_tbl->queues, queues,
1635                             ind_tbl->queues_n * sizeof(ind_tbl->queues[0]))
1636                      == 0))
1637                         break;
1638         }
1639         if (ind_tbl) {
1640                 unsigned int i;
1641
1642                 rte_atomic32_inc(&ind_tbl->refcnt);
1643                 DEBUG("%p: Indirection table %p: refcnt %d", (void *)priv,
1644                       (void *)ind_tbl, rte_atomic32_read(&ind_tbl->refcnt));
1645                 for (i = 0; i != ind_tbl->queues_n; ++i)
1646                         mlx5_priv_rxq_get(priv, ind_tbl->queues[i]);
1647         }
1648         return ind_tbl;
1649 }
1650
1651 /**
1652  * Release an indirection table.
1653  *
1654  * @param priv
1655  *   Pointer to private structure.
1656  * @param ind_table
1657  *   Indirection table to release.
1658  *
1659  * @return
1660  *   0 on success, errno value on failure.
1661  */
1662 int
1663 mlx5_priv_ind_table_ibv_release(struct priv *priv,
1664                                 struct mlx5_ind_table_ibv *ind_tbl)
1665 {
1666         unsigned int i;
1667
1668         DEBUG("%p: Indirection table %p: refcnt %d", (void *)priv,
1669               (void *)ind_tbl, rte_atomic32_read(&ind_tbl->refcnt));
1670         if (rte_atomic32_dec_and_test(&ind_tbl->refcnt))
1671                 claim_zero(ibv_destroy_rwq_ind_table(ind_tbl->ind_table));
1672         for (i = 0; i != ind_tbl->queues_n; ++i)
1673                 claim_nonzero(mlx5_priv_rxq_release(priv, ind_tbl->queues[i]));
1674         if (!rte_atomic32_read(&ind_tbl->refcnt)) {
1675                 LIST_REMOVE(ind_tbl, next);
1676                 rte_free(ind_tbl);
1677                 return 0;
1678         }
1679         return EBUSY;
1680 }
1681
1682 /**
1683  * Verify the Rx Queue list is empty
1684  *
1685  * @param priv
1686  *  Pointer to private structure.
1687  *
1688  * @return the number of object not released.
1689  */
1690 int
1691 mlx5_priv_ind_table_ibv_verify(struct priv *priv)
1692 {
1693         struct mlx5_ind_table_ibv *ind_tbl;
1694         int ret = 0;
1695
1696         LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) {
1697                 DEBUG("%p: Verbs indirection table %p still referenced",
1698                       (void *)priv, (void *)ind_tbl);
1699                 ++ret;
1700         }
1701         return ret;
1702 }
1703
1704 /**
1705  * Create an Rx Hash queue.
1706  *
1707  * @param priv
1708  *   Pointer to private structure.
1709  * @param rss_key
1710  *   RSS key for the Rx hash queue.
1711  * @param rss_key_len
1712  *   RSS key length.
1713  * @param hash_fields
1714  *   Verbs protocol hash field to make the RSS on.
1715  * @param queues
1716  *   Queues entering in hash queue.
1717  * @param queues_n
1718  *   Number of queues.
1719  *
1720  * @return
1721  *   An hash Rx queue on success.
1722  */
1723 struct mlx5_hrxq*
1724 mlx5_priv_hrxq_new(struct priv *priv, uint8_t *rss_key, uint8_t rss_key_len,
1725                    uint64_t hash_fields, uint16_t queues[], uint16_t queues_n)
1726 {
1727         struct mlx5_hrxq *hrxq;
1728         struct mlx5_ind_table_ibv *ind_tbl;
1729         struct ibv_qp *qp;
1730
1731         ind_tbl = mlx5_priv_ind_table_ibv_get(priv, queues, queues_n);
1732         if (!ind_tbl)
1733                 ind_tbl = mlx5_priv_ind_table_ibv_new(priv, queues, queues_n);
1734         if (!ind_tbl)
1735                 return NULL;
1736         qp = ibv_create_qp_ex(
1737                 priv->ctx,
1738                 &(struct ibv_qp_init_attr_ex){
1739                         .qp_type = IBV_QPT_RAW_PACKET,
1740                         .comp_mask =
1741                                 IBV_QP_INIT_ATTR_PD |
1742                                 IBV_QP_INIT_ATTR_IND_TABLE |
1743                                 IBV_QP_INIT_ATTR_RX_HASH,
1744                         .rx_hash_conf = (struct ibv_rx_hash_conf){
1745                                 .rx_hash_function = IBV_RX_HASH_FUNC_TOEPLITZ,
1746                                 .rx_hash_key_len = rss_key_len,
1747                                 .rx_hash_key = rss_key,
1748                                 .rx_hash_fields_mask = hash_fields,
1749                         },
1750                         .rwq_ind_tbl = ind_tbl->ind_table,
1751                         .pd = priv->pd,
1752                 });
1753         if (!qp)
1754                 goto error;
1755         hrxq = rte_calloc(__func__, 1, sizeof(*hrxq) + rss_key_len, 0);
1756         if (!hrxq)
1757                 goto error;
1758         hrxq->ind_table = ind_tbl;
1759         hrxq->qp = qp;
1760         hrxq->rss_key_len = rss_key_len;
1761         hrxq->hash_fields = hash_fields;
1762         memcpy(hrxq->rss_key, rss_key, rss_key_len);
1763         rte_atomic32_inc(&hrxq->refcnt);
1764         LIST_INSERT_HEAD(&priv->hrxqs, hrxq, next);
1765         DEBUG("%p: Hash Rx queue %p: refcnt %d", (void *)priv,
1766               (void *)hrxq, rte_atomic32_read(&hrxq->refcnt));
1767         return hrxq;
1768 error:
1769         mlx5_priv_ind_table_ibv_release(priv, ind_tbl);
1770         if (qp)
1771                 claim_zero(ibv_destroy_qp(qp));
1772         return NULL;
1773 }
1774
1775 /**
1776  * Get an Rx Hash queue.
1777  *
1778  * @param priv
1779  *   Pointer to private structure.
1780  * @param rss_conf
1781  *   RSS configuration for the Rx hash queue.
1782  * @param queues
1783  *   Queues entering in hash queue.
1784  * @param queues_n
1785  *   Number of queues.
1786  *
1787  * @return
1788  *   An hash Rx queue on success.
1789  */
1790 struct mlx5_hrxq*
1791 mlx5_priv_hrxq_get(struct priv *priv, uint8_t *rss_key, uint8_t rss_key_len,
1792                    uint64_t hash_fields, uint16_t queues[], uint16_t queues_n)
1793 {
1794         struct mlx5_hrxq *hrxq;
1795
1796         LIST_FOREACH(hrxq, &priv->hrxqs, next) {
1797                 struct mlx5_ind_table_ibv *ind_tbl;
1798
1799                 if (hrxq->rss_key_len != rss_key_len)
1800                         continue;
1801                 if (memcmp(hrxq->rss_key, rss_key, rss_key_len))
1802                         continue;
1803                 if (hrxq->hash_fields != hash_fields)
1804                         continue;
1805                 ind_tbl = mlx5_priv_ind_table_ibv_get(priv, queues, queues_n);
1806                 if (!ind_tbl)
1807                         continue;
1808                 if (ind_tbl != hrxq->ind_table) {
1809                         mlx5_priv_ind_table_ibv_release(priv, ind_tbl);
1810                         continue;
1811                 }
1812                 rte_atomic32_inc(&hrxq->refcnt);
1813                 DEBUG("%p: Hash Rx queue %p: refcnt %d", (void *)priv,
1814                       (void *)hrxq, rte_atomic32_read(&hrxq->refcnt));
1815                 return hrxq;
1816         }
1817         return NULL;
1818 }
1819
1820 /**
1821  * Release the hash Rx queue.
1822  *
1823  * @param priv
1824  *   Pointer to private structure.
1825  * @param hrxq
1826  *   Pointer to Hash Rx queue to release.
1827  *
1828  * @return
1829  *   0 on success, errno value on failure.
1830  */
1831 int
1832 mlx5_priv_hrxq_release(struct priv *priv, struct mlx5_hrxq *hrxq)
1833 {
1834         DEBUG("%p: Hash Rx queue %p: refcnt %d", (void *)priv,
1835               (void *)hrxq, rte_atomic32_read(&hrxq->refcnt));
1836         if (rte_atomic32_dec_and_test(&hrxq->refcnt)) {
1837                 claim_zero(ibv_destroy_qp(hrxq->qp));
1838                 mlx5_priv_ind_table_ibv_release(priv, hrxq->ind_table);
1839                 LIST_REMOVE(hrxq, next);
1840                 rte_free(hrxq);
1841                 return 0;
1842         }
1843         claim_nonzero(mlx5_priv_ind_table_ibv_release(priv, hrxq->ind_table));
1844         return EBUSY;
1845 }
1846
1847 /**
1848  * Verify the Rx Queue list is empty
1849  *
1850  * @param priv
1851  *  Pointer to private structure.
1852  *
1853  * @return the number of object not released.
1854  */
1855 int
1856 mlx5_priv_hrxq_ibv_verify(struct priv *priv)
1857 {
1858         struct mlx5_hrxq *hrxq;
1859         int ret = 0;
1860
1861         LIST_FOREACH(hrxq, &priv->hrxqs, next) {
1862                 DEBUG("%p: Verbs Hash Rx queue %p still referenced",
1863                       (void *)priv, (void *)hrxq);
1864                 ++ret;
1865         }
1866         return ret;
1867 }