708e3a33696a46dff41acbb19e6a4e10f43bea39
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2015 6WIND S.A.
3  * Copyright 2015 Mellanox Technologies, Ltd
4  */
5
6 #include <stddef.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <errno.h>
12
13 #include <ethdev_driver.h>
14 #include <rte_bus_pci.h>
15 #include <rte_mbuf.h>
16 #include <rte_common.h>
17 #include <rte_interrupts.h>
18 #include <rte_malloc.h>
19 #include <rte_string_fns.h>
20 #include <rte_rwlock.h>
21 #include <rte_cycles.h>
22
23 #include <mlx5_malloc.h>
24
25 #include "mlx5_rxtx.h"
26 #include "mlx5_rx.h"
27 #include "mlx5_autoconf.h"
28
29 /**
30  * Get the interface index from device name.
31  *
32  * @param[in] dev
33  *   Pointer to Ethernet device.
34  *
35  * @return
36  *   Nonzero interface index on success, zero otherwise and rte_errno is set.
37  */
38 unsigned int
39 mlx5_ifindex(const struct rte_eth_dev *dev)
40 {
41         struct mlx5_priv *priv = dev->data->dev_private;
42         unsigned int ifindex;
43
44         MLX5_ASSERT(priv);
45         MLX5_ASSERT(priv->if_index);
46         if (priv->master && priv->sh->bond.ifindex > 0)
47                 ifindex = priv->sh->bond.ifindex;
48         else
49                 ifindex = priv->if_index;
50         if (!ifindex)
51                 rte_errno = ENXIO;
52         return ifindex;
53 }
54
55 /**
56  * DPDK callback for Ethernet device configuration.
57  *
58  * @param dev
59  *   Pointer to Ethernet device structure.
60  *
61  * @return
62  *   0 on success, a negative errno value otherwise and rte_errno is set.
63  */
64 int
65 mlx5_dev_configure(struct rte_eth_dev *dev)
66 {
67         struct mlx5_priv *priv = dev->data->dev_private;
68         unsigned int rxqs_n = dev->data->nb_rx_queues;
69         unsigned int txqs_n = dev->data->nb_tx_queues;
70         const uint8_t use_app_rss_key =
71                 !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
72         int ret = 0;
73
74         if (use_app_rss_key &&
75             (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
76              MLX5_RSS_HASH_KEY_LEN)) {
77                 DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long",
78                         dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN));
79                 rte_errno = EINVAL;
80                 return -rte_errno;
81         }
82         priv->rss_conf.rss_key =
83                 mlx5_realloc(priv->rss_conf.rss_key, MLX5_MEM_RTE,
84                             MLX5_RSS_HASH_KEY_LEN, 0, SOCKET_ID_ANY);
85         if (!priv->rss_conf.rss_key) {
86                 DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
87                         dev->data->port_id, rxqs_n);
88                 rte_errno = ENOMEM;
89                 return -rte_errno;
90         }
91
92         if ((dev->data->dev_conf.txmode.offloads &
93                         DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) &&
94                         rte_mbuf_dyn_tx_timestamp_register(NULL, NULL) != 0) {
95                 DRV_LOG(ERR, "port %u cannot register Tx timestamp field/flag",
96                         dev->data->port_id);
97                 return -rte_errno;
98         }
99         memcpy(priv->rss_conf.rss_key,
100                use_app_rss_key ?
101                dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
102                rss_hash_default_key,
103                MLX5_RSS_HASH_KEY_LEN);
104         priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN;
105         priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
106         priv->rxqs = (void *)dev->data->rx_queues;
107         priv->txqs = (void *)dev->data->tx_queues;
108         if (txqs_n != priv->txqs_n) {
109                 DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
110                         dev->data->port_id, priv->txqs_n, txqs_n);
111                 priv->txqs_n = txqs_n;
112         }
113         if (rxqs_n > priv->config.ind_table_max_size) {
114                 DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
115                         dev->data->port_id, rxqs_n);
116                 rte_errno = EINVAL;
117                 return -rte_errno;
118         }
119         if (rxqs_n != priv->rxqs_n) {
120                 DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
121                         dev->data->port_id, priv->rxqs_n, rxqs_n);
122                 priv->rxqs_n = rxqs_n;
123         }
124         priv->skip_default_rss_reta = 0;
125         ret = mlx5_proc_priv_init(dev);
126         if (ret)
127                 return ret;
128         return 0;
129 }
130
131 /**
132  * Configure default RSS reta.
133  *
134  * @param dev
135  *   Pointer to Ethernet device structure.
136  *
137  * @return
138  *   0 on success, a negative errno value otherwise and rte_errno is set.
139  */
140 int
141 mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
142 {
143         struct mlx5_priv *priv = dev->data->dev_private;
144         unsigned int rxqs_n = dev->data->nb_rx_queues;
145         unsigned int i;
146         unsigned int j;
147         unsigned int reta_idx_n;
148         int ret = 0;
149         unsigned int *rss_queue_arr = NULL;
150         unsigned int rss_queue_n = 0;
151
152         if (priv->skip_default_rss_reta)
153                 return ret;
154         rss_queue_arr = mlx5_malloc(0, rxqs_n * sizeof(unsigned int), 0,
155                                     SOCKET_ID_ANY);
156         if (!rss_queue_arr) {
157                 DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)",
158                         dev->data->port_id, rxqs_n);
159                 rte_errno = ENOMEM;
160                 return -rte_errno;
161         }
162         for (i = 0, j = 0; i < rxqs_n; i++) {
163                 struct mlx5_rxq_data *rxq_data;
164                 struct mlx5_rxq_ctrl *rxq_ctrl;
165
166                 rxq_data = (*priv->rxqs)[i];
167                 rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
168                 if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
169                         rss_queue_arr[j++] = i;
170         }
171         rss_queue_n = j;
172         if (rss_queue_n > priv->config.ind_table_max_size) {
173                 DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
174                         dev->data->port_id, rss_queue_n);
175                 rte_errno = EINVAL;
176                 mlx5_free(rss_queue_arr);
177                 return -rte_errno;
178         }
179         DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
180                 dev->data->port_id, priv->rxqs_n, rxqs_n);
181         priv->rxqs_n = rxqs_n;
182         /*
183          * If the requested number of RX queues is not a power of two,
184          * use the maximum indirection table size for better balancing.
185          * The result is always rounded to the next power of two.
186          */
187         reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ?
188                                 priv->config.ind_table_max_size :
189                                 rss_queue_n));
190         ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
191         if (ret) {
192                 mlx5_free(rss_queue_arr);
193                 return ret;
194         }
195         /*
196          * When the number of RX queues is not a power of two,
197          * the remaining table entries are padded with reused WQs
198          * and hashes are not spread uniformly.
199          */
200         for (i = 0, j = 0; (i != reta_idx_n); ++i) {
201                 (*priv->reta_idx)[i] = rss_queue_arr[j];
202                 if (++j == rss_queue_n)
203                         j = 0;
204         }
205         mlx5_free(rss_queue_arr);
206         return ret;
207 }
208
209 /**
210  * Sets default tuning parameters.
211  *
212  * @param dev
213  *   Pointer to Ethernet device.
214  * @param[out] info
215  *   Info structure output buffer.
216  */
217 static void
218 mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
219 {
220         struct mlx5_priv *priv = dev->data->dev_private;
221
222         /* Minimum CPU utilization. */
223         info->default_rxportconf.ring_size = 256;
224         info->default_txportconf.ring_size = 256;
225         info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST;
226         info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST;
227         if ((priv->link_speed_capa & ETH_LINK_SPEED_200G) |
228                 (priv->link_speed_capa & ETH_LINK_SPEED_100G)) {
229                 info->default_rxportconf.nb_queues = 16;
230                 info->default_txportconf.nb_queues = 16;
231                 if (dev->data->nb_rx_queues > 2 ||
232                     dev->data->nb_tx_queues > 2) {
233                         /* Max Throughput. */
234                         info->default_rxportconf.ring_size = 2048;
235                         info->default_txportconf.ring_size = 2048;
236                 }
237         } else {
238                 info->default_rxportconf.nb_queues = 8;
239                 info->default_txportconf.nb_queues = 8;
240                 if (dev->data->nb_rx_queues > 2 ||
241                     dev->data->nb_tx_queues > 2) {
242                         /* Max Throughput. */
243                         info->default_rxportconf.ring_size = 4096;
244                         info->default_txportconf.ring_size = 4096;
245                 }
246         }
247 }
248
249 /**
250  * Sets tx mbuf limiting parameters.
251  *
252  * @param dev
253  *   Pointer to Ethernet device.
254  * @param[out] info
255  *   Info structure output buffer.
256  */
257 static void
258 mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
259 {
260         struct mlx5_priv *priv = dev->data->dev_private;
261         struct mlx5_dev_config *config = &priv->config;
262         unsigned int inlen;
263         uint16_t nb_max;
264
265         inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ?
266                 MLX5_SEND_DEF_INLINE_LEN :
267                 (unsigned int)config->txq_inline_max;
268         MLX5_ASSERT(config->txq_inline_min >= 0);
269         inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min);
270         inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX +
271                                MLX5_ESEG_MIN_INLINE_SIZE -
272                                MLX5_WQE_CSEG_SIZE -
273                                MLX5_WQE_ESEG_SIZE -
274                                MLX5_WQE_DSEG_SIZE * 2);
275         nb_max = (MLX5_WQE_SIZE_MAX +
276                   MLX5_ESEG_MIN_INLINE_SIZE -
277                   MLX5_WQE_CSEG_SIZE -
278                   MLX5_WQE_ESEG_SIZE -
279                   MLX5_WQE_DSEG_SIZE -
280                   inlen) / MLX5_WSEG_SIZE;
281         info->tx_desc_lim.nb_seg_max = nb_max;
282         info->tx_desc_lim.nb_mtu_seg_max = nb_max;
283 }
284
285 /**
286  * DPDK callback to get information about the device.
287  *
288  * @param dev
289  *   Pointer to Ethernet device structure.
290  * @param[out] info
291  *   Info structure output buffer.
292  */
293 int
294 mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
295 {
296         struct mlx5_priv *priv = dev->data->dev_private;
297         struct mlx5_dev_config *config = &priv->config;
298         unsigned int max;
299
300         /* FIXME: we should ask the device for these values. */
301         info->min_rx_bufsize = 32;
302         info->max_rx_pktlen = 65536;
303         info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE;
304         /*
305          * Since we need one CQ per QP, the limit is the minimum number
306          * between the two values.
307          */
308         max = RTE_MIN(priv->sh->device_attr.max_cq,
309                       priv->sh->device_attr.max_qp);
310         /* max_rx_queues is uint16_t. */
311         max = RTE_MIN(max, (unsigned int)UINT16_MAX);
312         info->max_rx_queues = max;
313         info->max_tx_queues = max;
314         info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES;
315         info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
316         info->rx_seg_capa.max_nseg = MLX5_MAX_RXQ_NSEG;
317         info->rx_seg_capa.multi_pools = !config->mprq.enabled;
318         info->rx_seg_capa.offset_allowed = !config->mprq.enabled;
319         info->rx_seg_capa.offset_align_log2 = 0;
320         info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
321                                  info->rx_queue_offload_capa);
322         info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
323         info->if_index = mlx5_ifindex(dev);
324         info->reta_size = priv->reta_idx_n ?
325                 priv->reta_idx_n : config->ind_table_max_size;
326         info->hash_key_size = MLX5_RSS_HASH_KEY_LEN;
327         info->speed_capa = priv->link_speed_capa;
328         info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
329         mlx5_set_default_params(dev, info);
330         mlx5_set_txlimit_params(dev, info);
331         info->switch_info.name = dev->data->name;
332         info->switch_info.domain_id = priv->domain_id;
333         info->switch_info.port_id = priv->representor_id;
334         if (priv->representor) {
335                 uint16_t port_id;
336
337                 MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
338                         struct mlx5_priv *opriv =
339                                 rte_eth_devices[port_id].data->dev_private;
340
341                         if (!opriv ||
342                             opriv->representor ||
343                             opriv->sh != priv->sh ||
344                             opriv->domain_id != priv->domain_id)
345                                 continue;
346                         /*
347                          * Override switch name with that of the master
348                          * device.
349                          */
350                         info->switch_info.name = opriv->dev_data->name;
351                         break;
352                 }
353         }
354         return 0;
355 }
356
357 /**
358  * Calculate representor ID from port switch info.
359  *
360  * Uint16 representor ID bits definition:
361  *   pf: 2
362  *   type: 2
363  *   vf/sf: 12
364  *
365  * @param info
366  *   Port switch info.
367  * @param hpf_type
368  *   Use this type if port is HPF.
369  *
370  * @return
371  *   Encoded representor ID.
372  */
373 uint16_t
374 mlx5_representor_id_encode(const struct mlx5_switch_info *info,
375                            enum rte_eth_representor_type hpf_type)
376 {
377         enum rte_eth_representor_type type = RTE_ETH_REPRESENTOR_VF;
378         uint16_t repr = info->port_name;
379
380         if (info->representor == 0)
381                 return UINT16_MAX;
382         if (info->name_type == MLX5_PHYS_PORT_NAME_TYPE_PFSF)
383                 type = RTE_ETH_REPRESENTOR_SF;
384         if (info->name_type == MLX5_PHYS_PORT_NAME_TYPE_PFHPF) {
385                 type = hpf_type;
386                 repr = UINT16_MAX;
387         }
388         return MLX5_REPRESENTOR_ID(info->pf_num, type, repr);
389 }
390
391 /**
392  * DPDK callback to get information about representor.
393  *
394  * Representor ID bits definition:
395  *   vf/sf: 12
396  *   type: 2
397  *   pf: 2
398  *
399  * @param dev
400  *   Pointer to Ethernet device structure.
401  * @param[out] info
402  *   Nullable info structure output buffer.
403  *
404  * @return
405  *   negative on error, or the number of representor ranges.
406  */
407 int
408 mlx5_representor_info_get(struct rte_eth_dev *dev,
409                           struct rte_eth_representor_info *info)
410 {
411         struct mlx5_priv *priv = dev->data->dev_private;
412         int n_type = 4; /* Representor types, VF, HPF@VF, SF and HPF@SF. */
413         int n_pf = 2; /* Number of PFs. */
414         int i = 0, pf;
415
416         if (info == NULL)
417                 goto out;
418         info->controller = 0;
419         info->pf = priv->pf_bond >= 0 ? priv->pf_bond : 0;
420         for (pf = 0; pf < n_pf; ++pf) {
421                 /* VF range. */
422                 info->ranges[i].type = RTE_ETH_REPRESENTOR_VF;
423                 info->ranges[i].controller = 0;
424                 info->ranges[i].pf = pf;
425                 info->ranges[i].vf = 0;
426                 info->ranges[i].id_base =
427                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, 0);
428                 info->ranges[i].id_end =
429                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
430                 snprintf(info->ranges[i].name,
431                          sizeof(info->ranges[i].name), "pf%dvf", pf);
432                 i++;
433                 /* HPF range of VF type. */
434                 info->ranges[i].type = RTE_ETH_REPRESENTOR_VF;
435                 info->ranges[i].controller = 0;
436                 info->ranges[i].pf = pf;
437                 info->ranges[i].vf = UINT16_MAX;
438                 info->ranges[i].id_base =
439                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
440                 info->ranges[i].id_end =
441                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
442                 snprintf(info->ranges[i].name,
443                          sizeof(info->ranges[i].name), "pf%dvf", pf);
444                 i++;
445                 /* SF range. */
446                 info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
447                 info->ranges[i].controller = 0;
448                 info->ranges[i].pf = pf;
449                 info->ranges[i].vf = 0;
450                 info->ranges[i].id_base =
451                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, 0);
452                 info->ranges[i].id_end =
453                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
454                 snprintf(info->ranges[i].name,
455                          sizeof(info->ranges[i].name), "pf%dsf", pf);
456                 i++;
457                 /* HPF range of SF type. */
458                 info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
459                 info->ranges[i].controller = 0;
460                 info->ranges[i].pf = pf;
461                 info->ranges[i].vf = UINT16_MAX;
462                 info->ranges[i].id_base =
463                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
464                 info->ranges[i].id_end =
465                         MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
466                 snprintf(info->ranges[i].name,
467                          sizeof(info->ranges[i].name), "pf%dsf", pf);
468                 i++;
469         }
470 out:
471         return n_type * n_pf;
472 }
473
474 /**
475  * Get firmware version of a device.
476  *
477  * @param dev
478  *   Ethernet device port.
479  * @param fw_ver
480  *   String output allocated by caller.
481  * @param fw_size
482  *   Size of the output string, including terminating null byte.
483  *
484  * @return
485  *   0 on success, or the size of the non truncated string if too big.
486  */
487 int
488 mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
489 {
490         struct mlx5_priv *priv = dev->data->dev_private;
491         struct mlx5_dev_attr *attr = &priv->sh->device_attr;
492         size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1;
493
494         if (fw_size < size)
495                 return size;
496         if (fw_ver != NULL)
497                 strlcpy(fw_ver, attr->fw_ver, fw_size);
498         return 0;
499 }
500
501 /**
502  * Get supported packet types.
503  *
504  * @param dev
505  *   Pointer to Ethernet device structure.
506  *
507  * @return
508  *   A pointer to the supported Packet types array.
509  */
510 const uint32_t *
511 mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
512 {
513         static const uint32_t ptypes[] = {
514                 /* refers to rxq_cq_to_pkt_type() */
515                 RTE_PTYPE_L2_ETHER,
516                 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
517                 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
518                 RTE_PTYPE_L4_NONFRAG,
519                 RTE_PTYPE_L4_FRAG,
520                 RTE_PTYPE_L4_TCP,
521                 RTE_PTYPE_L4_UDP,
522                 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
523                 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
524                 RTE_PTYPE_INNER_L4_NONFRAG,
525                 RTE_PTYPE_INNER_L4_FRAG,
526                 RTE_PTYPE_INNER_L4_TCP,
527                 RTE_PTYPE_INNER_L4_UDP,
528                 RTE_PTYPE_UNKNOWN
529         };
530
531         if (dev->rx_pkt_burst == mlx5_rx_burst ||
532             dev->rx_pkt_burst == mlx5_rx_burst_mprq ||
533             dev->rx_pkt_burst == mlx5_rx_burst_vec ||
534             dev->rx_pkt_burst == mlx5_rx_burst_mprq_vec)
535                 return ptypes;
536         return NULL;
537 }
538
539 /**
540  * DPDK callback to change the MTU.
541  *
542  * @param dev
543  *   Pointer to Ethernet device structure.
544  * @param in_mtu
545  *   New MTU.
546  *
547  * @return
548  *   0 on success, a negative errno value otherwise and rte_errno is set.
549  */
550 int
551 mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
552 {
553         struct mlx5_priv *priv = dev->data->dev_private;
554         uint16_t kern_mtu = 0;
555         int ret;
556
557         ret = mlx5_get_mtu(dev, &kern_mtu);
558         if (ret)
559                 return ret;
560         /* Set kernel interface MTU first. */
561         ret = mlx5_set_mtu(dev, mtu);
562         if (ret)
563                 return ret;
564         ret = mlx5_get_mtu(dev, &kern_mtu);
565         if (ret)
566                 return ret;
567         if (kern_mtu == mtu) {
568                 priv->mtu = mtu;
569                 DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
570                         dev->data->port_id, mtu);
571                 return 0;
572         }
573         rte_errno = EAGAIN;
574         return -rte_errno;
575 }
576
577 /**
578  * Configure the RX function to use.
579  *
580  * @param dev
581  *   Pointer to private data structure.
582  *
583  * @return
584  *   Pointer to selected Rx burst function.
585  */
586 eth_rx_burst_t
587 mlx5_select_rx_function(struct rte_eth_dev *dev)
588 {
589         eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
590
591         MLX5_ASSERT(dev != NULL);
592         if (mlx5_check_vec_rx_support(dev) > 0) {
593                 if (mlx5_mprq_enabled(dev)) {
594                         rx_pkt_burst = mlx5_rx_burst_mprq_vec;
595                         DRV_LOG(DEBUG, "port %u selected vectorized"
596                                 " MPRQ Rx function", dev->data->port_id);
597                 } else {
598                         rx_pkt_burst = mlx5_rx_burst_vec;
599                         DRV_LOG(DEBUG, "port %u selected vectorized"
600                                 " SPRQ Rx function", dev->data->port_id);
601                 }
602         } else if (mlx5_mprq_enabled(dev)) {
603                 rx_pkt_burst = mlx5_rx_burst_mprq;
604                 DRV_LOG(DEBUG, "port %u selected MPRQ Rx function",
605                         dev->data->port_id);
606         } else {
607                 DRV_LOG(DEBUG, "port %u selected SPRQ Rx function",
608                         dev->data->port_id);
609         }
610         return rx_pkt_burst;
611 }
612
613 /**
614  * Get the E-Switch parameters by port id.
615  *
616  * @param[in] port
617  *   Device port id.
618  * @param[in] valid
619  *   Device port id is valid, skip check. This flag is useful
620  *   when trials are performed from probing and device is not
621  *   flagged as valid yet (in attaching process).
622  * @param[out] es_domain_id
623  *   E-Switch domain id.
624  * @param[out] es_port_id
625  *   The port id of the port in the E-Switch.
626  *
627  * @return
628  *   pointer to device private data structure containing data needed
629  *   on success, NULL otherwise and rte_errno is set.
630  */
631 struct mlx5_priv *
632 mlx5_port_to_eswitch_info(uint16_t port, bool valid)
633 {
634         struct rte_eth_dev *dev;
635         struct mlx5_priv *priv;
636
637         if (port >= RTE_MAX_ETHPORTS) {
638                 rte_errno = EINVAL;
639                 return NULL;
640         }
641         if (!valid && !rte_eth_dev_is_valid_port(port)) {
642                 rte_errno = ENODEV;
643                 return NULL;
644         }
645         dev = &rte_eth_devices[port];
646         priv = dev->data->dev_private;
647         if (!(priv->representor || priv->master)) {
648                 rte_errno = EINVAL;
649                 return NULL;
650         }
651         return priv;
652 }
653
654 /**
655  * Get the E-Switch parameters by device instance.
656  *
657  * @param[in] port
658  *   Device port id.
659  * @param[out] es_domain_id
660  *   E-Switch domain id.
661  * @param[out] es_port_id
662  *   The port id of the port in the E-Switch.
663  *
664  * @return
665  *   pointer to device private data structure containing data needed
666  *   on success, NULL otherwise and rte_errno is set.
667  */
668 struct mlx5_priv *
669 mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev)
670 {
671         struct mlx5_priv *priv;
672
673         priv = dev->data->dev_private;
674         if (!(priv->representor || priv->master)) {
675                 rte_errno = EINVAL;
676                 return NULL;
677         }
678         return priv;
679 }
680
681 /**
682  * DPDK callback to retrieve hairpin capabilities.
683  *
684  * @param dev
685  *   Pointer to Ethernet device structure.
686  * @param[out] cap
687  *   Storage for hairpin capability data.
688  *
689  * @return
690  *   0 on success, a negative errno value otherwise and rte_errno is set.
691  */
692 int
693 mlx5_hairpin_cap_get(struct rte_eth_dev *dev, struct rte_eth_hairpin_cap *cap)
694 {
695         struct mlx5_priv *priv = dev->data->dev_private;
696         struct mlx5_dev_config *config = &priv->config;
697
698         if (!priv->sh->devx || !config->dest_tir || !config->dv_flow_en) {
699                 rte_errno = ENOTSUP;
700                 return -rte_errno;
701         }
702         cap->max_nb_queues = UINT16_MAX;
703         cap->max_rx_2_tx = 1;
704         cap->max_tx_2_rx = 1;
705         cap->max_nb_desc = 8192;
706         return 0;
707 }