mlx5: get rid of the WR structure in Rx queue elements
[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_autoconf.h"
64 #include "mlx5_rxtx.h"
65 #include "mlx5_utils.h"
66 #include "mlx5_defs.h"
67
68 /**
69  * Allocate RX queue elements with scattered packets support.
70  *
71  * @param rxq
72  *   Pointer to RX queue structure.
73  * @param elts_n
74  *   Number of elements to allocate.
75  * @param[in] pool
76  *   If not NULL, fetch buffers from this array instead of allocating them
77  *   with rte_pktmbuf_alloc().
78  *
79  * @return
80  *   0 on success, errno value on failure.
81  */
82 static int
83 rxq_alloc_elts_sp(struct rxq *rxq, unsigned int elts_n,
84                   struct rte_mbuf **pool)
85 {
86         unsigned int i;
87         struct rxq_elt_sp (*elts)[elts_n] =
88                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
89                                   rxq->socket);
90         int ret = 0;
91
92         if (elts == NULL) {
93                 ERROR("%p: can't allocate packets array", (void *)rxq);
94                 ret = ENOMEM;
95                 goto error;
96         }
97         /* For each WR (packet). */
98         for (i = 0; (i != elts_n); ++i) {
99                 unsigned int j;
100                 struct rxq_elt_sp *elt = &(*elts)[i];
101                 struct ibv_sge (*sges)[RTE_DIM(elt->sges)] = &elt->sges;
102
103                 /* These two arrays must have the same size. */
104                 assert(RTE_DIM(elt->sges) == RTE_DIM(elt->bufs));
105                 /* For each SGE (segment). */
106                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
107                         struct ibv_sge *sge = &(*sges)[j];
108                         struct rte_mbuf *buf;
109
110                         if (pool != NULL) {
111                                 buf = *(pool++);
112                                 assert(buf != NULL);
113                                 rte_pktmbuf_reset(buf);
114                         } else
115                                 buf = rte_pktmbuf_alloc(rxq->mp);
116                         if (buf == NULL) {
117                                 assert(pool == NULL);
118                                 ERROR("%p: empty mbuf pool", (void *)rxq);
119                                 ret = ENOMEM;
120                                 goto error;
121                         }
122                         elt->bufs[j] = buf;
123                         /* Headroom is reserved by rte_pktmbuf_alloc(). */
124                         assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
125                         /* Buffer is supposed to be empty. */
126                         assert(rte_pktmbuf_data_len(buf) == 0);
127                         assert(rte_pktmbuf_pkt_len(buf) == 0);
128                         /* sge->addr must be able to store a pointer. */
129                         assert(sizeof(sge->addr) >= sizeof(uintptr_t));
130                         if (j == 0) {
131                                 /* The first SGE keeps its headroom. */
132                                 sge->addr = rte_pktmbuf_mtod(buf, uintptr_t);
133                                 sge->length = (buf->buf_len -
134                                                RTE_PKTMBUF_HEADROOM);
135                         } else {
136                                 /* Subsequent SGEs lose theirs. */
137                                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
138                                 SET_DATA_OFF(buf, 0);
139                                 sge->addr = (uintptr_t)buf->buf_addr;
140                                 sge->length = buf->buf_len;
141                         }
142                         sge->lkey = rxq->mr->lkey;
143                         /* Redundant check for tailroom. */
144                         assert(sge->length == rte_pktmbuf_tailroom(buf));
145                 }
146         }
147         DEBUG("%p: allocated and configured %u WRs (%zu segments)",
148               (void *)rxq, elts_n, (elts_n * RTE_DIM((*elts)[0].sges)));
149         rxq->elts_n = elts_n;
150         rxq->elts_head = 0;
151         rxq->elts.sp = elts;
152         assert(ret == 0);
153         return 0;
154 error:
155         if (elts != NULL) {
156                 assert(pool == NULL);
157                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
158                         unsigned int j;
159                         struct rxq_elt_sp *elt = &(*elts)[i];
160
161                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
162                                 struct rte_mbuf *buf = elt->bufs[j];
163
164                                 if (buf != NULL)
165                                         rte_pktmbuf_free_seg(buf);
166                         }
167                 }
168                 rte_free(elts);
169         }
170         DEBUG("%p: failed, freed everything", (void *)rxq);
171         assert(ret > 0);
172         return ret;
173 }
174
175 /**
176  * Free RX queue elements with scattered packets support.
177  *
178  * @param rxq
179  *   Pointer to RX queue structure.
180  */
181 static void
182 rxq_free_elts_sp(struct rxq *rxq)
183 {
184         unsigned int i;
185         unsigned int elts_n = rxq->elts_n;
186         struct rxq_elt_sp (*elts)[elts_n] = rxq->elts.sp;
187
188         DEBUG("%p: freeing WRs", (void *)rxq);
189         rxq->elts_n = 0;
190         rxq->elts.sp = NULL;
191         if (elts == NULL)
192                 return;
193         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
194                 unsigned int j;
195                 struct rxq_elt_sp *elt = &(*elts)[i];
196
197                 for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
198                         struct rte_mbuf *buf = elt->bufs[j];
199
200                         if (buf != NULL)
201                                 rte_pktmbuf_free_seg(buf);
202                 }
203         }
204         rte_free(elts);
205 }
206
207 /**
208  * Allocate RX queue elements.
209  *
210  * @param rxq
211  *   Pointer to RX queue structure.
212  * @param elts_n
213  *   Number of elements to allocate.
214  * @param[in] pool
215  *   If not NULL, fetch buffers from this array instead of allocating them
216  *   with rte_pktmbuf_alloc().
217  *
218  * @return
219  *   0 on success, errno value on failure.
220  */
221 static int
222 rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n, struct rte_mbuf **pool)
223 {
224         unsigned int i;
225         struct rxq_elt (*elts)[elts_n] =
226                 rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0,
227                                   rxq->socket);
228         int ret = 0;
229
230         if (elts == NULL) {
231                 ERROR("%p: can't allocate packets array", (void *)rxq);
232                 ret = ENOMEM;
233                 goto error;
234         }
235         /* For each WR (packet). */
236         for (i = 0; (i != elts_n); ++i) {
237                 struct rxq_elt *elt = &(*elts)[i];
238                 struct ibv_sge *sge = &(*elts)[i].sge;
239                 struct rte_mbuf *buf;
240
241                 if (pool != NULL) {
242                         buf = *(pool++);
243                         assert(buf != NULL);
244                         rte_pktmbuf_reset(buf);
245                 } else
246                         buf = rte_pktmbuf_alloc(rxq->mp);
247                 if (buf == NULL) {
248                         assert(pool == NULL);
249                         ERROR("%p: empty mbuf pool", (void *)rxq);
250                         ret = ENOMEM;
251                         goto error;
252                 }
253                 elt->buf = buf;
254                 /* Headroom is reserved by rte_pktmbuf_alloc(). */
255                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
256                 /* Buffer is supposed to be empty. */
257                 assert(rte_pktmbuf_data_len(buf) == 0);
258                 assert(rte_pktmbuf_pkt_len(buf) == 0);
259                 /* sge->addr must be able to store a pointer. */
260                 assert(sizeof(sge->addr) >= sizeof(uintptr_t));
261                 /* SGE keeps its headroom. */
262                 sge->addr = (uintptr_t)
263                         ((uint8_t *)buf->buf_addr + RTE_PKTMBUF_HEADROOM);
264                 sge->length = (buf->buf_len - RTE_PKTMBUF_HEADROOM);
265                 sge->lkey = rxq->mr->lkey;
266                 /* Redundant check for tailroom. */
267                 assert(sge->length == rte_pktmbuf_tailroom(buf));
268         }
269         DEBUG("%p: allocated and configured %u single-segment WRs",
270               (void *)rxq, elts_n);
271         rxq->elts_n = elts_n;
272         rxq->elts_head = 0;
273         rxq->elts.no_sp = elts;
274         assert(ret == 0);
275         return 0;
276 error:
277         if (elts != NULL) {
278                 assert(pool == NULL);
279                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
280                         struct rxq_elt *elt = &(*elts)[i];
281                         struct rte_mbuf *buf = elt->buf;
282
283                         if (buf != NULL)
284                                 rte_pktmbuf_free_seg(buf);
285                 }
286                 rte_free(elts);
287         }
288         DEBUG("%p: failed, freed everything", (void *)rxq);
289         assert(ret > 0);
290         return ret;
291 }
292
293 /**
294  * Free RX queue elements.
295  *
296  * @param rxq
297  *   Pointer to RX queue structure.
298  */
299 static void
300 rxq_free_elts(struct rxq *rxq)
301 {
302         unsigned int i;
303         unsigned int elts_n = rxq->elts_n;
304         struct rxq_elt (*elts)[elts_n] = rxq->elts.no_sp;
305
306         DEBUG("%p: freeing WRs", (void *)rxq);
307         rxq->elts_n = 0;
308         rxq->elts.no_sp = NULL;
309         if (elts == NULL)
310                 return;
311         for (i = 0; (i != RTE_DIM(*elts)); ++i) {
312                 struct rxq_elt *elt = &(*elts)[i];
313                 struct rte_mbuf *buf = elt->buf;
314
315                 if (buf != NULL)
316                         rte_pktmbuf_free_seg(buf);
317         }
318         rte_free(elts);
319 }
320
321 /**
322  * Clean up a RX queue.
323  *
324  * Destroy objects, free allocated memory and reset the structure for reuse.
325  *
326  * @param rxq
327  *   Pointer to RX queue structure.
328  */
329 void
330 rxq_cleanup(struct rxq *rxq)
331 {
332         struct ibv_exp_release_intf_params params;
333
334         DEBUG("cleaning up %p", (void *)rxq);
335         if (rxq->sp)
336                 rxq_free_elts_sp(rxq);
337         else
338                 rxq_free_elts(rxq);
339         if (rxq->if_qp != NULL) {
340                 assert(rxq->priv != NULL);
341                 assert(rxq->priv->ctx != NULL);
342                 assert(rxq->qp != NULL);
343                 params = (struct ibv_exp_release_intf_params){
344                         .comp_mask = 0,
345                 };
346                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
347                                                 rxq->if_qp,
348                                                 &params));
349         }
350         if (rxq->if_cq != NULL) {
351                 assert(rxq->priv != NULL);
352                 assert(rxq->priv->ctx != NULL);
353                 assert(rxq->cq != NULL);
354                 params = (struct ibv_exp_release_intf_params){
355                         .comp_mask = 0,
356                 };
357                 claim_zero(ibv_exp_release_intf(rxq->priv->ctx,
358                                                 rxq->if_cq,
359                                                 &params));
360         }
361         if (rxq->qp != NULL) {
362                 rxq_promiscuous_disable(rxq);
363                 rxq_allmulticast_disable(rxq);
364                 rxq_mac_addrs_del(rxq);
365                 claim_zero(ibv_destroy_qp(rxq->qp));
366         }
367         if (rxq->cq != NULL)
368                 claim_zero(ibv_destroy_cq(rxq->cq));
369         if (rxq->rd != NULL) {
370                 struct ibv_exp_destroy_res_domain_attr attr = {
371                         .comp_mask = 0,
372                 };
373
374                 assert(rxq->priv != NULL);
375                 assert(rxq->priv->ctx != NULL);
376                 claim_zero(ibv_exp_destroy_res_domain(rxq->priv->ctx,
377                                                       rxq->rd,
378                                                       &attr));
379         }
380         if (rxq->mr != NULL)
381                 claim_zero(ibv_dereg_mr(rxq->mr));
382         memset(rxq, 0, sizeof(*rxq));
383 }
384
385 /**
386  * Allocate a Queue Pair.
387  * Optionally setup inline receive if supported.
388  *
389  * @param priv
390  *   Pointer to private structure.
391  * @param cq
392  *   Completion queue to associate with QP.
393  * @param desc
394  *   Number of descriptors in QP (hint only).
395  *
396  * @return
397  *   QP pointer or NULL in case of error.
398  */
399 static struct ibv_qp *
400 rxq_setup_qp(struct priv *priv, struct ibv_cq *cq, uint16_t desc,
401              struct ibv_exp_res_domain *rd)
402 {
403         struct ibv_exp_qp_init_attr attr = {
404                 /* CQ to be associated with the send queue. */
405                 .send_cq = cq,
406                 /* CQ to be associated with the receive queue. */
407                 .recv_cq = cq,
408                 .cap = {
409                         /* Max number of outstanding WRs. */
410                         .max_recv_wr = ((priv->device_attr.max_qp_wr < desc) ?
411                                         priv->device_attr.max_qp_wr :
412                                         desc),
413                         /* Max number of scatter/gather elements in a WR. */
414                         .max_recv_sge = ((priv->device_attr.max_sge <
415                                           MLX5_PMD_SGE_WR_N) ?
416                                          priv->device_attr.max_sge :
417                                          MLX5_PMD_SGE_WR_N),
418                 },
419                 .qp_type = IBV_QPT_RAW_PACKET,
420                 .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD |
421                               IBV_EXP_QP_INIT_ATTR_RES_DOMAIN),
422                 .pd = priv->pd,
423                 .res_domain = rd,
424         };
425
426         return ibv_exp_create_qp(priv->ctx, &attr);
427 }
428
429 #ifdef RSS_SUPPORT
430
431 /**
432  * Allocate a RSS Queue Pair.
433  * Optionally setup inline receive if supported.
434  *
435  * @param priv
436  *   Pointer to private structure.
437  * @param cq
438  *   Completion queue to associate with QP.
439  * @param desc
440  *   Number of descriptors in QP (hint only).
441  * @param parent
442  *   If nonzero, create a parent QP, otherwise a child.
443  *
444  * @return
445  *   QP pointer or NULL in case of error.
446  */
447 static struct ibv_qp *
448 rxq_setup_qp_rss(struct priv *priv, struct ibv_cq *cq, uint16_t desc,
449                  int parent, struct ibv_exp_res_domain *rd)
450 {
451         struct ibv_exp_qp_init_attr attr = {
452                 /* CQ to be associated with the send queue. */
453                 .send_cq = cq,
454                 /* CQ to be associated with the receive queue. */
455                 .recv_cq = cq,
456                 .cap = {
457                         /* Max number of outstanding WRs. */
458                         .max_recv_wr = ((priv->device_attr.max_qp_wr < desc) ?
459                                         priv->device_attr.max_qp_wr :
460                                         desc),
461                         /* Max number of scatter/gather elements in a WR. */
462                         .max_recv_sge = ((priv->device_attr.max_sge <
463                                           MLX5_PMD_SGE_WR_N) ?
464                                          priv->device_attr.max_sge :
465                                          MLX5_PMD_SGE_WR_N),
466                 },
467                 .qp_type = IBV_QPT_RAW_PACKET,
468                 .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD |
469                               IBV_EXP_QP_INIT_ATTR_RES_DOMAIN |
470                               IBV_EXP_QP_INIT_ATTR_QPG),
471                 .pd = priv->pd,
472                 .res_domain = rd,
473         };
474
475         if (parent) {
476                 attr.qpg.qpg_type = IBV_EXP_QPG_PARENT;
477                 /* TSS isn't necessary. */
478                 attr.qpg.parent_attrib.tss_child_count = 0;
479                 attr.qpg.parent_attrib.rss_child_count = priv->rxqs_n;
480                 DEBUG("initializing parent RSS queue");
481         } else {
482                 attr.qpg.qpg_type = IBV_EXP_QPG_CHILD_RX;
483                 attr.qpg.qpg_parent = priv->rxq_parent.qp;
484                 DEBUG("initializing child RSS queue");
485         }
486         return ibv_exp_create_qp(priv->ctx, &attr);
487 }
488
489 #endif /* RSS_SUPPORT */
490
491 /**
492  * Reconfigure a RX queue with new parameters.
493  *
494  * rxq_rehash() does not allocate mbufs, which, if not done from the right
495  * thread (such as a control thread), may corrupt the pool.
496  * In case of failure, the queue is left untouched.
497  *
498  * @param dev
499  *   Pointer to Ethernet device structure.
500  * @param rxq
501  *   RX queue pointer.
502  *
503  * @return
504  *   0 on success, errno value on failure.
505  */
506 int
507 rxq_rehash(struct rte_eth_dev *dev, struct rxq *rxq)
508 {
509         struct priv *priv = rxq->priv;
510         struct rxq tmpl = *rxq;
511         unsigned int mbuf_n;
512         unsigned int desc_n;
513         struct rte_mbuf **pool;
514         unsigned int i, k;
515         struct ibv_exp_qp_attr mod;
516         int err;
517         int parent = (rxq == &priv->rxq_parent);
518
519         if (parent) {
520                 ERROR("%p: cannot rehash parent queue %p",
521                       (void *)dev, (void *)rxq);
522                 return EINVAL;
523         }
524         DEBUG("%p: rehashing queue %p", (void *)dev, (void *)rxq);
525         /* Number of descriptors and mbufs currently allocated. */
526         desc_n = (tmpl.elts_n * (tmpl.sp ? MLX5_PMD_SGE_WR_N : 1));
527         mbuf_n = desc_n;
528         /* Toggle RX checksum offload if hardware supports it. */
529         if (priv->hw_csum) {
530                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
531                 rxq->csum = tmpl.csum;
532         }
533         if (priv->hw_csum_l2tun) {
534                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
535                 rxq->csum_l2tun = tmpl.csum_l2tun;
536         }
537         /* Enable scattered packets support for this queue if necessary. */
538         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
539             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
540              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
541                 tmpl.sp = 1;
542                 desc_n /= MLX5_PMD_SGE_WR_N;
543         } else
544                 tmpl.sp = 0;
545         DEBUG("%p: %s scattered packets support (%u WRs)",
546               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc_n);
547         /* If scatter mode is the same as before, nothing to do. */
548         if (tmpl.sp == rxq->sp) {
549                 DEBUG("%p: nothing to do", (void *)dev);
550                 return 0;
551         }
552         /* Remove attached flows if RSS is disabled (no parent queue). */
553         if (!priv->rss) {
554                 rxq_allmulticast_disable(&tmpl);
555                 rxq_promiscuous_disable(&tmpl);
556                 rxq_mac_addrs_del(&tmpl);
557                 /* Update original queue in case of failure. */
558                 rxq->allmulti_flow = tmpl.allmulti_flow;
559                 rxq->promisc_flow = tmpl.promisc_flow;
560                 memcpy(rxq->mac_flow, tmpl.mac_flow, sizeof(rxq->mac_flow));
561         }
562         /* From now on, any failure will render the queue unusable.
563          * Reinitialize QP. */
564         mod = (struct ibv_exp_qp_attr){ .qp_state = IBV_QPS_RESET };
565         err = ibv_exp_modify_qp(tmpl.qp, &mod, IBV_EXP_QP_STATE);
566         if (err) {
567                 ERROR("%p: cannot reset QP: %s", (void *)dev, strerror(err));
568                 assert(err > 0);
569                 return err;
570         }
571         err = ibv_resize_cq(tmpl.cq, desc_n);
572         if (err) {
573                 ERROR("%p: cannot resize CQ: %s", (void *)dev, strerror(err));
574                 assert(err > 0);
575                 return err;
576         }
577         mod = (struct ibv_exp_qp_attr){
578                 /* Move the QP to this state. */
579                 .qp_state = IBV_QPS_INIT,
580                 /* Primary port number. */
581                 .port_num = priv->port
582         };
583         err = ibv_exp_modify_qp(tmpl.qp, &mod,
584                                 (IBV_EXP_QP_STATE |
585 #ifdef RSS_SUPPORT
586                                  (parent ? IBV_EXP_QP_GROUP_RSS : 0) |
587 #endif /* RSS_SUPPORT */
588                                  IBV_EXP_QP_PORT));
589         if (err) {
590                 ERROR("%p: QP state to IBV_QPS_INIT failed: %s",
591                       (void *)dev, strerror(err));
592                 assert(err > 0);
593                 return err;
594         };
595         /* Reconfigure flows. Do not care for errors. */
596         if (!priv->rss) {
597                 if (priv->started)
598                         rxq_mac_addrs_add(&tmpl);
599                 if (priv->started && priv->promisc_req)
600                         rxq_promiscuous_enable(&tmpl);
601                 if (priv->started && priv->allmulti_req)
602                         rxq_allmulticast_enable(&tmpl);
603                 /* Update original queue in case of failure. */
604                 rxq->allmulti_flow = tmpl.allmulti_flow;
605                 rxq->promisc_flow = tmpl.promisc_flow;
606                 memcpy(rxq->mac_flow, tmpl.mac_flow, sizeof(rxq->mac_flow));
607         }
608         /* Allocate pool. */
609         pool = rte_malloc(__func__, (mbuf_n * sizeof(*pool)), 0);
610         if (pool == NULL) {
611                 ERROR("%p: cannot allocate memory", (void *)dev);
612                 return ENOBUFS;
613         }
614         /* Snatch mbufs from original queue. */
615         k = 0;
616         if (rxq->sp) {
617                 struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp;
618
619                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
620                         struct rxq_elt_sp *elt = &(*elts)[i];
621                         unsigned int j;
622
623                         for (j = 0; (j != RTE_DIM(elt->bufs)); ++j) {
624                                 assert(elt->bufs[j] != NULL);
625                                 pool[k++] = elt->bufs[j];
626                         }
627                 }
628         } else {
629                 struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp;
630
631                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
632                         struct rxq_elt *elt = &(*elts)[i];
633                         struct rte_mbuf *buf = elt->buf;
634
635                         pool[k++] = buf;
636                 }
637         }
638         assert(k == mbuf_n);
639         tmpl.elts_n = 0;
640         tmpl.elts.sp = NULL;
641         assert((void *)&tmpl.elts.sp == (void *)&tmpl.elts.no_sp);
642         err = ((tmpl.sp) ?
643                rxq_alloc_elts_sp(&tmpl, desc_n, pool) :
644                rxq_alloc_elts(&tmpl, desc_n, pool));
645         if (err) {
646                 ERROR("%p: cannot reallocate WRs, aborting", (void *)dev);
647                 rte_free(pool);
648                 assert(err > 0);
649                 return err;
650         }
651         assert(tmpl.elts_n == desc_n);
652         assert(tmpl.elts.sp != NULL);
653         rte_free(pool);
654         /* Clean up original data. */
655         rxq->elts_n = 0;
656         rte_free(rxq->elts.sp);
657         rxq->elts.sp = NULL;
658         /* Post SGEs. */
659         assert(tmpl.if_qp != NULL);
660         if (tmpl.sp) {
661                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
662
663                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
664 #ifdef HAVE_EXP_QP_BURST_RECV_SG_LIST
665                         err = tmpl.if_qp->recv_sg_list
666                                 (tmpl.qp,
667                                  (*elts)[i].sges,
668                                  RTE_DIM((*elts)[i].sges));
669 #else /* HAVE_EXP_QP_BURST_RECV_SG_LIST */
670                         errno = ENOSYS;
671                         err = -1;
672 #endif /* HAVE_EXP_QP_BURST_RECV_SG_LIST */
673                         if (err)
674                                 break;
675                 }
676         } else {
677                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
678
679                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
680                         err = tmpl.if_qp->recv_burst(
681                                 tmpl.qp,
682                                 &(*elts)[i].sge,
683                                 1);
684                         if (err)
685                                 break;
686                 }
687         }
688         if (err) {
689                 ERROR("%p: failed to post SGEs with error %d",
690                       (void *)dev, err);
691                 /* Set err because it does not contain a valid errno value. */
692                 err = EIO;
693                 goto skip_rtr;
694         }
695         mod = (struct ibv_exp_qp_attr){
696                 .qp_state = IBV_QPS_RTR
697         };
698         err = ibv_exp_modify_qp(tmpl.qp, &mod, IBV_EXP_QP_STATE);
699         if (err)
700                 ERROR("%p: QP state to IBV_QPS_RTR failed: %s",
701                       (void *)dev, strerror(err));
702 skip_rtr:
703         *rxq = tmpl;
704         assert(err >= 0);
705         return err;
706 }
707
708 /**
709  * Configure a RX queue.
710  *
711  * @param dev
712  *   Pointer to Ethernet device structure.
713  * @param rxq
714  *   Pointer to RX queue structure.
715  * @param desc
716  *   Number of descriptors to configure in queue.
717  * @param socket
718  *   NUMA socket on which memory must be allocated.
719  * @param[in] conf
720  *   Thresholds parameters.
721  * @param mp
722  *   Memory pool for buffer allocations.
723  *
724  * @return
725  *   0 on success, errno value on failure.
726  */
727 int
728 rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,
729           unsigned int socket, const struct rte_eth_rxconf *conf,
730           struct rte_mempool *mp)
731 {
732         struct priv *priv = dev->data->dev_private;
733         struct rxq tmpl = {
734                 .priv = priv,
735                 .mp = mp,
736                 .socket = socket
737         };
738         struct ibv_exp_qp_attr mod;
739         union {
740                 struct ibv_exp_query_intf_params params;
741                 struct ibv_exp_cq_init_attr cq;
742                 struct ibv_exp_res_domain_init_attr rd;
743         } attr;
744         enum ibv_exp_query_intf_status status;
745         struct rte_mbuf *buf;
746         int ret = 0;
747         int parent = (rxq == &priv->rxq_parent);
748         unsigned int i;
749
750         (void)conf; /* Thresholds configuration (ignored). */
751         /*
752          * If this is a parent queue, hardware must support RSS and
753          * RSS must be enabled.
754          */
755         assert((!parent) || ((priv->hw_rss) && (priv->rss)));
756         if (parent) {
757                 /* Even if unused, ibv_create_cq() requires at least one
758                  * descriptor. */
759                 desc = 1;
760                 goto skip_mr;
761         }
762         if ((desc == 0) || (desc % MLX5_PMD_SGE_WR_N)) {
763                 ERROR("%p: invalid number of RX descriptors (must be a"
764                       " multiple of %d)", (void *)dev, MLX5_PMD_SGE_WR_N);
765                 return EINVAL;
766         }
767         /* Get mbuf length. */
768         buf = rte_pktmbuf_alloc(mp);
769         if (buf == NULL) {
770                 ERROR("%p: unable to allocate mbuf", (void *)dev);
771                 return ENOMEM;
772         }
773         tmpl.mb_len = buf->buf_len;
774         assert((rte_pktmbuf_headroom(buf) +
775                 rte_pktmbuf_tailroom(buf)) == tmpl.mb_len);
776         assert(rte_pktmbuf_headroom(buf) == RTE_PKTMBUF_HEADROOM);
777         rte_pktmbuf_free(buf);
778         /* Toggle RX checksum offload if hardware supports it. */
779         if (priv->hw_csum)
780                 tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
781         if (priv->hw_csum_l2tun)
782                 tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum;
783         /* Enable scattered packets support for this queue if necessary. */
784         if ((dev->data->dev_conf.rxmode.jumbo_frame) &&
785             (dev->data->dev_conf.rxmode.max_rx_pkt_len >
786              (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) {
787                 tmpl.sp = 1;
788                 desc /= MLX5_PMD_SGE_WR_N;
789         }
790         DEBUG("%p: %s scattered packets support (%u WRs)",
791               (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc);
792         /* Use the entire RX mempool as the memory region. */
793         tmpl.mr = ibv_reg_mr(priv->pd,
794                              (void *)mp->elt_va_start,
795                              (mp->elt_va_end - mp->elt_va_start),
796                              (IBV_ACCESS_LOCAL_WRITE |
797                               IBV_ACCESS_REMOTE_WRITE));
798         if (tmpl.mr == NULL) {
799                 ret = EINVAL;
800                 ERROR("%p: MR creation failure: %s",
801                       (void *)dev, strerror(ret));
802                 goto error;
803         }
804 skip_mr:
805         attr.rd = (struct ibv_exp_res_domain_init_attr){
806                 .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL |
807                               IBV_EXP_RES_DOMAIN_MSG_MODEL),
808                 .thread_model = IBV_EXP_THREAD_SINGLE,
809                 .msg_model = IBV_EXP_MSG_HIGH_BW,
810         };
811         tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd);
812         if (tmpl.rd == NULL) {
813                 ret = ENOMEM;
814                 ERROR("%p: RD creation failure: %s",
815                       (void *)dev, strerror(ret));
816                 goto error;
817         }
818         attr.cq = (struct ibv_exp_cq_init_attr){
819                 .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN,
820                 .res_domain = tmpl.rd,
821         };
822         tmpl.cq = ibv_exp_create_cq(priv->ctx, desc, NULL, NULL, 0, &attr.cq);
823         if (tmpl.cq == NULL) {
824                 ret = ENOMEM;
825                 ERROR("%p: CQ creation failure: %s",
826                       (void *)dev, strerror(ret));
827                 goto error;
828         }
829         DEBUG("priv->device_attr.max_qp_wr is %d",
830               priv->device_attr.max_qp_wr);
831         DEBUG("priv->device_attr.max_sge is %d",
832               priv->device_attr.max_sge);
833 #ifdef RSS_SUPPORT
834         if (priv->rss)
835                 tmpl.qp = rxq_setup_qp_rss(priv, tmpl.cq, desc, parent,
836                                            tmpl.rd);
837         else
838 #endif /* RSS_SUPPORT */
839                 tmpl.qp = rxq_setup_qp(priv, tmpl.cq, desc, tmpl.rd);
840         if (tmpl.qp == NULL) {
841                 ret = (errno ? errno : EINVAL);
842                 ERROR("%p: QP creation failure: %s",
843                       (void *)dev, strerror(ret));
844                 goto error;
845         }
846         mod = (struct ibv_exp_qp_attr){
847                 /* Move the QP to this state. */
848                 .qp_state = IBV_QPS_INIT,
849                 /* Primary port number. */
850                 .port_num = priv->port
851         };
852         ret = ibv_exp_modify_qp(tmpl.qp, &mod,
853                                 (IBV_EXP_QP_STATE |
854 #ifdef RSS_SUPPORT
855                                  (parent ? IBV_EXP_QP_GROUP_RSS : 0) |
856 #endif /* RSS_SUPPORT */
857                                  IBV_EXP_QP_PORT));
858         if (ret) {
859                 ERROR("%p: QP state to IBV_QPS_INIT failed: %s",
860                       (void *)dev, strerror(ret));
861                 goto error;
862         }
863         if ((parent) || (!priv->rss))  {
864                 /* Configure MAC and broadcast addresses. */
865                 ret = rxq_mac_addrs_add(&tmpl);
866                 if (ret) {
867                         ERROR("%p: QP flow attachment failed: %s",
868                               (void *)dev, strerror(ret));
869                         goto error;
870                 }
871         }
872         /* Allocate descriptors for RX queues, except for the RSS parent. */
873         if (parent)
874                 goto skip_alloc;
875         if (tmpl.sp)
876                 ret = rxq_alloc_elts_sp(&tmpl, desc, NULL);
877         else
878                 ret = rxq_alloc_elts(&tmpl, desc, NULL);
879         if (ret) {
880                 ERROR("%p: RXQ allocation failed: %s",
881                       (void *)dev, strerror(ret));
882                 goto error;
883         }
884 skip_alloc:
885         /* Save port ID. */
886         tmpl.port_id = dev->data->port_id;
887         DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id);
888         attr.params = (struct ibv_exp_query_intf_params){
889                 .intf_scope = IBV_EXP_INTF_GLOBAL,
890                 .intf = IBV_EXP_INTF_CQ,
891                 .obj = tmpl.cq,
892         };
893         tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
894         if (tmpl.if_cq == NULL) {
895                 ERROR("%p: CQ interface family query failed with status %d",
896                       (void *)dev, status);
897                 goto error;
898         }
899         attr.params = (struct ibv_exp_query_intf_params){
900                 .intf_scope = IBV_EXP_INTF_GLOBAL,
901                 .intf = IBV_EXP_INTF_QP_BURST,
902                 .obj = tmpl.qp,
903         };
904         tmpl.if_qp = ibv_exp_query_intf(priv->ctx, &attr.params, &status);
905         if (tmpl.if_qp == NULL) {
906                 ERROR("%p: QP interface family query failed with status %d",
907                       (void *)dev, status);
908                 goto error;
909         }
910         /* Post SGEs. */
911         if (!parent && tmpl.sp) {
912                 struct rxq_elt_sp (*elts)[tmpl.elts_n] = tmpl.elts.sp;
913
914                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
915 #ifdef HAVE_EXP_QP_BURST_RECV_SG_LIST
916                         ret = tmpl.if_qp->recv_sg_list
917                                 (tmpl.qp,
918                                  (*elts)[i].sges,
919                                  RTE_DIM((*elts)[i].sges));
920 #else /* HAVE_EXP_QP_BURST_RECV_SG_LIST */
921                         errno = ENOSYS;
922                         ret = -1;
923 #endif /* HAVE_EXP_QP_BURST_RECV_SG_LIST */
924                         if (ret)
925                                 break;
926                 }
927         } else if (!parent) {
928                 struct rxq_elt (*elts)[tmpl.elts_n] = tmpl.elts.no_sp;
929
930                 for (i = 0; (i != RTE_DIM(*elts)); ++i) {
931                         ret = tmpl.if_qp->recv_burst(
932                                 tmpl.qp,
933                                 &(*elts)[i].sge,
934                                 1);
935                         if (ret)
936                                 break;
937                 }
938         }
939         if (ret) {
940                 ERROR("%p: failed to post SGEs with error %d",
941                       (void *)dev, ret);
942                 /* Set ret because it does not contain a valid errno value. */
943                 ret = EIO;
944                 goto error;
945         }
946         mod = (struct ibv_exp_qp_attr){
947                 .qp_state = IBV_QPS_RTR
948         };
949         ret = ibv_exp_modify_qp(tmpl.qp, &mod, IBV_EXP_QP_STATE);
950         if (ret) {
951                 ERROR("%p: QP state to IBV_QPS_RTR failed: %s",
952                       (void *)dev, strerror(ret));
953                 goto error;
954         }
955         /* Clean up rxq in case we're reinitializing it. */
956         DEBUG("%p: cleaning-up old rxq just in case", (void *)rxq);
957         rxq_cleanup(rxq);
958         *rxq = tmpl;
959         DEBUG("%p: rxq updated with %p", (void *)rxq, (void *)&tmpl);
960         assert(ret == 0);
961         return 0;
962 error:
963         rxq_cleanup(&tmpl);
964         assert(ret > 0);
965         return ret;
966 }
967
968 /**
969  * DPDK callback to configure a RX queue.
970  *
971  * @param dev
972  *   Pointer to Ethernet device structure.
973  * @param idx
974  *   RX queue index.
975  * @param desc
976  *   Number of descriptors to configure in queue.
977  * @param socket
978  *   NUMA socket on which memory must be allocated.
979  * @param[in] conf
980  *   Thresholds parameters.
981  * @param mp
982  *   Memory pool for buffer allocations.
983  *
984  * @return
985  *   0 on success, negative errno value on failure.
986  */
987 int
988 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
989                     unsigned int socket, const struct rte_eth_rxconf *conf,
990                     struct rte_mempool *mp)
991 {
992         struct priv *priv = dev->data->dev_private;
993         struct rxq *rxq = (*priv->rxqs)[idx];
994         int ret;
995
996         priv_lock(priv);
997         DEBUG("%p: configuring queue %u for %u descriptors",
998               (void *)dev, idx, desc);
999         if (idx >= priv->rxqs_n) {
1000                 ERROR("%p: queue index out of range (%u >= %u)",
1001                       (void *)dev, idx, priv->rxqs_n);
1002                 priv_unlock(priv);
1003                 return -EOVERFLOW;
1004         }
1005         if (rxq != NULL) {
1006                 DEBUG("%p: reusing already allocated queue index %u (%p)",
1007                       (void *)dev, idx, (void *)rxq);
1008                 if (priv->started) {
1009                         priv_unlock(priv);
1010                         return -EEXIST;
1011                 }
1012                 (*priv->rxqs)[idx] = NULL;
1013                 rxq_cleanup(rxq);
1014         } else {
1015                 rxq = rte_calloc_socket("RXQ", 1, sizeof(*rxq), 0, socket);
1016                 if (rxq == NULL) {
1017                         ERROR("%p: unable to allocate queue index %u",
1018                               (void *)dev, idx);
1019                         priv_unlock(priv);
1020                         return -ENOMEM;
1021                 }
1022         }
1023         ret = rxq_setup(dev, rxq, desc, socket, conf, mp);
1024         if (ret)
1025                 rte_free(rxq);
1026         else {
1027                 rxq->stats.idx = idx;
1028                 DEBUG("%p: adding RX queue %p to list",
1029                       (void *)dev, (void *)rxq);
1030                 (*priv->rxqs)[idx] = rxq;
1031                 /* Update receive callback. */
1032                 if (rxq->sp)
1033                         dev->rx_pkt_burst = mlx5_rx_burst_sp;
1034                 else
1035                         dev->rx_pkt_burst = mlx5_rx_burst;
1036         }
1037         priv_unlock(priv);
1038         return -ret;
1039 }
1040
1041 /**
1042  * DPDK callback to release a RX queue.
1043  *
1044  * @param dpdk_rxq
1045  *   Generic RX queue pointer.
1046  */
1047 void
1048 mlx5_rx_queue_release(void *dpdk_rxq)
1049 {
1050         struct rxq *rxq = (struct rxq *)dpdk_rxq;
1051         struct priv *priv;
1052         unsigned int i;
1053
1054         if (rxq == NULL)
1055                 return;
1056         priv = rxq->priv;
1057         priv_lock(priv);
1058         assert(rxq != &priv->rxq_parent);
1059         for (i = 0; (i != priv->rxqs_n); ++i)
1060                 if ((*priv->rxqs)[i] == rxq) {
1061                         DEBUG("%p: removing RX queue %p from list",
1062                               (void *)priv->dev, (void *)rxq);
1063                         (*priv->rxqs)[i] = NULL;
1064                         break;
1065                 }
1066         rxq_cleanup(rxq);
1067         rte_free(rxq);
1068         priv_unlock(priv);
1069 }