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