1b4570586043aaaa30497a739b4a4e5d1563f9f0
[dpdk.git] / drivers / net / mlx5 / mlx5_rxq.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2015 6WIND S.A.
3  * Copyright 2015 Mellanox.
4  */
5
6 #include <stddef.h>
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <stdint.h>
11 #include <fcntl.h>
12 #include <sys/queue.h>
13
14 /* Verbs header. */
15 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
16 #ifdef PEDANTIC
17 #pragma GCC diagnostic ignored "-Wpedantic"
18 #endif
19 #include <infiniband/verbs.h>
20 #include <infiniband/mlx5dv.h>
21 #ifdef PEDANTIC
22 #pragma GCC diagnostic error "-Wpedantic"
23 #endif
24
25 #include <rte_mbuf.h>
26 #include <rte_malloc.h>
27 #include <rte_ethdev_driver.h>
28 #include <rte_common.h>
29 #include <rte_interrupts.h>
30 #include <rte_debug.h>
31 #include <rte_io.h>
32
33 #include "mlx5.h"
34 #include "mlx5_rxtx.h"
35 #include "mlx5_utils.h"
36 #include "mlx5_autoconf.h"
37 #include "mlx5_defs.h"
38 #include "mlx5_glue.h"
39
40 /* Default RSS hash key also used for ConnectX-3. */
41 uint8_t rss_hash_default_key[] = {
42         0x2c, 0xc6, 0x81, 0xd1,
43         0x5b, 0xdb, 0xf4, 0xf7,
44         0xfc, 0xa2, 0x83, 0x19,
45         0xdb, 0x1a, 0x3e, 0x94,
46         0x6b, 0x9e, 0x38, 0xd9,
47         0x2c, 0x9c, 0x03, 0xd1,
48         0xad, 0x99, 0x44, 0xa7,
49         0xd9, 0x56, 0x3d, 0x59,
50         0x06, 0x3c, 0x25, 0xf3,
51         0xfc, 0x1f, 0xdc, 0x2a,
52 };
53
54 /* Length of the default RSS hash key. */
55 const size_t rss_hash_default_key_len = sizeof(rss_hash_default_key);
56
57 /**
58  * Allocate RX queue elements.
59  *
60  * @param rxq_ctrl
61  *   Pointer to RX queue structure.
62  *
63  * @return
64  *   0 on success, a negative errno value otherwise and rte_errno is set.
65  */
66 int
67 rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl)
68 {
69         const unsigned int sges_n = 1 << rxq_ctrl->rxq.sges_n;
70         unsigned int elts_n = 1 << rxq_ctrl->rxq.elts_n;
71         unsigned int i;
72         int err;
73
74         /* Iterate on segments. */
75         for (i = 0; (i != elts_n); ++i) {
76                 struct rte_mbuf *buf;
77
78                 buf = rte_pktmbuf_alloc(rxq_ctrl->rxq.mp);
79                 if (buf == NULL) {
80                         DRV_LOG(ERR, "port %u empty mbuf pool",
81                                 rxq_ctrl->priv->dev->data->port_id);
82                         rte_errno = ENOMEM;
83                         goto error;
84                 }
85                 /* Headroom is reserved by rte_pktmbuf_alloc(). */
86                 assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM);
87                 /* Buffer is supposed to be empty. */
88                 assert(rte_pktmbuf_data_len(buf) == 0);
89                 assert(rte_pktmbuf_pkt_len(buf) == 0);
90                 assert(!buf->next);
91                 /* Only the first segment keeps headroom. */
92                 if (i % sges_n)
93                         SET_DATA_OFF(buf, 0);
94                 PORT(buf) = rxq_ctrl->rxq.port_id;
95                 DATA_LEN(buf) = rte_pktmbuf_tailroom(buf);
96                 PKT_LEN(buf) = DATA_LEN(buf);
97                 NB_SEGS(buf) = 1;
98                 (*rxq_ctrl->rxq.elts)[i] = buf;
99         }
100         /* If Rx vector is activated. */
101         if (mlx5_rxq_check_vec_support(&rxq_ctrl->rxq) > 0) {
102                 struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq;
103                 struct rte_mbuf *mbuf_init = &rxq->fake_mbuf;
104                 int j;
105
106                 /* Initialize default rearm_data for vPMD. */
107                 mbuf_init->data_off = RTE_PKTMBUF_HEADROOM;
108                 rte_mbuf_refcnt_set(mbuf_init, 1);
109                 mbuf_init->nb_segs = 1;
110                 mbuf_init->port = rxq->port_id;
111                 /*
112                  * prevent compiler reordering:
113                  * rearm_data covers previous fields.
114                  */
115                 rte_compiler_barrier();
116                 rxq->mbuf_initializer =
117                         *(uint64_t *)&mbuf_init->rearm_data;
118                 /* Padding with a fake mbuf for vectorized Rx. */
119                 for (j = 0; j < MLX5_VPMD_DESCS_PER_LOOP; ++j)
120                         (*rxq->elts)[elts_n + j] = &rxq->fake_mbuf;
121         }
122         DRV_LOG(DEBUG,
123                 "port %u Rx queue %u allocated and configured %u segments"
124                 " (max %u packets)",
125                 rxq_ctrl->priv->dev->data->port_id, rxq_ctrl->idx, elts_n,
126                 elts_n / (1 << rxq_ctrl->rxq.sges_n));
127         return 0;
128 error:
129         err = rte_errno; /* Save rte_errno before cleanup. */
130         elts_n = i;
131         for (i = 0; (i != elts_n); ++i) {
132                 if ((*rxq_ctrl->rxq.elts)[i] != NULL)
133                         rte_pktmbuf_free_seg((*rxq_ctrl->rxq.elts)[i]);
134                 (*rxq_ctrl->rxq.elts)[i] = NULL;
135         }
136         DRV_LOG(DEBUG, "port %u Rx queue %u failed, freed everything",
137                 rxq_ctrl->priv->dev->data->port_id, rxq_ctrl->idx);
138         rte_errno = err; /* Restore rte_errno. */
139         return -rte_errno;
140 }
141
142 /**
143  * Free RX queue elements.
144  *
145  * @param rxq_ctrl
146  *   Pointer to RX queue structure.
147  */
148 static void
149 rxq_free_elts(struct mlx5_rxq_ctrl *rxq_ctrl)
150 {
151         struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq;
152         const uint16_t q_n = (1 << rxq->elts_n);
153         const uint16_t q_mask = q_n - 1;
154         uint16_t used = q_n - (rxq->rq_ci - rxq->rq_pi);
155         uint16_t i;
156
157         DRV_LOG(DEBUG, "port %u Rx queue %u freeing WRs",
158                 rxq_ctrl->priv->dev->data->port_id, rxq_ctrl->idx);
159         if (rxq->elts == NULL)
160                 return;
161         /**
162          * Some mbuf in the Ring belongs to the application.  They cannot be
163          * freed.
164          */
165         if (mlx5_rxq_check_vec_support(rxq) > 0) {
166                 for (i = 0; i < used; ++i)
167                         (*rxq->elts)[(rxq->rq_ci + i) & q_mask] = NULL;
168                 rxq->rq_pi = rxq->rq_ci;
169         }
170         for (i = 0; (i != (1u << rxq->elts_n)); ++i) {
171                 if ((*rxq->elts)[i] != NULL)
172                         rte_pktmbuf_free_seg((*rxq->elts)[i]);
173                 (*rxq->elts)[i] = NULL;
174         }
175 }
176
177 /**
178  * Clean up a RX queue.
179  *
180  * Destroy objects, free allocated memory and reset the structure for reuse.
181  *
182  * @param rxq_ctrl
183  *   Pointer to RX queue structure.
184  */
185 void
186 mlx5_rxq_cleanup(struct mlx5_rxq_ctrl *rxq_ctrl)
187 {
188         DRV_LOG(DEBUG, "port %u cleaning up Rx queue %u",
189                 rxq_ctrl->priv->dev->data->port_id, rxq_ctrl->idx);
190         if (rxq_ctrl->ibv)
191                 mlx5_rxq_ibv_release(rxq_ctrl->ibv);
192         memset(rxq_ctrl, 0, sizeof(*rxq_ctrl));
193 }
194
195 /**
196  * Returns the per-queue supported offloads.
197  *
198  * @param dev
199  *   Pointer to Ethernet device.
200  *
201  * @return
202  *   Supported Rx offloads.
203  */
204 uint64_t
205 mlx5_get_rx_queue_offloads(struct rte_eth_dev *dev)
206 {
207         struct priv *priv = dev->data->dev_private;
208         struct mlx5_dev_config *config = &priv->config;
209         uint64_t offloads = (DEV_RX_OFFLOAD_SCATTER |
210                              DEV_RX_OFFLOAD_TIMESTAMP |
211                              DEV_RX_OFFLOAD_JUMBO_FRAME);
212
213         if (config->hw_fcs_strip)
214                 offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
215         if (config->hw_csum)
216                 offloads |= (DEV_RX_OFFLOAD_IPV4_CKSUM |
217                              DEV_RX_OFFLOAD_UDP_CKSUM |
218                              DEV_RX_OFFLOAD_TCP_CKSUM);
219         if (config->hw_vlan_strip)
220                 offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
221         return offloads;
222 }
223
224
225 /**
226  * Returns the per-port supported offloads.
227  *
228  * @return
229  *   Supported Rx offloads.
230  */
231 uint64_t
232 mlx5_get_rx_port_offloads(void)
233 {
234         uint64_t offloads = DEV_RX_OFFLOAD_VLAN_FILTER;
235
236         return offloads;
237 }
238
239 /**
240  * Checks if the per-queue offload configuration is valid.
241  *
242  * @param dev
243  *   Pointer to Ethernet device.
244  * @param offloads
245  *   Per-queue offloads configuration.
246  *
247  * @return
248  *   1 if the configuration is valid, 0 otherwise.
249  */
250 static int
251 mlx5_is_rx_queue_offloads_allowed(struct rte_eth_dev *dev, uint64_t offloads)
252 {
253         uint64_t port_offloads = dev->data->dev_conf.rxmode.offloads;
254         uint64_t queue_supp_offloads = mlx5_get_rx_queue_offloads(dev);
255         uint64_t port_supp_offloads = mlx5_get_rx_port_offloads();
256
257         if ((offloads & (queue_supp_offloads | port_supp_offloads)) !=
258             offloads)
259                 return 0;
260         if (((port_offloads ^ offloads) & port_supp_offloads))
261                 return 0;
262         return 1;
263 }
264
265 /**
266  *
267  * @param dev
268  *   Pointer to Ethernet device structure.
269  * @param idx
270  *   RX queue index.
271  * @param desc
272  *   Number of descriptors to configure in queue.
273  * @param socket
274  *   NUMA socket on which memory must be allocated.
275  * @param[in] conf
276  *   Thresholds parameters.
277  * @param mp
278  *   Memory pool for buffer allocations.
279  *
280  * @return
281  *   0 on success, a negative errno value otherwise and rte_errno is set.
282  */
283 int
284 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
285                     unsigned int socket, const struct rte_eth_rxconf *conf,
286                     struct rte_mempool *mp)
287 {
288         struct priv *priv = dev->data->dev_private;
289         struct mlx5_rxq_data *rxq = (*priv->rxqs)[idx];
290         struct mlx5_rxq_ctrl *rxq_ctrl =
291                 container_of(rxq, struct mlx5_rxq_ctrl, rxq);
292
293         if (!rte_is_power_of_2(desc)) {
294                 desc = 1 << log2above(desc);
295                 DRV_LOG(WARNING,
296                         "port %u increased number of descriptors in Rx queue %u"
297                         " to the next power of two (%d)",
298                         dev->data->port_id, idx, desc);
299         }
300         DRV_LOG(DEBUG, "port %u configuring Rx queue %u for %u descriptors",
301                 dev->data->port_id, idx, desc);
302         if (idx >= priv->rxqs_n) {
303                 DRV_LOG(ERR, "port %u Rx queue index out of range (%u >= %u)",
304                         dev->data->port_id, idx, priv->rxqs_n);
305                 rte_errno = EOVERFLOW;
306                 return -rte_errno;
307         }
308         if (!mlx5_is_rx_queue_offloads_allowed(dev, conf->offloads)) {
309                 DRV_LOG(ERR,
310                         "port %u Rx queue offloads 0x%" PRIx64 " don't match"
311                         " port offloads 0x%" PRIx64 " or supported offloads 0x%"
312                         PRIx64,
313                         dev->data->port_id, conf->offloads,
314                         dev->data->dev_conf.rxmode.offloads,
315                         (mlx5_get_rx_port_offloads() |
316                          mlx5_get_rx_queue_offloads(dev)));
317                 rte_errno = ENOTSUP;
318                 return -rte_errno;
319         }
320         if (!mlx5_rxq_releasable(dev, idx)) {
321                 DRV_LOG(ERR, "port %u unable to release queue index %u",
322                         dev->data->port_id, idx);
323                 rte_errno = EBUSY;
324                 return -rte_errno;
325         }
326         mlx5_rxq_release(dev, idx);
327         rxq_ctrl = mlx5_rxq_new(dev, idx, desc, socket, conf, mp);
328         if (!rxq_ctrl) {
329                 DRV_LOG(ERR, "port %u unable to allocate queue index %u",
330                         dev->data->port_id, idx);
331                 rte_errno = ENOMEM;
332                 return -rte_errno;
333         }
334         DRV_LOG(DEBUG, "port %u adding Rx queue %u to list",
335                 dev->data->port_id, idx);
336         (*priv->rxqs)[idx] = &rxq_ctrl->rxq;
337         return 0;
338 }
339
340 /**
341  * DPDK callback to release a RX queue.
342  *
343  * @param dpdk_rxq
344  *   Generic RX queue pointer.
345  */
346 void
347 mlx5_rx_queue_release(void *dpdk_rxq)
348 {
349         struct mlx5_rxq_data *rxq = (struct mlx5_rxq_data *)dpdk_rxq;
350         struct mlx5_rxq_ctrl *rxq_ctrl;
351         struct priv *priv;
352
353         if (rxq == NULL)
354                 return;
355         rxq_ctrl = container_of(rxq, struct mlx5_rxq_ctrl, rxq);
356         priv = rxq_ctrl->priv;
357         if (!mlx5_rxq_releasable(priv->dev, rxq_ctrl->rxq.stats.idx))
358                 rte_panic("port %u Rx queue %u is still used by a flow and"
359                           " cannot be removed\n", priv->dev->data->port_id,
360                           rxq_ctrl->idx);
361         mlx5_rxq_release(priv->dev, rxq_ctrl->rxq.stats.idx);
362 }
363
364 /**
365  * Allocate queue vector and fill epoll fd list for Rx interrupts.
366  *
367  * @param dev
368  *   Pointer to Ethernet device.
369  *
370  * @return
371  *   0 on success, a negative errno value otherwise and rte_errno is set.
372  */
373 int
374 mlx5_rx_intr_vec_enable(struct rte_eth_dev *dev)
375 {
376         struct priv *priv = dev->data->dev_private;
377         unsigned int i;
378         unsigned int rxqs_n = priv->rxqs_n;
379         unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
380         unsigned int count = 0;
381         struct rte_intr_handle *intr_handle = priv->dev->intr_handle;
382
383         if (!priv->dev->data->dev_conf.intr_conf.rxq)
384                 return 0;
385         mlx5_rx_intr_vec_disable(dev);
386         intr_handle->intr_vec = malloc(n * sizeof(intr_handle->intr_vec[0]));
387         if (intr_handle->intr_vec == NULL) {
388                 DRV_LOG(ERR,
389                         "port %u failed to allocate memory for interrupt"
390                         " vector, Rx interrupts will not be supported",
391                         dev->data->port_id);
392                 rte_errno = ENOMEM;
393                 return -rte_errno;
394         }
395         intr_handle->type = RTE_INTR_HANDLE_EXT;
396         for (i = 0; i != n; ++i) {
397                 /* This rxq ibv must not be released in this function. */
398                 struct mlx5_rxq_ibv *rxq_ibv = mlx5_rxq_ibv_get(dev, i);
399                 int fd;
400                 int flags;
401                 int rc;
402
403                 /* Skip queues that cannot request interrupts. */
404                 if (!rxq_ibv || !rxq_ibv->channel) {
405                         /* Use invalid intr_vec[] index to disable entry. */
406                         intr_handle->intr_vec[i] =
407                                 RTE_INTR_VEC_RXTX_OFFSET +
408                                 RTE_MAX_RXTX_INTR_VEC_ID;
409                         continue;
410                 }
411                 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) {
412                         DRV_LOG(ERR,
413                                 "port %u too many Rx queues for interrupt"
414                                 " vector size (%d), Rx interrupts cannot be"
415                                 " enabled",
416                                 dev->data->port_id, RTE_MAX_RXTX_INTR_VEC_ID);
417                         mlx5_rx_intr_vec_disable(dev);
418                         rte_errno = ENOMEM;
419                         return -rte_errno;
420                 }
421                 fd = rxq_ibv->channel->fd;
422                 flags = fcntl(fd, F_GETFL);
423                 rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
424                 if (rc < 0) {
425                         rte_errno = errno;
426                         DRV_LOG(ERR,
427                                 "port %u failed to make Rx interrupt file"
428                                 " descriptor %d non-blocking for queue index"
429                                 " %d",
430                                 dev->data->port_id, fd, i);
431                         mlx5_rx_intr_vec_disable(dev);
432                         return -rte_errno;
433                 }
434                 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count;
435                 intr_handle->efds[count] = fd;
436                 count++;
437         }
438         if (!count)
439                 mlx5_rx_intr_vec_disable(dev);
440         else
441                 intr_handle->nb_efd = count;
442         return 0;
443 }
444
445 /**
446  * Clean up Rx interrupts handler.
447  *
448  * @param dev
449  *   Pointer to Ethernet device.
450  */
451 void
452 mlx5_rx_intr_vec_disable(struct rte_eth_dev *dev)
453 {
454         struct priv *priv = dev->data->dev_private;
455         struct rte_intr_handle *intr_handle = priv->dev->intr_handle;
456         unsigned int i;
457         unsigned int rxqs_n = priv->rxqs_n;
458         unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
459
460         if (!priv->dev->data->dev_conf.intr_conf.rxq)
461                 return;
462         if (!intr_handle->intr_vec)
463                 goto free;
464         for (i = 0; i != n; ++i) {
465                 struct mlx5_rxq_ctrl *rxq_ctrl;
466                 struct mlx5_rxq_data *rxq_data;
467
468                 if (intr_handle->intr_vec[i] == RTE_INTR_VEC_RXTX_OFFSET +
469                     RTE_MAX_RXTX_INTR_VEC_ID)
470                         continue;
471                 /**
472                  * Need to access directly the queue to release the reference
473                  * kept in priv_rx_intr_vec_enable().
474                  */
475                 rxq_data = (*priv->rxqs)[i];
476                 rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
477                 mlx5_rxq_ibv_release(rxq_ctrl->ibv);
478         }
479 free:
480         rte_intr_free_epoll_fd(intr_handle);
481         if (intr_handle->intr_vec)
482                 free(intr_handle->intr_vec);
483         intr_handle->nb_efd = 0;
484         intr_handle->intr_vec = NULL;
485 }
486
487 /**
488  *  MLX5 CQ notification .
489  *
490  *  @param rxq
491  *     Pointer to receive queue structure.
492  *  @param sq_n_rxq
493  *     Sequence number per receive queue .
494  */
495 static inline void
496 mlx5_arm_cq(struct mlx5_rxq_data *rxq, int sq_n_rxq)
497 {
498         int sq_n = 0;
499         uint32_t doorbell_hi;
500         uint64_t doorbell;
501         void *cq_db_reg = (char *)rxq->cq_uar + MLX5_CQ_DOORBELL;
502
503         sq_n = sq_n_rxq & MLX5_CQ_SQN_MASK;
504         doorbell_hi = sq_n << MLX5_CQ_SQN_OFFSET | (rxq->cq_ci & MLX5_CI_MASK);
505         doorbell = (uint64_t)doorbell_hi << 32;
506         doorbell |=  rxq->cqn;
507         rxq->cq_db[MLX5_CQ_ARM_DB] = rte_cpu_to_be_32(doorbell_hi);
508         rte_write64(rte_cpu_to_be_64(doorbell), cq_db_reg);
509 }
510
511 /**
512  * DPDK callback for Rx queue interrupt enable.
513  *
514  * @param dev
515  *   Pointer to Ethernet device structure.
516  * @param rx_queue_id
517  *   Rx queue number.
518  *
519  * @return
520  *   0 on success, a negative errno value otherwise and rte_errno is set.
521  */
522 int
523 mlx5_rx_intr_enable(struct rte_eth_dev *dev, uint16_t rx_queue_id)
524 {
525         struct priv *priv = dev->data->dev_private;
526         struct mlx5_rxq_data *rxq_data;
527         struct mlx5_rxq_ctrl *rxq_ctrl;
528
529         rxq_data = (*priv->rxqs)[rx_queue_id];
530         if (!rxq_data) {
531                 rte_errno = EINVAL;
532                 return -rte_errno;
533         }
534         rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
535         if (rxq_ctrl->irq) {
536                 struct mlx5_rxq_ibv *rxq_ibv;
537
538                 rxq_ibv = mlx5_rxq_ibv_get(dev, rx_queue_id);
539                 if (!rxq_ibv) {
540                         rte_errno = EINVAL;
541                         return -rte_errno;
542                 }
543                 mlx5_arm_cq(rxq_data, rxq_data->cq_arm_sn);
544                 mlx5_rxq_ibv_release(rxq_ibv);
545         }
546         return 0;
547 }
548
549 /**
550  * DPDK callback for Rx queue interrupt disable.
551  *
552  * @param dev
553  *   Pointer to Ethernet device structure.
554  * @param rx_queue_id
555  *   Rx queue number.
556  *
557  * @return
558  *   0 on success, a negative errno value otherwise and rte_errno is set.
559  */
560 int
561 mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id)
562 {
563         struct priv *priv = dev->data->dev_private;
564         struct mlx5_rxq_data *rxq_data;
565         struct mlx5_rxq_ctrl *rxq_ctrl;
566         struct mlx5_rxq_ibv *rxq_ibv = NULL;
567         struct ibv_cq *ev_cq;
568         void *ev_ctx;
569         int ret;
570
571         rxq_data = (*priv->rxqs)[rx_queue_id];
572         if (!rxq_data) {
573                 rte_errno = EINVAL;
574                 return -rte_errno;
575         }
576         rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
577         if (!rxq_ctrl->irq)
578                 return 0;
579         rxq_ibv = mlx5_rxq_ibv_get(dev, rx_queue_id);
580         if (!rxq_ibv) {
581                 rte_errno = EINVAL;
582                 return -rte_errno;
583         }
584         ret = mlx5_glue->get_cq_event(rxq_ibv->channel, &ev_cq, &ev_ctx);
585         if (ret || ev_cq != rxq_ibv->cq) {
586                 rte_errno = EINVAL;
587                 goto exit;
588         }
589         rxq_data->cq_arm_sn++;
590         mlx5_glue->ack_cq_events(rxq_ibv->cq, 1);
591         return 0;
592 exit:
593         ret = rte_errno; /* Save rte_errno before cleanup. */
594         if (rxq_ibv)
595                 mlx5_rxq_ibv_release(rxq_ibv);
596         DRV_LOG(WARNING, "port %u unable to disable interrupt on Rx queue %d",
597                 dev->data->port_id, rx_queue_id);
598         rte_errno = ret; /* Restore rte_errno. */
599         return -rte_errno;
600 }
601
602 /**
603  * Create the Rx queue Verbs object.
604  *
605  * @param dev
606  *   Pointer to Ethernet device.
607  * @param idx
608  *   Queue index in DPDK Rx queue array
609  *
610  * @return
611  *   The Verbs object initialised, NULL otherwise and rte_errno is set.
612  */
613 struct mlx5_rxq_ibv *
614 mlx5_rxq_ibv_new(struct rte_eth_dev *dev, uint16_t idx)
615 {
616         struct priv *priv = dev->data->dev_private;
617         struct mlx5_rxq_data *rxq_data = (*priv->rxqs)[idx];
618         struct mlx5_rxq_ctrl *rxq_ctrl =
619                 container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
620         struct ibv_wq_attr mod;
621         union {
622                 struct {
623                         struct ibv_cq_init_attr_ex ibv;
624                         struct mlx5dv_cq_init_attr mlx5;
625                 } cq;
626                 struct ibv_wq_init_attr wq;
627                 struct ibv_cq_ex cq_attr;
628         } attr;
629         unsigned int cqe_n = (1 << rxq_data->elts_n) - 1;
630         struct mlx5_rxq_ibv *tmpl;
631         struct mlx5dv_cq cq_info;
632         struct mlx5dv_rwq rwq;
633         unsigned int i;
634         int ret = 0;
635         struct mlx5dv_obj obj;
636         struct mlx5_dev_config *config = &priv->config;
637
638         assert(rxq_data);
639         assert(!rxq_ctrl->ibv);
640         priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_RX_QUEUE;
641         priv->verbs_alloc_ctx.obj = rxq_ctrl;
642         tmpl = rte_calloc_socket(__func__, 1, sizeof(*tmpl), 0,
643                                  rxq_ctrl->socket);
644         if (!tmpl) {
645                 DRV_LOG(ERR,
646                         "port %u Rx queue %u cannot allocate verbs resources",
647                         dev->data->port_id, rxq_ctrl->idx);
648                 rte_errno = ENOMEM;
649                 goto error;
650         }
651         tmpl->rxq_ctrl = rxq_ctrl;
652         /* Use the entire RX mempool as the memory region. */
653         tmpl->mr = mlx5_mr_get(dev, rxq_data->mp);
654         if (!tmpl->mr) {
655                 tmpl->mr = mlx5_mr_new(dev, rxq_data->mp);
656                 if (!tmpl->mr) {
657                         DRV_LOG(ERR, "port %u: memeroy region creation failure",
658                                 dev->data->port_id);
659                         goto error;
660                 }
661         }
662         if (rxq_ctrl->irq) {
663                 tmpl->channel = mlx5_glue->create_comp_channel(priv->ctx);
664                 if (!tmpl->channel) {
665                         DRV_LOG(ERR, "port %u: comp channel creation failure",
666                                 dev->data->port_id);
667                         rte_errno = ENOMEM;
668                         goto error;
669                 }
670         }
671         attr.cq.ibv = (struct ibv_cq_init_attr_ex){
672                 .cqe = cqe_n,
673                 .channel = tmpl->channel,
674                 .comp_mask = 0,
675         };
676         attr.cq.mlx5 = (struct mlx5dv_cq_init_attr){
677                 .comp_mask = 0,
678         };
679         if (config->cqe_comp && !rxq_data->hw_timestamp) {
680                 attr.cq.mlx5.comp_mask |=
681                         MLX5DV_CQ_INIT_ATTR_MASK_COMPRESSED_CQE;
682                 attr.cq.mlx5.cqe_comp_res_format = MLX5DV_CQE_RES_FORMAT_HASH;
683                 /*
684                  * For vectorized Rx, it must not be doubled in order to
685                  * make cq_ci and rq_ci aligned.
686                  */
687                 if (mlx5_rxq_check_vec_support(rxq_data) < 0)
688                         attr.cq.ibv.cqe *= 2;
689         } else if (config->cqe_comp && rxq_data->hw_timestamp) {
690                 DRV_LOG(DEBUG,
691                         "port %u Rx CQE compression is disabled for HW"
692                         " timestamp",
693                         dev->data->port_id);
694         }
695         tmpl->cq = mlx5_glue->cq_ex_to_cq
696                 (mlx5_glue->dv_create_cq(priv->ctx, &attr.cq.ibv,
697                                          &attr.cq.mlx5));
698         if (tmpl->cq == NULL) {
699                 DRV_LOG(ERR, "port %u Rx queue %u CQ creation failure",
700                         dev->data->port_id, idx);
701                 rte_errno = ENOMEM;
702                 goto error;
703         }
704         DRV_LOG(DEBUG, "port %u priv->device_attr.max_qp_wr is %d",
705                 dev->data->port_id, priv->device_attr.orig_attr.max_qp_wr);
706         DRV_LOG(DEBUG, "port %u priv->device_attr.max_sge is %d",
707                 dev->data->port_id, priv->device_attr.orig_attr.max_sge);
708         attr.wq = (struct ibv_wq_init_attr){
709                 .wq_context = NULL, /* Could be useful in the future. */
710                 .wq_type = IBV_WQT_RQ,
711                 /* Max number of outstanding WRs. */
712                 .max_wr = (1 << rxq_data->elts_n) >> rxq_data->sges_n,
713                 /* Max number of scatter/gather elements in a WR. */
714                 .max_sge = 1 << rxq_data->sges_n,
715                 .pd = priv->pd,
716                 .cq = tmpl->cq,
717                 .comp_mask =
718                         IBV_WQ_FLAGS_CVLAN_STRIPPING |
719                         0,
720                 .create_flags = (rxq_data->vlan_strip ?
721                                  IBV_WQ_FLAGS_CVLAN_STRIPPING :
722                                  0),
723         };
724         /* By default, FCS (CRC) is stripped by hardware. */
725         if (rxq_data->crc_present) {
726                 attr.wq.create_flags |= IBV_WQ_FLAGS_SCATTER_FCS;
727                 attr.wq.comp_mask |= IBV_WQ_INIT_ATTR_FLAGS;
728         }
729 #ifdef HAVE_IBV_WQ_FLAG_RX_END_PADDING
730         if (config->hw_padding) {
731                 attr.wq.create_flags |= IBV_WQ_FLAG_RX_END_PADDING;
732                 attr.wq.comp_mask |= IBV_WQ_INIT_ATTR_FLAGS;
733         }
734 #endif
735         tmpl->wq = mlx5_glue->create_wq(priv->ctx, &attr.wq);
736         if (tmpl->wq == NULL) {
737                 DRV_LOG(ERR, "port %u Rx queue %u WQ creation failure",
738                         dev->data->port_id, idx);
739                 rte_errno = ENOMEM;
740                 goto error;
741         }
742         /*
743          * Make sure number of WRs*SGEs match expectations since a queue
744          * cannot allocate more than "desc" buffers.
745          */
746         if (((int)attr.wq.max_wr !=
747              ((1 << rxq_data->elts_n) >> rxq_data->sges_n)) ||
748             ((int)attr.wq.max_sge != (1 << rxq_data->sges_n))) {
749                 DRV_LOG(ERR,
750                         "port %u Rx queue %u requested %u*%u but got %u*%u"
751                         " WRs*SGEs",
752                         dev->data->port_id, idx,
753                         ((1 << rxq_data->elts_n) >> rxq_data->sges_n),
754                         (1 << rxq_data->sges_n),
755                         attr.wq.max_wr, attr.wq.max_sge);
756                 rte_errno = EINVAL;
757                 goto error;
758         }
759         /* Change queue state to ready. */
760         mod = (struct ibv_wq_attr){
761                 .attr_mask = IBV_WQ_ATTR_STATE,
762                 .wq_state = IBV_WQS_RDY,
763         };
764         ret = mlx5_glue->modify_wq(tmpl->wq, &mod);
765         if (ret) {
766                 DRV_LOG(ERR,
767                         "port %u Rx queue %u WQ state to IBV_WQS_RDY failed",
768                         dev->data->port_id, idx);
769                 rte_errno = ret;
770                 goto error;
771         }
772         obj.cq.in = tmpl->cq;
773         obj.cq.out = &cq_info;
774         obj.rwq.in = tmpl->wq;
775         obj.rwq.out = &rwq;
776         ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_CQ | MLX5DV_OBJ_RWQ);
777         if (ret) {
778                 rte_errno = ret;
779                 goto error;
780         }
781         if (cq_info.cqe_size != RTE_CACHE_LINE_SIZE) {
782                 DRV_LOG(ERR,
783                         "port %u wrong MLX5_CQE_SIZE environment variable"
784                         " value: it should be set to %u",
785                         dev->data->port_id, RTE_CACHE_LINE_SIZE);
786                 rte_errno = EINVAL;
787                 goto error;
788         }
789         /* Fill the rings. */
790         rxq_data->wqes = (volatile struct mlx5_wqe_data_seg (*)[])
791                 (uintptr_t)rwq.buf;
792         for (i = 0; (i != (unsigned int)(1 << rxq_data->elts_n)); ++i) {
793                 struct rte_mbuf *buf = (*rxq_data->elts)[i];
794                 volatile struct mlx5_wqe_data_seg *scat = &(*rxq_data->wqes)[i];
795
796                 /* scat->addr must be able to store a pointer. */
797                 assert(sizeof(scat->addr) >= sizeof(uintptr_t));
798                 *scat = (struct mlx5_wqe_data_seg){
799                         .addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(buf,
800                                                                   uintptr_t)),
801                         .byte_count = rte_cpu_to_be_32(DATA_LEN(buf)),
802                         .lkey = tmpl->mr->lkey,
803                 };
804         }
805         rxq_data->rq_db = rwq.dbrec;
806         rxq_data->cqe_n = log2above(cq_info.cqe_cnt);
807         rxq_data->cq_ci = 0;
808         rxq_data->rq_ci = 0;
809         rxq_data->rq_pi = 0;
810         rxq_data->zip = (struct rxq_zip){
811                 .ai = 0,
812         };
813         rxq_data->cq_db = cq_info.dbrec;
814         rxq_data->cqes = (volatile struct mlx5_cqe (*)[])(uintptr_t)cq_info.buf;
815         rxq_data->cq_uar = cq_info.cq_uar;
816         rxq_data->cqn = cq_info.cqn;
817         rxq_data->cq_arm_sn = 0;
818         /* Update doorbell counter. */
819         rxq_data->rq_ci = (1 << rxq_data->elts_n) >> rxq_data->sges_n;
820         rte_wmb();
821         *rxq_data->rq_db = rte_cpu_to_be_32(rxq_data->rq_ci);
822         DRV_LOG(DEBUG, "port %u rxq %u updated with %p", dev->data->port_id,
823                 idx, (void *)&tmpl);
824         rte_atomic32_inc(&tmpl->refcnt);
825         DRV_LOG(DEBUG, "port %u Verbs Rx queue %u: refcnt %d",
826                 dev->data->port_id, idx, rte_atomic32_read(&tmpl->refcnt));
827         LIST_INSERT_HEAD(&priv->rxqsibv, tmpl, next);
828         priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;
829         return tmpl;
830 error:
831         ret = rte_errno; /* Save rte_errno before cleanup. */
832         if (tmpl->wq)
833                 claim_zero(mlx5_glue->destroy_wq(tmpl->wq));
834         if (tmpl->cq)
835                 claim_zero(mlx5_glue->destroy_cq(tmpl->cq));
836         if (tmpl->channel)
837                 claim_zero(mlx5_glue->destroy_comp_channel(tmpl->channel));
838         if (tmpl->mr)
839                 mlx5_mr_release(tmpl->mr);
840         priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;
841         rte_errno = ret; /* Restore rte_errno. */
842         return NULL;
843 }
844
845 /**
846  * Get an Rx queue Verbs object.
847  *
848  * @param dev
849  *   Pointer to Ethernet device.
850  * @param idx
851  *   Queue index in DPDK Rx queue array
852  *
853  * @return
854  *   The Verbs object if it exists.
855  */
856 struct mlx5_rxq_ibv *
857 mlx5_rxq_ibv_get(struct rte_eth_dev *dev, uint16_t idx)
858 {
859         struct priv *priv = dev->data->dev_private;
860         struct mlx5_rxq_data *rxq_data = (*priv->rxqs)[idx];
861         struct mlx5_rxq_ctrl *rxq_ctrl;
862
863         if (idx >= priv->rxqs_n)
864                 return NULL;
865         if (!rxq_data)
866                 return NULL;
867         rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
868         if (rxq_ctrl->ibv) {
869                 mlx5_mr_get(dev, rxq_data->mp);
870                 rte_atomic32_inc(&rxq_ctrl->ibv->refcnt);
871                 DRV_LOG(DEBUG, "port %u Verbs Rx queue %u: refcnt %d",
872                         dev->data->port_id, rxq_ctrl->idx,
873                         rte_atomic32_read(&rxq_ctrl->ibv->refcnt));
874         }
875         return rxq_ctrl->ibv;
876 }
877
878 /**
879  * Release an Rx verbs queue object.
880  *
881  * @param rxq_ibv
882  *   Verbs Rx queue object.
883  *
884  * @return
885  *   1 while a reference on it exists, 0 when freed.
886  */
887 int
888 mlx5_rxq_ibv_release(struct mlx5_rxq_ibv *rxq_ibv)
889 {
890         int ret;
891
892         assert(rxq_ibv);
893         assert(rxq_ibv->wq);
894         assert(rxq_ibv->cq);
895         assert(rxq_ibv->mr);
896         ret = mlx5_mr_release(rxq_ibv->mr);
897         if (!ret)
898                 rxq_ibv->mr = NULL;
899         DRV_LOG(DEBUG, "port %u Verbs Rx queue %u: refcnt %d",
900                 rxq_ibv->rxq_ctrl->priv->dev->data->port_id,
901                 rxq_ibv->rxq_ctrl->idx, rte_atomic32_read(&rxq_ibv->refcnt));
902         if (rte_atomic32_dec_and_test(&rxq_ibv->refcnt)) {
903                 rxq_free_elts(rxq_ibv->rxq_ctrl);
904                 claim_zero(mlx5_glue->destroy_wq(rxq_ibv->wq));
905                 claim_zero(mlx5_glue->destroy_cq(rxq_ibv->cq));
906                 if (rxq_ibv->channel)
907                         claim_zero(mlx5_glue->destroy_comp_channel
908                                    (rxq_ibv->channel));
909                 LIST_REMOVE(rxq_ibv, next);
910                 rte_free(rxq_ibv);
911                 return 0;
912         }
913         return 1;
914 }
915
916 /**
917  * Verify the Verbs Rx queue list is empty
918  *
919  * @param dev
920  *   Pointer to Ethernet device.
921  *
922  * @return
923  *   The number of object not released.
924  */
925 int
926 mlx5_rxq_ibv_verify(struct rte_eth_dev *dev)
927 {
928         struct priv *priv = dev->data->dev_private;
929         int ret = 0;
930         struct mlx5_rxq_ibv *rxq_ibv;
931
932         LIST_FOREACH(rxq_ibv, &priv->rxqsibv, next) {
933                 DRV_LOG(DEBUG, "port %u Verbs Rx queue %u still referenced",
934                         dev->data->port_id, rxq_ibv->rxq_ctrl->idx);
935                 ++ret;
936         }
937         return ret;
938 }
939
940 /**
941  * Return true if a single reference exists on the object.
942  *
943  * @param rxq_ibv
944  *   Verbs Rx queue object.
945  */
946 int
947 mlx5_rxq_ibv_releasable(struct mlx5_rxq_ibv *rxq_ibv)
948 {
949         assert(rxq_ibv);
950         return (rte_atomic32_read(&rxq_ibv->refcnt) == 1);
951 }
952
953 /**
954  * Create a DPDK Rx queue.
955  *
956  * @param dev
957  *   Pointer to Ethernet device.
958  * @param idx
959  *   TX queue index.
960  * @param desc
961  *   Number of descriptors to configure in queue.
962  * @param socket
963  *   NUMA socket on which memory must be allocated.
964  *
965  * @return
966  *   A DPDK queue object on success, NULL otherwise and rte_errno is set.
967  */
968 struct mlx5_rxq_ctrl *
969 mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
970              unsigned int socket, const struct rte_eth_rxconf *conf,
971              struct rte_mempool *mp)
972 {
973         struct priv *priv = dev->data->dev_private;
974         struct mlx5_rxq_ctrl *tmpl;
975         unsigned int mb_len = rte_pktmbuf_data_room_size(mp);
976         struct mlx5_dev_config *config = &priv->config;
977         /*
978          * Always allocate extra slots, even if eventually
979          * the vector Rx will not be used.
980          */
981         const uint16_t desc_n =
982                 desc + config->rx_vec_en * MLX5_VPMD_DESCS_PER_LOOP;
983
984         tmpl = rte_calloc_socket("RXQ", 1,
985                                  sizeof(*tmpl) +
986                                  desc_n * sizeof(struct rte_mbuf *),
987                                  0, socket);
988         if (!tmpl) {
989                 rte_errno = ENOMEM;
990                 return NULL;
991         }
992         tmpl->socket = socket;
993         if (priv->dev->data->dev_conf.intr_conf.rxq)
994                 tmpl->irq = 1;
995         /* Enable scattered packets support for this queue if necessary. */
996         assert(mb_len >= RTE_PKTMBUF_HEADROOM);
997         if (dev->data->dev_conf.rxmode.max_rx_pkt_len <=
998             (mb_len - RTE_PKTMBUF_HEADROOM)) {
999                 tmpl->rxq.sges_n = 0;
1000         } else if (conf->offloads & DEV_RX_OFFLOAD_SCATTER) {
1001                 unsigned int size =
1002                         RTE_PKTMBUF_HEADROOM +
1003                         dev->data->dev_conf.rxmode.max_rx_pkt_len;
1004                 unsigned int sges_n;
1005
1006                 /*
1007                  * Determine the number of SGEs needed for a full packet
1008                  * and round it to the next power of two.
1009                  */
1010                 sges_n = log2above((size / mb_len) + !!(size % mb_len));
1011                 tmpl->rxq.sges_n = sges_n;
1012                 /* Make sure rxq.sges_n did not overflow. */
1013                 size = mb_len * (1 << tmpl->rxq.sges_n);
1014                 size -= RTE_PKTMBUF_HEADROOM;
1015                 if (size < dev->data->dev_conf.rxmode.max_rx_pkt_len) {
1016                         DRV_LOG(ERR,
1017                                 "port %u too many SGEs (%u) needed to handle"
1018                                 " requested maximum packet size %u",
1019                                 dev->data->port_id,
1020                                 1 << sges_n,
1021                                 dev->data->dev_conf.rxmode.max_rx_pkt_len);
1022                         rte_errno = EOVERFLOW;
1023                         goto error;
1024                 }
1025         } else {
1026                 DRV_LOG(WARNING,
1027                         "port %u the requested maximum Rx packet size (%u) is"
1028                         " larger than a single mbuf (%u) and scattered mode has"
1029                         " not been requested",
1030                         dev->data->port_id,
1031                         dev->data->dev_conf.rxmode.max_rx_pkt_len,
1032                         mb_len - RTE_PKTMBUF_HEADROOM);
1033         }
1034         DRV_LOG(DEBUG, "port %u maximum number of segments per packet: %u",
1035                 dev->data->port_id, 1 << tmpl->rxq.sges_n);
1036         if (desc % (1 << tmpl->rxq.sges_n)) {
1037                 DRV_LOG(ERR,
1038                         "port %u number of Rx queue descriptors (%u) is not a"
1039                         " multiple of SGEs per packet (%u)",
1040                         dev->data->port_id,
1041                         desc,
1042                         1 << tmpl->rxq.sges_n);
1043                 rte_errno = EINVAL;
1044                 goto error;
1045         }
1046         /* Toggle RX checksum offload if hardware supports it. */
1047         tmpl->rxq.csum = !!(conf->offloads & DEV_RX_OFFLOAD_CHECKSUM);
1048         tmpl->rxq.csum_l2tun = (!!(conf->offloads & DEV_RX_OFFLOAD_CHECKSUM) &&
1049                                 priv->config.tunnel_en);
1050         tmpl->rxq.hw_timestamp = !!(conf->offloads & DEV_RX_OFFLOAD_TIMESTAMP);
1051         /* Configure VLAN stripping. */
1052         tmpl->rxq.vlan_strip = !!(conf->offloads & DEV_RX_OFFLOAD_VLAN_STRIP);
1053         /* By default, FCS (CRC) is stripped by hardware. */
1054         if (conf->offloads & DEV_RX_OFFLOAD_CRC_STRIP) {
1055                 tmpl->rxq.crc_present = 0;
1056         } else if (config->hw_fcs_strip) {
1057                 tmpl->rxq.crc_present = 1;
1058         } else {
1059                 DRV_LOG(WARNING,
1060                         "port %u CRC stripping has been disabled but will"
1061                         " still be performed by hardware, make sure MLNX_OFED"
1062                         " and firmware are up to date",
1063                         dev->data->port_id);
1064                 tmpl->rxq.crc_present = 0;
1065         }
1066         DRV_LOG(DEBUG,
1067                 "port %u CRC stripping is %s, %u bytes will be subtracted from"
1068                 " incoming frames to hide it",
1069                 dev->data->port_id,
1070                 tmpl->rxq.crc_present ? "disabled" : "enabled",
1071                 tmpl->rxq.crc_present << 2);
1072         /* Save port ID. */
1073         tmpl->rxq.rss_hash = !!priv->rss_conf.rss_hf &&
1074                 (!!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS));
1075         tmpl->rxq.port_id = dev->data->port_id;
1076         tmpl->priv = priv;
1077         tmpl->rxq.mp = mp;
1078         tmpl->rxq.stats.idx = idx;
1079         tmpl->rxq.elts_n = log2above(desc);
1080         tmpl->rxq.elts =
1081                 (struct rte_mbuf *(*)[1 << tmpl->rxq.elts_n])(tmpl + 1);
1082         tmpl->idx = idx;
1083         rte_atomic32_inc(&tmpl->refcnt);
1084         DRV_LOG(DEBUG, "port %u Rx queue %u: refcnt %d", dev->data->port_id,
1085                 idx, rte_atomic32_read(&tmpl->refcnt));
1086         LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next);
1087         return tmpl;
1088 error:
1089         rte_free(tmpl);
1090         return NULL;
1091 }
1092
1093 /**
1094  * Get a Rx queue.
1095  *
1096  * @param dev
1097  *   Pointer to Ethernet device.
1098  * @param idx
1099  *   TX queue index.
1100  *
1101  * @return
1102  *   A pointer to the queue if it exists, NULL otherwise.
1103  */
1104 struct mlx5_rxq_ctrl *
1105 mlx5_rxq_get(struct rte_eth_dev *dev, uint16_t idx)
1106 {
1107         struct priv *priv = dev->data->dev_private;
1108         struct mlx5_rxq_ctrl *rxq_ctrl = NULL;
1109
1110         if ((*priv->rxqs)[idx]) {
1111                 rxq_ctrl = container_of((*priv->rxqs)[idx],
1112                                         struct mlx5_rxq_ctrl,
1113                                         rxq);
1114                 mlx5_rxq_ibv_get(dev, idx);
1115                 rte_atomic32_inc(&rxq_ctrl->refcnt);
1116                 DRV_LOG(DEBUG, "port %u Rx queue %u: refcnt %d",
1117                         dev->data->port_id, rxq_ctrl->idx,
1118                         rte_atomic32_read(&rxq_ctrl->refcnt));
1119         }
1120         return rxq_ctrl;
1121 }
1122
1123 /**
1124  * Release a Rx queue.
1125  *
1126  * @param dev
1127  *   Pointer to Ethernet device.
1128  * @param idx
1129  *   TX queue index.
1130  *
1131  * @return
1132  *   1 while a reference on it exists, 0 when freed.
1133  */
1134 int
1135 mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
1136 {
1137         struct priv *priv = dev->data->dev_private;
1138         struct mlx5_rxq_ctrl *rxq_ctrl;
1139
1140         if (!(*priv->rxqs)[idx])
1141                 return 0;
1142         rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq);
1143         assert(rxq_ctrl->priv);
1144         if (rxq_ctrl->ibv && !mlx5_rxq_ibv_release(rxq_ctrl->ibv))
1145                 rxq_ctrl->ibv = NULL;
1146         DRV_LOG(DEBUG, "port %u Rx queue %u: refcnt %d", dev->data->port_id,
1147                 rxq_ctrl->idx, rte_atomic32_read(&rxq_ctrl->refcnt));
1148         if (rte_atomic32_dec_and_test(&rxq_ctrl->refcnt)) {
1149                 LIST_REMOVE(rxq_ctrl, next);
1150                 rte_free(rxq_ctrl);
1151                 (*priv->rxqs)[idx] = NULL;
1152                 return 0;
1153         }
1154         return 1;
1155 }
1156
1157 /**
1158  * Verify if the queue can be released.
1159  *
1160  * @param dev
1161  *   Pointer to Ethernet device.
1162  * @param idx
1163  *   TX queue index.
1164  *
1165  * @return
1166  *   1 if the queue can be released, negative errno otherwise and rte_errno is
1167  *   set.
1168  */
1169 int
1170 mlx5_rxq_releasable(struct rte_eth_dev *dev, uint16_t idx)
1171 {
1172         struct priv *priv = dev->data->dev_private;
1173         struct mlx5_rxq_ctrl *rxq_ctrl;
1174
1175         if (!(*priv->rxqs)[idx]) {
1176                 rte_errno = EINVAL;
1177                 return -rte_errno;
1178         }
1179         rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq);
1180         return (rte_atomic32_read(&rxq_ctrl->refcnt) == 1);
1181 }
1182
1183 /**
1184  * Verify the Rx Queue list is empty
1185  *
1186  * @param dev
1187  *   Pointer to Ethernet device.
1188  *
1189  * @return
1190  *   The number of object not released.
1191  */
1192 int
1193 mlx5_rxq_verify(struct rte_eth_dev *dev)
1194 {
1195         struct priv *priv = dev->data->dev_private;
1196         struct mlx5_rxq_ctrl *rxq_ctrl;
1197         int ret = 0;
1198
1199         LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) {
1200                 DRV_LOG(DEBUG, "port %u Rx Queue %u still referenced",
1201                         dev->data->port_id, rxq_ctrl->idx);
1202                 ++ret;
1203         }
1204         return ret;
1205 }
1206
1207 /**
1208  * Create an indirection table.
1209  *
1210  * @param dev
1211  *   Pointer to Ethernet device.
1212  * @param queues
1213  *   Queues entering in the indirection table.
1214  * @param queues_n
1215  *   Number of queues in the array.
1216  *
1217  * @return
1218  *   The Verbs object initialised, NULL otherwise and rte_errno is set.
1219  */
1220 struct mlx5_ind_table_ibv *
1221 mlx5_ind_table_ibv_new(struct rte_eth_dev *dev, uint16_t queues[],
1222                        uint16_t queues_n)
1223 {
1224         struct priv *priv = dev->data->dev_private;
1225         struct mlx5_ind_table_ibv *ind_tbl;
1226         const unsigned int wq_n = rte_is_power_of_2(queues_n) ?
1227                 log2above(queues_n) :
1228                 log2above(priv->config.ind_table_max_size);
1229         struct ibv_wq *wq[1 << wq_n];
1230         unsigned int i;
1231         unsigned int j;
1232
1233         ind_tbl = rte_calloc(__func__, 1, sizeof(*ind_tbl) +
1234                              queues_n * sizeof(uint16_t), 0);
1235         if (!ind_tbl) {
1236                 rte_errno = ENOMEM;
1237                 return NULL;
1238         }
1239         for (i = 0; i != queues_n; ++i) {
1240                 struct mlx5_rxq_ctrl *rxq = mlx5_rxq_get(dev, queues[i]);
1241
1242                 if (!rxq)
1243                         goto error;
1244                 wq[i] = rxq->ibv->wq;
1245                 ind_tbl->queues[i] = queues[i];
1246         }
1247         ind_tbl->queues_n = queues_n;
1248         /* Finalise indirection table. */
1249         for (j = 0; i != (unsigned int)(1 << wq_n); ++i, ++j)
1250                 wq[i] = wq[j];
1251         ind_tbl->ind_table = mlx5_glue->create_rwq_ind_table
1252                 (priv->ctx,
1253                  &(struct ibv_rwq_ind_table_init_attr){
1254                         .log_ind_tbl_size = wq_n,
1255                         .ind_tbl = wq,
1256                         .comp_mask = 0,
1257                  });
1258         if (!ind_tbl->ind_table) {
1259                 rte_errno = errno;
1260                 goto error;
1261         }
1262         rte_atomic32_inc(&ind_tbl->refcnt);
1263         LIST_INSERT_HEAD(&priv->ind_tbls, ind_tbl, next);
1264         DRV_LOG(DEBUG, "port %u indirection table %p: refcnt %d",
1265                 dev->data->port_id, (void *)ind_tbl,
1266                 rte_atomic32_read(&ind_tbl->refcnt));
1267         return ind_tbl;
1268 error:
1269         rte_free(ind_tbl);
1270         DRV_LOG(DEBUG, "port %u cannot create indirection table",
1271                 dev->data->port_id);
1272         return NULL;
1273 }
1274
1275 /**
1276  * Get an indirection table.
1277  *
1278  * @param dev
1279  *   Pointer to Ethernet device.
1280  * @param queues
1281  *   Queues entering in the indirection table.
1282  * @param queues_n
1283  *   Number of queues in the array.
1284  *
1285  * @return
1286  *   An indirection table if found.
1287  */
1288 struct mlx5_ind_table_ibv *
1289 mlx5_ind_table_ibv_get(struct rte_eth_dev *dev, uint16_t queues[],
1290                        uint16_t queues_n)
1291 {
1292         struct priv *priv = dev->data->dev_private;
1293         struct mlx5_ind_table_ibv *ind_tbl;
1294
1295         LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) {
1296                 if ((ind_tbl->queues_n == queues_n) &&
1297                     (memcmp(ind_tbl->queues, queues,
1298                             ind_tbl->queues_n * sizeof(ind_tbl->queues[0]))
1299                      == 0))
1300                         break;
1301         }
1302         if (ind_tbl) {
1303                 unsigned int i;
1304
1305                 rte_atomic32_inc(&ind_tbl->refcnt);
1306                 DRV_LOG(DEBUG, "port %u indirection table %p: refcnt %d",
1307                         dev->data->port_id, (void *)ind_tbl,
1308                         rte_atomic32_read(&ind_tbl->refcnt));
1309                 for (i = 0; i != ind_tbl->queues_n; ++i)
1310                         mlx5_rxq_get(dev, ind_tbl->queues[i]);
1311         }
1312         return ind_tbl;
1313 }
1314
1315 /**
1316  * Release an indirection table.
1317  *
1318  * @param dev
1319  *   Pointer to Ethernet device.
1320  * @param ind_table
1321  *   Indirection table to release.
1322  *
1323  * @return
1324  *   1 while a reference on it exists, 0 when freed.
1325  */
1326 int
1327 mlx5_ind_table_ibv_release(struct rte_eth_dev *dev,
1328                            struct mlx5_ind_table_ibv *ind_tbl)
1329 {
1330         unsigned int i;
1331
1332         DRV_LOG(DEBUG, "port %u indirection table %p: refcnt %d",
1333                 ((struct priv *)dev->data->dev_private)->port,
1334                 (void *)ind_tbl, rte_atomic32_read(&ind_tbl->refcnt));
1335         if (rte_atomic32_dec_and_test(&ind_tbl->refcnt))
1336                 claim_zero(mlx5_glue->destroy_rwq_ind_table
1337                            (ind_tbl->ind_table));
1338         for (i = 0; i != ind_tbl->queues_n; ++i)
1339                 claim_nonzero(mlx5_rxq_release(dev, ind_tbl->queues[i]));
1340         if (!rte_atomic32_read(&ind_tbl->refcnt)) {
1341                 LIST_REMOVE(ind_tbl, next);
1342                 rte_free(ind_tbl);
1343                 return 0;
1344         }
1345         return 1;
1346 }
1347
1348 /**
1349  * Verify the Rx Queue list is empty
1350  *
1351  * @param dev
1352  *   Pointer to Ethernet device.
1353  *
1354  * @return
1355  *   The number of object not released.
1356  */
1357 int
1358 mlx5_ind_table_ibv_verify(struct rte_eth_dev *dev)
1359 {
1360         struct priv *priv = dev->data->dev_private;
1361         struct mlx5_ind_table_ibv *ind_tbl;
1362         int ret = 0;
1363
1364         LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) {
1365                 DRV_LOG(DEBUG,
1366                         "port %u Verbs indirection table %p still referenced",
1367                         dev->data->port_id, (void *)ind_tbl);
1368                 ++ret;
1369         }
1370         return ret;
1371 }
1372
1373 /**
1374  * Create an Rx Hash queue.
1375  *
1376  * @param dev
1377  *   Pointer to Ethernet device.
1378  * @param rss_key
1379  *   RSS key for the Rx hash queue.
1380  * @param rss_key_len
1381  *   RSS key length.
1382  * @param hash_fields
1383  *   Verbs protocol hash field to make the RSS on.
1384  * @param queues
1385  *   Queues entering in hash queue. In case of empty hash_fields only the
1386  *   first queue index will be taken for the indirection table.
1387  * @param queues_n
1388  *   Number of queues.
1389  *
1390  * @return
1391  *   The Verbs object initialised, NULL otherwise and rte_errno is set.
1392  */
1393 struct mlx5_hrxq *
1394 mlx5_hrxq_new(struct rte_eth_dev *dev, uint8_t *rss_key, uint8_t rss_key_len,
1395               uint64_t hash_fields, uint16_t queues[], uint16_t queues_n)
1396 {
1397         struct priv *priv = dev->data->dev_private;
1398         struct mlx5_hrxq *hrxq;
1399         struct mlx5_ind_table_ibv *ind_tbl;
1400         struct ibv_qp *qp;
1401         int err;
1402
1403         queues_n = hash_fields ? queues_n : 1;
1404         ind_tbl = mlx5_ind_table_ibv_get(dev, queues, queues_n);
1405         if (!ind_tbl)
1406                 ind_tbl = mlx5_ind_table_ibv_new(dev, queues, queues_n);
1407         if (!ind_tbl) {
1408                 rte_errno = ENOMEM;
1409                 return NULL;
1410         }
1411         qp = mlx5_glue->create_qp_ex
1412                 (priv->ctx,
1413                  &(struct ibv_qp_init_attr_ex){
1414                         .qp_type = IBV_QPT_RAW_PACKET,
1415                         .comp_mask =
1416                                 IBV_QP_INIT_ATTR_PD |
1417                                 IBV_QP_INIT_ATTR_IND_TABLE |
1418                                 IBV_QP_INIT_ATTR_RX_HASH,
1419                         .rx_hash_conf = (struct ibv_rx_hash_conf){
1420                                 .rx_hash_function = IBV_RX_HASH_FUNC_TOEPLITZ,
1421                                 .rx_hash_key_len = rss_key_len,
1422                                 .rx_hash_key = rss_key,
1423                                 .rx_hash_fields_mask = hash_fields,
1424                         },
1425                         .rwq_ind_tbl = ind_tbl->ind_table,
1426                         .pd = priv->pd,
1427                  });
1428         if (!qp) {
1429                 rte_errno = errno;
1430                 goto error;
1431         }
1432         hrxq = rte_calloc(__func__, 1, sizeof(*hrxq) + rss_key_len, 0);
1433         if (!hrxq)
1434                 goto error;
1435         hrxq->ind_table = ind_tbl;
1436         hrxq->qp = qp;
1437         hrxq->rss_key_len = rss_key_len;
1438         hrxq->hash_fields = hash_fields;
1439         memcpy(hrxq->rss_key, rss_key, rss_key_len);
1440         rte_atomic32_inc(&hrxq->refcnt);
1441         LIST_INSERT_HEAD(&priv->hrxqs, hrxq, next);
1442         DRV_LOG(DEBUG, "port %u hash Rx queue %p: refcnt %d",
1443                 dev->data->port_id, (void *)hrxq,
1444                 rte_atomic32_read(&hrxq->refcnt));
1445         return hrxq;
1446 error:
1447         err = rte_errno; /* Save rte_errno before cleanup. */
1448         mlx5_ind_table_ibv_release(dev, ind_tbl);
1449         if (qp)
1450                 claim_zero(mlx5_glue->destroy_qp(qp));
1451         rte_errno = err; /* Restore rte_errno. */
1452         return NULL;
1453 }
1454
1455 /**
1456  * Get an Rx Hash queue.
1457  *
1458  * @param dev
1459  *   Pointer to Ethernet device.
1460  * @param rss_conf
1461  *   RSS configuration for the Rx hash queue.
1462  * @param queues
1463  *   Queues entering in hash queue. In case of empty hash_fields only the
1464  *   first queue index will be taken for the indirection table.
1465  * @param queues_n
1466  *   Number of queues.
1467  *
1468  * @return
1469  *   An hash Rx queue on success.
1470  */
1471 struct mlx5_hrxq *
1472 mlx5_hrxq_get(struct rte_eth_dev *dev, uint8_t *rss_key, uint8_t rss_key_len,
1473               uint64_t hash_fields, uint16_t queues[], uint16_t queues_n)
1474 {
1475         struct priv *priv = dev->data->dev_private;
1476         struct mlx5_hrxq *hrxq;
1477
1478         queues_n = hash_fields ? queues_n : 1;
1479         LIST_FOREACH(hrxq, &priv->hrxqs, next) {
1480                 struct mlx5_ind_table_ibv *ind_tbl;
1481
1482                 if (hrxq->rss_key_len != rss_key_len)
1483                         continue;
1484                 if (memcmp(hrxq->rss_key, rss_key, rss_key_len))
1485                         continue;
1486                 if (hrxq->hash_fields != hash_fields)
1487                         continue;
1488                 ind_tbl = mlx5_ind_table_ibv_get(dev, queues, queues_n);
1489                 if (!ind_tbl)
1490                         continue;
1491                 if (ind_tbl != hrxq->ind_table) {
1492                         mlx5_ind_table_ibv_release(dev, ind_tbl);
1493                         continue;
1494                 }
1495                 rte_atomic32_inc(&hrxq->refcnt);
1496                 DRV_LOG(DEBUG, "port %u hash Rx queue %p: refcnt %d",
1497                         dev->data->port_id, (void *)hrxq,
1498                         rte_atomic32_read(&hrxq->refcnt));
1499                 return hrxq;
1500         }
1501         return NULL;
1502 }
1503
1504 /**
1505  * Release the hash Rx queue.
1506  *
1507  * @param dev
1508  *   Pointer to Ethernet device.
1509  * @param hrxq
1510  *   Pointer to Hash Rx queue to release.
1511  *
1512  * @return
1513  *   1 while a reference on it exists, 0 when freed.
1514  */
1515 int
1516 mlx5_hrxq_release(struct rte_eth_dev *dev, struct mlx5_hrxq *hrxq)
1517 {
1518         DRV_LOG(DEBUG, "port %u hash Rx queue %p: refcnt %d",
1519                 ((struct priv *)dev->data->dev_private)->port,
1520                 (void *)hrxq, rte_atomic32_read(&hrxq->refcnt));
1521         if (rte_atomic32_dec_and_test(&hrxq->refcnt)) {
1522                 claim_zero(mlx5_glue->destroy_qp(hrxq->qp));
1523                 mlx5_ind_table_ibv_release(dev, hrxq->ind_table);
1524                 LIST_REMOVE(hrxq, next);
1525                 rte_free(hrxq);
1526                 return 0;
1527         }
1528         claim_nonzero(mlx5_ind_table_ibv_release(dev, hrxq->ind_table));
1529         return 1;
1530 }
1531
1532 /**
1533  * Verify the Rx Queue list is empty
1534  *
1535  * @param dev
1536  *   Pointer to Ethernet device.
1537  *
1538  * @return
1539  *   The number of object not released.
1540  */
1541 int
1542 mlx5_hrxq_ibv_verify(struct rte_eth_dev *dev)
1543 {
1544         struct priv *priv = dev->data->dev_private;
1545         struct mlx5_hrxq *hrxq;
1546         int ret = 0;
1547
1548         LIST_FOREACH(hrxq, &priv->hrxqs, next) {
1549                 DRV_LOG(DEBUG,
1550                         "port %u Verbs hash Rx queue %p still referenced",
1551                         dev->data->port_id, (void *)hrxq);
1552                 ++ret;
1553         }
1554         return ret;
1555 }