net/mlx5: fix statistics read on Linux
[dpdk.git] / drivers / net / mlx5 / linux / mlx5_ethdev_os.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 <inttypes.h>
8 #include <unistd.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <errno.h>
15 #include <dirent.h>
16 #include <net/if.h>
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <linux/ethtool.h>
21 #include <linux/sockios.h>
22 #include <fcntl.h>
23 #include <stdalign.h>
24 #include <sys/un.h>
25 #include <time.h>
26
27 #include <ethdev_driver.h>
28 #include <rte_bus_pci.h>
29 #include <rte_mbuf.h>
30 #include <rte_common.h>
31 #include <rte_interrupts.h>
32 #include <rte_malloc.h>
33 #include <rte_string_fns.h>
34 #include <rte_rwlock.h>
35 #include <rte_cycles.h>
36
37 #include <mlx5_glue.h>
38 #include <mlx5_devx_cmds.h>
39 #include <mlx5_common.h>
40 #include <mlx5_malloc.h>
41 #include <mlx5_nl.h>
42
43 #include "mlx5.h"
44 #include "mlx5_rxtx.h"
45 #include "mlx5_utils.h"
46
47 /* Supported speed values found in /usr/include/linux/ethtool.h */
48 #ifndef HAVE_SUPPORTED_40000baseKR4_Full
49 #define SUPPORTED_40000baseKR4_Full (1 << 23)
50 #endif
51 #ifndef HAVE_SUPPORTED_40000baseCR4_Full
52 #define SUPPORTED_40000baseCR4_Full (1 << 24)
53 #endif
54 #ifndef HAVE_SUPPORTED_40000baseSR4_Full
55 #define SUPPORTED_40000baseSR4_Full (1 << 25)
56 #endif
57 #ifndef HAVE_SUPPORTED_40000baseLR4_Full
58 #define SUPPORTED_40000baseLR4_Full (1 << 26)
59 #endif
60 #ifndef HAVE_SUPPORTED_56000baseKR4_Full
61 #define SUPPORTED_56000baseKR4_Full (1 << 27)
62 #endif
63 #ifndef HAVE_SUPPORTED_56000baseCR4_Full
64 #define SUPPORTED_56000baseCR4_Full (1 << 28)
65 #endif
66 #ifndef HAVE_SUPPORTED_56000baseSR4_Full
67 #define SUPPORTED_56000baseSR4_Full (1 << 29)
68 #endif
69 #ifndef HAVE_SUPPORTED_56000baseLR4_Full
70 #define SUPPORTED_56000baseLR4_Full (1 << 30)
71 #endif
72
73 /* Add defines in case the running kernel is not the same as user headers. */
74 #ifndef ETHTOOL_GLINKSETTINGS
75 struct ethtool_link_settings {
76         uint32_t cmd;
77         uint32_t speed;
78         uint8_t duplex;
79         uint8_t port;
80         uint8_t phy_address;
81         uint8_t autoneg;
82         uint8_t mdio_support;
83         uint8_t eth_to_mdix;
84         uint8_t eth_tp_mdix_ctrl;
85         int8_t link_mode_masks_nwords;
86         uint32_t reserved[8];
87         uint32_t link_mode_masks[];
88 };
89
90 /* The kernel values can be found in /include/uapi/linux/ethtool.h */
91 #define ETHTOOL_GLINKSETTINGS 0x0000004c
92 #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5
93 #define ETHTOOL_LINK_MODE_Autoneg_BIT 6
94 #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17
95 #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18
96 #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19
97 #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20
98 #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21
99 #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22
100 #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23
101 #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24
102 #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25
103 #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26
104 #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27
105 #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28
106 #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29
107 #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30
108 #endif
109 #ifndef HAVE_ETHTOOL_LINK_MODE_25G
110 #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31
111 #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32
112 #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33
113 #endif
114 #ifndef HAVE_ETHTOOL_LINK_MODE_50G
115 #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34
116 #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35
117 #endif
118 #ifndef HAVE_ETHTOOL_LINK_MODE_100G
119 #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36
120 #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37
121 #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38
122 #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39
123 #endif
124 #ifndef HAVE_ETHTOOL_LINK_MODE_200G
125 #define ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT 62
126 #define ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT 63
127 #define ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT 0 /* 64 - 64 */
128 #define ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT 1 /* 65 - 64 */
129 #define ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT 2 /* 66 - 64 */
130 #endif
131
132 /* Get interface index from SubFunction device name. */
133 int
134 mlx5_auxiliary_get_ifindex(const char *sf_name)
135 {
136         char if_name[IF_NAMESIZE] = { 0 };
137
138         if (mlx5_auxiliary_get_child_name(sf_name, "/net",
139                                           if_name, sizeof(if_name)) != 0)
140                 return -rte_errno;
141         return if_nametoindex(if_name);
142 }
143
144 /**
145  * Get interface name from private structure.
146  *
147  * This is a port representor-aware version of mlx5_get_ifname_sysfs().
148  *
149  * @param[in] dev
150  *   Pointer to Ethernet device.
151  * @param[out] ifname
152  *   Interface name output buffer.
153  *
154  * @return
155  *   0 on success, a negative errno value otherwise and rte_errno is set.
156  */
157 int
158 mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[MLX5_NAMESIZE])
159 {
160         struct mlx5_priv *priv = dev->data->dev_private;
161         unsigned int ifindex;
162
163         MLX5_ASSERT(priv);
164         MLX5_ASSERT(priv->sh);
165         if (priv->master && priv->sh->bond.ifindex > 0) {
166                 memcpy(ifname, priv->sh->bond.ifname, MLX5_NAMESIZE);
167                 return 0;
168         }
169         ifindex = mlx5_ifindex(dev);
170         if (!ifindex) {
171                 if (!priv->representor)
172                         return mlx5_get_ifname_sysfs(priv->sh->ibdev_path,
173                                                      *ifname);
174                 rte_errno = ENXIO;
175                 return -rte_errno;
176         }
177         if (if_indextoname(ifindex, &(*ifname)[0]))
178                 return 0;
179         rte_errno = errno;
180         return -rte_errno;
181 }
182
183 /**
184  * Perform ifreq ioctl() on associated netdev ifname.
185  *
186  * @param[in] ifname
187  *   Pointer to netdev name.
188  * @param req
189  *   Request number to pass to ioctl().
190  * @param[out] ifr
191  *   Interface request structure output buffer.
192  *
193  * @return
194  *   0 on success, a negative errno value otherwise and rte_errno is set.
195  */
196 static int
197 mlx5_ifreq_by_ifname(const char *ifname, int req, struct ifreq *ifr)
198 {
199         int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
200         int ret = 0;
201
202         if (sock == -1) {
203                 rte_errno = errno;
204                 return -rte_errno;
205         }
206         rte_strscpy(ifr->ifr_name, ifname, sizeof(ifr->ifr_name));
207         ret = ioctl(sock, req, ifr);
208         if (ret == -1) {
209                 rte_errno = errno;
210                 goto error;
211         }
212         close(sock);
213         return 0;
214 error:
215         close(sock);
216         return -rte_errno;
217 }
218
219 /**
220  * Perform ifreq ioctl() on associated Ethernet device.
221  *
222  * @param[in] dev
223  *   Pointer to Ethernet device.
224  * @param req
225  *   Request number to pass to ioctl().
226  * @param[out] ifr
227  *   Interface request structure output buffer.
228  *
229  * @return
230  *   0 on success, a negative errno value otherwise and rte_errno is set.
231  */
232 static int
233 mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
234 {
235         char ifname[sizeof(ifr->ifr_name)];
236         int ret;
237
238         ret = mlx5_get_ifname(dev, &ifname);
239         if (ret)
240                 return -rte_errno;
241         return mlx5_ifreq_by_ifname(ifname, req, ifr);
242 }
243
244 /**
245  * Get device MTU.
246  *
247  * @param dev
248  *   Pointer to Ethernet device.
249  * @param[out] mtu
250  *   MTU value output buffer.
251  *
252  * @return
253  *   0 on success, a negative errno value otherwise and rte_errno is set.
254  */
255 int
256 mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
257 {
258         struct ifreq request;
259         int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
260
261         if (ret)
262                 return ret;
263         *mtu = request.ifr_mtu;
264         return 0;
265 }
266
267 /**
268  * Set device MTU.
269  *
270  * @param dev
271  *   Pointer to Ethernet device.
272  * @param mtu
273  *   MTU value to set.
274  *
275  * @return
276  *   0 on success, a negative errno value otherwise and rte_errno is set.
277  */
278 int
279 mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
280 {
281         struct ifreq request = { .ifr_mtu = mtu, };
282
283         return mlx5_ifreq(dev, SIOCSIFMTU, &request);
284 }
285
286 /**
287  * Set device flags.
288  *
289  * @param dev
290  *   Pointer to Ethernet device.
291  * @param keep
292  *   Bitmask for flags that must remain untouched.
293  * @param flags
294  *   Bitmask for flags to modify.
295  *
296  * @return
297  *   0 on success, a negative errno value otherwise and rte_errno is set.
298  */
299 static int
300 mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
301 {
302         struct ifreq request;
303         int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
304
305         if (ret)
306                 return ret;
307         request.ifr_flags &= keep;
308         request.ifr_flags |= flags & ~keep;
309         return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
310 }
311
312 /**
313  * Get device current raw clock counter
314  *
315  * @param dev
316  *   Pointer to Ethernet device structure.
317  * @param[out] time
318  *   Current raw clock counter of the device.
319  *
320  * @return
321  *   0 if the clock has correctly been read
322  *   The value of errno in case of error
323  */
324 int
325 mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
326 {
327         struct mlx5_priv *priv = dev->data->dev_private;
328         struct ibv_context *ctx = priv->sh->cdev->ctx;
329         struct ibv_values_ex values;
330         int err = 0;
331
332         values.comp_mask = IBV_VALUES_MASK_RAW_CLOCK;
333         err = mlx5_glue->query_rt_values_ex(ctx, &values);
334         if (err != 0) {
335                 DRV_LOG(WARNING, "Could not query the clock !");
336                 return err;
337         }
338         *clock = values.raw_clock.tv_nsec;
339         return 0;
340 }
341
342 /**
343  * Retrieve the master device for representor in the same switch domain.
344  *
345  * @param dev
346  *   Pointer to representor Ethernet device structure.
347  *
348  * @return
349  *   Master device structure  on success, NULL otherwise.
350  */
351 static struct rte_eth_dev *
352 mlx5_find_master_dev(struct rte_eth_dev *dev)
353 {
354         struct mlx5_priv *priv;
355         uint16_t port_id;
356         uint16_t domain_id;
357
358         priv = dev->data->dev_private;
359         domain_id = priv->domain_id;
360         MLX5_ASSERT(priv->representor);
361         MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
362                 struct mlx5_priv *opriv =
363                         rte_eth_devices[port_id].data->dev_private;
364                 if (opriv &&
365                     opriv->master &&
366                     opriv->domain_id == domain_id &&
367                     opriv->sh == priv->sh)
368                         return &rte_eth_devices[port_id];
369         }
370         return NULL;
371 }
372
373 /**
374  * DPDK callback to retrieve physical link information.
375  *
376  * @param dev
377  *   Pointer to Ethernet device structure.
378  * @param[out] link
379  *   Storage for current link status.
380  *
381  * @return
382  *   0 on success, a negative errno value otherwise and rte_errno is set.
383  */
384 static int
385 mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
386                                struct rte_eth_link *link)
387 {
388         struct mlx5_priv *priv = dev->data->dev_private;
389         struct ethtool_cmd edata = {
390                 .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
391         };
392         struct ifreq ifr;
393         struct rte_eth_link dev_link;
394         int link_speed = 0;
395         int ret;
396
397         ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
398         if (ret) {
399                 DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
400                         dev->data->port_id, strerror(rte_errno));
401                 return ret;
402         }
403         dev_link = (struct rte_eth_link) {
404                 .link_status = ((ifr.ifr_flags & IFF_UP) &&
405                                 (ifr.ifr_flags & IFF_RUNNING)),
406         };
407         ifr = (struct ifreq) {
408                 .ifr_data = (void *)&edata,
409         };
410         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
411         if (ret) {
412                 if (ret == -ENOTSUP && priv->representor) {
413                         struct rte_eth_dev *master;
414
415                         /*
416                          * For representors we can try to inherit link
417                          * settings from the master device. Actually
418                          * link settings do not make a lot of sense
419                          * for representors due to missing physical
420                          * link. The old kernel drivers supported
421                          * emulated settings query for representors,
422                          * the new ones do not, so we have to add
423                          * this code for compatibility issues.
424                          */
425                         master = mlx5_find_master_dev(dev);
426                         if (master) {
427                                 ifr = (struct ifreq) {
428                                         .ifr_data = (void *)&edata,
429                                 };
430                                 ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr);
431                         }
432                 }
433                 if (ret) {
434                         DRV_LOG(WARNING,
435                                 "port %u ioctl(SIOCETHTOOL,"
436                                 " ETHTOOL_GSET) failed: %s",
437                                 dev->data->port_id, strerror(rte_errno));
438                         return ret;
439                 }
440         }
441         link_speed = ethtool_cmd_speed(&edata);
442         if (link_speed == -1)
443                 dev_link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
444         else
445                 dev_link.link_speed = link_speed;
446         priv->link_speed_capa = 0;
447         if (edata.supported & (SUPPORTED_1000baseT_Full |
448                                SUPPORTED_1000baseKX_Full))
449                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_1G;
450         if (edata.supported & SUPPORTED_10000baseKR_Full)
451                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_10G;
452         if (edata.supported & (SUPPORTED_40000baseKR4_Full |
453                                SUPPORTED_40000baseCR4_Full |
454                                SUPPORTED_40000baseSR4_Full |
455                                SUPPORTED_40000baseLR4_Full))
456                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_40G;
457         dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
458                                 RTE_ETH_LINK_HALF_DUPLEX : RTE_ETH_LINK_FULL_DUPLEX);
459         dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
460                         RTE_ETH_LINK_SPEED_FIXED);
461         *link = dev_link;
462         return 0;
463 }
464
465 /**
466  * Retrieve physical link information (unlocked version using new ioctl).
467  *
468  * @param dev
469  *   Pointer to Ethernet device structure.
470  * @param[out] link
471  *   Storage for current link status.
472  *
473  * @return
474  *   0 on success, a negative errno value otherwise and rte_errno is set.
475  */
476 static int
477 mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
478                              struct rte_eth_link *link)
479
480 {
481         struct mlx5_priv *priv = dev->data->dev_private;
482         struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
483         struct ifreq ifr;
484         struct rte_eth_link dev_link;
485         struct rte_eth_dev *master = NULL;
486         uint64_t sc;
487         int ret;
488
489         ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
490         if (ret) {
491                 DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
492                         dev->data->port_id, strerror(rte_errno));
493                 return ret;
494         }
495         dev_link = (struct rte_eth_link) {
496                 .link_status = ((ifr.ifr_flags & IFF_UP) &&
497                                 (ifr.ifr_flags & IFF_RUNNING)),
498         };
499         ifr = (struct ifreq) {
500                 .ifr_data = (void *)&gcmd,
501         };
502         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
503         if (ret) {
504                 if (ret == -ENOTSUP && priv->representor) {
505                         /*
506                          * For representors we can try to inherit link
507                          * settings from the master device. Actually
508                          * link settings do not make a lot of sense
509                          * for representors due to missing physical
510                          * link. The old kernel drivers supported
511                          * emulated settings query for representors,
512                          * the new ones do not, so we have to add
513                          * this code for compatibility issues.
514                          */
515                         master = mlx5_find_master_dev(dev);
516                         if (master) {
517                                 ifr = (struct ifreq) {
518                                         .ifr_data = (void *)&gcmd,
519                                 };
520                                 ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr);
521                         }
522                 }
523                 if (ret) {
524                         DRV_LOG(DEBUG,
525                                 "port %u ioctl(SIOCETHTOOL,"
526                                 " ETHTOOL_GLINKSETTINGS) failed: %s",
527                                 dev->data->port_id, strerror(rte_errno));
528                         return ret;
529                 }
530         }
531         gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
532
533         alignas(struct ethtool_link_settings)
534         uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
535                      sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
536         struct ethtool_link_settings *ecmd = (void *)data;
537
538         *ecmd = gcmd;
539         ifr.ifr_data = (void *)ecmd;
540         ret = mlx5_ifreq(master ? master : dev, SIOCETHTOOL, &ifr);
541         if (ret) {
542                 DRV_LOG(DEBUG,
543                         "port %u ioctl(SIOCETHTOOL,"
544                         "ETHTOOL_GLINKSETTINGS) failed: %s",
545                         dev->data->port_id, strerror(rte_errno));
546                 return ret;
547         }
548         dev_link.link_speed = (ecmd->speed == UINT32_MAX) ?
549                                 RTE_ETH_SPEED_NUM_UNKNOWN : ecmd->speed;
550         sc = ecmd->link_mode_masks[0] |
551                 ((uint64_t)ecmd->link_mode_masks[1] << 32);
552         priv->link_speed_capa = 0;
553         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
554                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
555                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_1G;
556         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
557                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
558                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
559                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_10G;
560         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
561                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
562                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_20G;
563         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
564                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
565                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
566                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
567                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_40G;
568         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
569                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
570                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
571                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
572                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_56G;
573         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
574                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
575                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
576                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_25G;
577         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
578                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
579                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_50G;
580         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
581                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
582                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
583                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
584                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_100G;
585         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT) |
586                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT)))
587                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_200G;
588
589         sc = ecmd->link_mode_masks[2] |
590                 ((uint64_t)ecmd->link_mode_masks[3] << 32);
591         if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT) |
592                   MLX5_BITSHIFT
593                        (ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT) |
594                   MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT)))
595                 priv->link_speed_capa |= RTE_ETH_LINK_SPEED_200G;
596         dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
597                                 RTE_ETH_LINK_HALF_DUPLEX : RTE_ETH_LINK_FULL_DUPLEX);
598         dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
599                                   RTE_ETH_LINK_SPEED_FIXED);
600         *link = dev_link;
601         return 0;
602 }
603
604 /**
605  * DPDK callback to retrieve physical link information.
606  *
607  * @param dev
608  *   Pointer to Ethernet device structure.
609  * @param wait_to_complete
610  *   Wait for request completion.
611  *
612  * @return
613  *   0 if link status was not updated, positive if it was, a negative errno
614  *   value otherwise and rte_errno is set.
615  */
616 int
617 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
618 {
619         int ret;
620         struct rte_eth_link dev_link;
621         time_t start_time = time(NULL);
622         int retry = MLX5_GET_LINK_STATUS_RETRY_COUNT;
623
624         do {
625                 ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
626                 if (ret == -ENOTSUP)
627                         ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
628                 if (ret == 0)
629                         break;
630                 /* Handle wait to complete situation. */
631                 if ((wait_to_complete || retry) && ret == -EAGAIN) {
632                         if (abs((int)difftime(time(NULL), start_time)) <
633                             MLX5_LINK_STATUS_TIMEOUT) {
634                                 usleep(0);
635                                 continue;
636                         } else {
637                                 rte_errno = EBUSY;
638                                 return -rte_errno;
639                         }
640                 } else if (ret < 0) {
641                         return ret;
642                 }
643         } while (wait_to_complete || retry-- > 0);
644         ret = !!memcmp(&dev->data->dev_link, &dev_link,
645                        sizeof(struct rte_eth_link));
646         dev->data->dev_link = dev_link;
647         return ret;
648 }
649
650 /**
651  * DPDK callback to get flow control status.
652  *
653  * @param dev
654  *   Pointer to Ethernet device structure.
655  * @param[out] fc_conf
656  *   Flow control output buffer.
657  *
658  * @return
659  *   0 on success, a negative errno value otherwise and rte_errno is set.
660  */
661 int
662 mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
663 {
664         struct ifreq ifr;
665         struct ethtool_pauseparam ethpause = {
666                 .cmd = ETHTOOL_GPAUSEPARAM
667         };
668         int ret;
669
670         ifr.ifr_data = (void *)&ethpause;
671         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
672         if (ret) {
673                 DRV_LOG(WARNING,
674                         "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
675                         " %s",
676                         dev->data->port_id, strerror(rte_errno));
677                 return ret;
678         }
679         fc_conf->autoneg = ethpause.autoneg;
680         if (ethpause.rx_pause && ethpause.tx_pause)
681                 fc_conf->mode = RTE_ETH_FC_FULL;
682         else if (ethpause.rx_pause)
683                 fc_conf->mode = RTE_ETH_FC_RX_PAUSE;
684         else if (ethpause.tx_pause)
685                 fc_conf->mode = RTE_ETH_FC_TX_PAUSE;
686         else
687                 fc_conf->mode = RTE_ETH_FC_NONE;
688         return 0;
689 }
690
691 /**
692  * DPDK callback to modify flow control parameters.
693  *
694  * @param dev
695  *   Pointer to Ethernet device structure.
696  * @param[in] fc_conf
697  *   Flow control parameters.
698  *
699  * @return
700  *   0 on success, a negative errno value otherwise and rte_errno is set.
701  */
702 int
703 mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
704 {
705         struct ifreq ifr;
706         struct ethtool_pauseparam ethpause = {
707                 .cmd = ETHTOOL_SPAUSEPARAM
708         };
709         int ret;
710
711         ifr.ifr_data = (void *)&ethpause;
712         ethpause.autoneg = fc_conf->autoneg;
713         if (((fc_conf->mode & RTE_ETH_FC_FULL) == RTE_ETH_FC_FULL) ||
714             (fc_conf->mode & RTE_ETH_FC_RX_PAUSE))
715                 ethpause.rx_pause = 1;
716         else
717                 ethpause.rx_pause = 0;
718
719         if (((fc_conf->mode & RTE_ETH_FC_FULL) == RTE_ETH_FC_FULL) ||
720             (fc_conf->mode & RTE_ETH_FC_TX_PAUSE))
721                 ethpause.tx_pause = 1;
722         else
723                 ethpause.tx_pause = 0;
724         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
725         if (ret) {
726                 DRV_LOG(WARNING,
727                         "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
728                         " failed: %s",
729                         dev->data->port_id, strerror(rte_errno));
730                 return ret;
731         }
732         return 0;
733 }
734
735 /**
736  * Handle asynchronous removal event for entire multiport device.
737  *
738  * @param sh
739  *   Infiniband device shared context.
740  */
741 static void
742 mlx5_dev_interrupt_device_fatal(struct mlx5_dev_ctx_shared *sh)
743 {
744         uint32_t i;
745
746         for (i = 0; i < sh->max_port; ++i) {
747                 struct rte_eth_dev *dev;
748
749                 if (sh->port[i].ih_port_id >= RTE_MAX_ETHPORTS) {
750                         /*
751                          * Or not existing port either no
752                          * handler installed for this port.
753                          */
754                         continue;
755                 }
756                 dev = &rte_eth_devices[sh->port[i].ih_port_id];
757                 MLX5_ASSERT(dev);
758                 if (dev->data->dev_conf.intr_conf.rmv)
759                         rte_eth_dev_callback_process
760                                 (dev, RTE_ETH_EVENT_INTR_RMV, NULL);
761         }
762 }
763
764 static void
765 mlx5_dev_interrupt_nl_cb(struct nlmsghdr *hdr, void *cb_arg)
766 {
767         struct mlx5_dev_ctx_shared *sh = cb_arg;
768         uint32_t i;
769         uint32_t if_index;
770
771         if (mlx5_nl_parse_link_status_update(hdr, &if_index) < 0)
772                 return;
773         for (i = 0; i < sh->max_port; i++) {
774                 struct mlx5_dev_shared_port *port = &sh->port[i];
775                 struct rte_eth_dev *dev;
776                 struct mlx5_priv *priv;
777
778                 if (port->nl_ih_port_id >= RTE_MAX_ETHPORTS)
779                         continue;
780                 dev = &rte_eth_devices[port->nl_ih_port_id];
781                 /* Probing may initiate an LSC before configuration is done. */
782                 if (dev->data->dev_configured &&
783                     !dev->data->dev_conf.intr_conf.lsc)
784                         break;
785                 priv = dev->data->dev_private;
786                 if (priv->if_index == if_index) {
787                         /* Block logical LSC events. */
788                         uint16_t prev_status = dev->data->dev_link.link_status;
789
790                         if (mlx5_link_update(dev, 0) < 0)
791                                 DRV_LOG(ERR, "Failed to update link status: %s",
792                                         rte_strerror(rte_errno));
793                         else if (prev_status != dev->data->dev_link.link_status)
794                                 rte_eth_dev_callback_process
795                                         (dev, RTE_ETH_EVENT_INTR_LSC, NULL);
796                         break;
797                 }
798         }
799 }
800
801 void
802 mlx5_dev_interrupt_handler_nl(void *arg)
803 {
804         struct mlx5_dev_ctx_shared *sh = arg;
805         int nlsk_fd = rte_intr_fd_get(sh->intr_handle_nl);
806
807         if (nlsk_fd < 0)
808                 return;
809         if (mlx5_nl_read_events(nlsk_fd, mlx5_dev_interrupt_nl_cb, sh) < 0)
810                 DRV_LOG(ERR, "Failed to process Netlink events: %s",
811                         rte_strerror(rte_errno));
812 }
813
814 /**
815  * Handle shared asynchronous events the NIC (removal event
816  * and link status change). Supports multiport IB device.
817  *
818  * @param cb_arg
819  *   Callback argument.
820  */
821 void
822 mlx5_dev_interrupt_handler(void *cb_arg)
823 {
824         struct mlx5_dev_ctx_shared *sh = cb_arg;
825         struct ibv_async_event event;
826
827         /* Read all message from the IB device and acknowledge them. */
828         for (;;) {
829                 struct rte_eth_dev *dev;
830                 uint32_t tmp;
831
832                 if (mlx5_glue->get_async_event(sh->cdev->ctx, &event))
833                         break;
834                 /* Retrieve and check IB port index. */
835                 tmp = (uint32_t)event.element.port_num;
836                 if (!tmp && event.event_type == IBV_EVENT_DEVICE_FATAL) {
837                         /*
838                          * The DEVICE_FATAL event is called once for
839                          * entire device without port specifying.
840                          * We should notify all existing ports.
841                          */
842                         mlx5_glue->ack_async_event(&event);
843                         mlx5_dev_interrupt_device_fatal(sh);
844                         continue;
845                 }
846                 MLX5_ASSERT(tmp && (tmp <= sh->max_port));
847                 if (!tmp) {
848                         /* Unsupported device level event. */
849                         mlx5_glue->ack_async_event(&event);
850                         DRV_LOG(DEBUG,
851                                 "unsupported common event (type %d)",
852                                 event.event_type);
853                         continue;
854                 }
855                 if (tmp > sh->max_port) {
856                         /* Invalid IB port index. */
857                         mlx5_glue->ack_async_event(&event);
858                         DRV_LOG(DEBUG,
859                                 "cannot handle an event (type %d)"
860                                 "due to invalid IB port index (%u)",
861                                 event.event_type, tmp);
862                         continue;
863                 }
864                 if (sh->port[tmp - 1].ih_port_id >= RTE_MAX_ETHPORTS) {
865                         /* No handler installed. */
866                         mlx5_glue->ack_async_event(&event);
867                         DRV_LOG(DEBUG,
868                                 "cannot handle an event (type %d)"
869                                 "due to no handler installed for port %u",
870                                 event.event_type, tmp);
871                         continue;
872                 }
873                 /* Retrieve ethernet device descriptor. */
874                 tmp = sh->port[tmp - 1].ih_port_id;
875                 dev = &rte_eth_devices[tmp];
876                 MLX5_ASSERT(dev);
877                 DRV_LOG(DEBUG,
878                         "port %u cannot handle an unknown event (type %d)",
879                         dev->data->port_id, event.event_type);
880                 mlx5_glue->ack_async_event(&event);
881         }
882 }
883
884 /*
885  * Unregister callback handler safely. The handler may be active
886  * while we are trying to unregister it, in this case code -EAGAIN
887  * is returned by rte_intr_callback_unregister(). This routine checks
888  * the return code and tries to unregister handler again.
889  *
890  * @param handle
891  *   interrupt handle
892  * @param cb_fn
893  *   pointer to callback routine
894  * @cb_arg
895  *   opaque callback parameter
896  */
897 void
898 mlx5_intr_callback_unregister(const struct rte_intr_handle *handle,
899                               rte_intr_callback_fn cb_fn, void *cb_arg)
900 {
901         /*
902          * Try to reduce timeout management overhead by not calling
903          * the timer related routines on the first iteration. If the
904          * unregistering succeeds on first call there will be no
905          * timer calls at all.
906          */
907         uint64_t twait = 0;
908         uint64_t start = 0;
909
910         do {
911                 int ret;
912
913                 ret = rte_intr_callback_unregister(handle, cb_fn, cb_arg);
914                 if (ret >= 0)
915                         return;
916                 if (ret != -EAGAIN) {
917                         DRV_LOG(INFO, "failed to unregister interrupt"
918                                       " handler (error: %d)", ret);
919                         MLX5_ASSERT(false);
920                         return;
921                 }
922                 if (twait) {
923                         struct timespec onems;
924
925                         /* Wait one millisecond and try again. */
926                         onems.tv_sec = 0;
927                         onems.tv_nsec = NS_PER_S / MS_PER_S;
928                         nanosleep(&onems, 0);
929                         /* Check whether one second elapsed. */
930                         if ((rte_get_timer_cycles() - start) <= twait)
931                                 continue;
932                 } else {
933                         /*
934                          * We get the amount of timer ticks for one second.
935                          * If this amount elapsed it means we spent one
936                          * second in waiting. This branch is executed once
937                          * on first iteration.
938                          */
939                         twait = rte_get_timer_hz();
940                         MLX5_ASSERT(twait);
941                 }
942                 /*
943                  * Timeout elapsed, show message (once a second) and retry.
944                  * We have no other acceptable option here, if we ignore
945                  * the unregistering return code the handler will not
946                  * be unregistered, fd will be closed and we may get the
947                  * crush. Hanging and messaging in the loop seems not to be
948                  * the worst choice.
949                  */
950                 DRV_LOG(INFO, "Retrying to unregister interrupt handler");
951                 start = rte_get_timer_cycles();
952         } while (true);
953 }
954
955 /**
956  * Handle DEVX interrupts from the NIC.
957  * This function is probably called from the DPDK host thread.
958  *
959  * @param cb_arg
960  *   Callback argument.
961  */
962 void
963 mlx5_dev_interrupt_handler_devx(void *cb_arg)
964 {
965 #ifndef HAVE_IBV_DEVX_ASYNC
966         (void)cb_arg;
967         return;
968 #else
969         struct mlx5_dev_ctx_shared *sh = cb_arg;
970         union {
971                 struct mlx5dv_devx_async_cmd_hdr cmd_resp;
972                 uint8_t buf[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
973                             MLX5_ST_SZ_BYTES(traffic_counter) +
974                             sizeof(struct mlx5dv_devx_async_cmd_hdr)];
975         } out;
976         uint8_t *buf = out.buf + sizeof(out.cmd_resp);
977
978         while (!mlx5_glue->devx_get_async_cmd_comp(sh->devx_comp,
979                                                    &out.cmd_resp,
980                                                    sizeof(out.buf)))
981                 mlx5_flow_async_pool_query_handle
982                         (sh, (uint64_t)out.cmd_resp.wr_id,
983                          mlx5_devx_get_out_command_status(buf));
984 #endif /* HAVE_IBV_DEVX_ASYNC */
985 }
986
987 /**
988  * DPDK callback to bring the link DOWN.
989  *
990  * @param dev
991  *   Pointer to Ethernet device structure.
992  *
993  * @return
994  *   0 on success, a negative errno value otherwise and rte_errno is set.
995  */
996 int
997 mlx5_set_link_down(struct rte_eth_dev *dev)
998 {
999         return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP);
1000 }
1001
1002 /**
1003  * DPDK callback to bring the link UP.
1004  *
1005  * @param dev
1006  *   Pointer to Ethernet device structure.
1007  *
1008  * @return
1009  *   0 on success, a negative errno value otherwise and rte_errno is set.
1010  */
1011 int
1012 mlx5_set_link_up(struct rte_eth_dev *dev)
1013 {
1014         return mlx5_set_flags(dev, ~IFF_UP, IFF_UP);
1015 }
1016
1017 /**
1018  * Check if mlx5 device was removed.
1019  *
1020  * @param dev
1021  *   Pointer to Ethernet device structure.
1022  *
1023  * @return
1024  *   1 when device is removed, otherwise 0.
1025  */
1026 int
1027 mlx5_is_removed(struct rte_eth_dev *dev)
1028 {
1029         struct ibv_device_attr device_attr;
1030         struct mlx5_priv *priv = dev->data->dev_private;
1031
1032         if (mlx5_glue->query_device(priv->sh->cdev->ctx, &device_attr) == EIO)
1033                 return 1;
1034         return 0;
1035 }
1036
1037 /**
1038  * Analyze gathered port parameters via sysfs to recognize master
1039  * and representor devices for E-Switch configuration.
1040  *
1041  * @param[in] device_dir
1042  *   flag of presence of "device" directory under port device key.
1043  * @param[inout] switch_info
1044  *   Port information, including port name as a number and port name
1045  *   type if recognized
1046  *
1047  * @return
1048  *   master and representor flags are set in switch_info according to
1049  *   recognized parameters (if any).
1050  */
1051 static void
1052 mlx5_sysfs_check_switch_info(bool device_dir,
1053                              struct mlx5_switch_info *switch_info)
1054 {
1055         switch (switch_info->name_type) {
1056         case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:
1057                 /*
1058                  * Name is not recognized, assume the master,
1059                  * check the device directory presence.
1060                  */
1061                 switch_info->master = device_dir;
1062                 break;
1063         case MLX5_PHYS_PORT_NAME_TYPE_NOTSET:
1064                 /*
1065                  * Name is not set, this assumes the legacy naming
1066                  * schema for master, just check if there is
1067                  * a device directory.
1068                  */
1069                 switch_info->master = device_dir;
1070                 break;
1071         case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
1072                 /* New uplink naming schema recognized. */
1073                 switch_info->master = 1;
1074                 break;
1075         case MLX5_PHYS_PORT_NAME_TYPE_LEGACY:
1076                 /* Legacy representors naming schema. */
1077                 switch_info->representor = !device_dir;
1078                 break;
1079         case MLX5_PHYS_PORT_NAME_TYPE_PFHPF:
1080                 /* Fallthrough */
1081         case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
1082                 /* Fallthrough */
1083         case MLX5_PHYS_PORT_NAME_TYPE_PFSF:
1084                 /* New representors naming schema. */
1085                 switch_info->representor = 1;
1086                 break;
1087         default:
1088                 switch_info->master = device_dir;
1089                 break;
1090         }
1091 }
1092
1093 /**
1094  * Get switch information associated with network interface.
1095  *
1096  * @param ifindex
1097  *   Network interface index.
1098  * @param[out] info
1099  *   Switch information object, populated in case of success.
1100  *
1101  * @return
1102  *   0 on success, a negative errno value otherwise and rte_errno is set.
1103  */
1104 int
1105 mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info)
1106 {
1107         char ifname[IF_NAMESIZE];
1108         char port_name[IF_NAMESIZE];
1109         FILE *file;
1110         struct mlx5_switch_info data = {
1111                 .master = 0,
1112                 .representor = 0,
1113                 .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET,
1114                 .port_name = 0,
1115                 .switch_id = 0,
1116         };
1117         DIR *dir;
1118         bool port_switch_id_set = false;
1119         bool device_dir = false;
1120         char c;
1121         int ret;
1122
1123         if (!if_indextoname(ifindex, ifname)) {
1124                 rte_errno = errno;
1125                 return -rte_errno;
1126         }
1127
1128         MKSTR(phys_port_name, "/sys/class/net/%s/phys_port_name",
1129               ifname);
1130         MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id",
1131               ifname);
1132         MKSTR(pci_device, "/sys/class/net/%s/device",
1133               ifname);
1134
1135         file = fopen(phys_port_name, "rb");
1136         if (file != NULL) {
1137                 ret = fscanf(file, "%" RTE_STR(IF_NAMESIZE) "s", port_name);
1138                 fclose(file);
1139                 if (ret == 1)
1140                         mlx5_translate_port_name(port_name, &data);
1141         }
1142         file = fopen(phys_switch_id, "rb");
1143         if (file == NULL) {
1144                 rte_errno = errno;
1145                 return -rte_errno;
1146         }
1147         port_switch_id_set =
1148                 fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 &&
1149                 c == '\n';
1150         fclose(file);
1151         dir = opendir(pci_device);
1152         if (dir != NULL) {
1153                 closedir(dir);
1154                 device_dir = true;
1155         }
1156         if (port_switch_id_set) {
1157                 /* We have some E-Switch configuration. */
1158                 mlx5_sysfs_check_switch_info(device_dir, &data);
1159         }
1160         *info = data;
1161         MLX5_ASSERT(!(data.master && data.representor));
1162         if (data.master && data.representor) {
1163                 DRV_LOG(ERR, "ifindex %u device is recognized as master"
1164                              " and as representor", ifindex);
1165                 rte_errno = ENODEV;
1166                 return -rte_errno;
1167         }
1168         return 0;
1169 }
1170
1171 /**
1172  * Get bond information associated with network interface.
1173  *
1174  * @param pf_ifindex
1175  *   Network interface index of bond slave interface
1176  * @param[out] ifindex
1177  *   Pointer to bond ifindex.
1178  * @param[out] ifname
1179  *   Pointer to bond ifname.
1180  *
1181  * @return
1182  *   0 on success, a negative errno value otherwise and rte_errno is set.
1183  */
1184 int
1185 mlx5_sysfs_bond_info(unsigned int pf_ifindex, unsigned int *ifindex,
1186                      char *ifname)
1187 {
1188         char name[IF_NAMESIZE];
1189         FILE *file;
1190         unsigned int index;
1191         int ret;
1192
1193         if (!if_indextoname(pf_ifindex, name) || !strlen(name)) {
1194                 rte_errno = errno;
1195                 return -rte_errno;
1196         }
1197         MKSTR(bond_if, "/sys/class/net/%s/master/ifindex", name);
1198         /* read bond ifindex */
1199         file = fopen(bond_if, "rb");
1200         if (file == NULL) {
1201                 rte_errno = errno;
1202                 return -rte_errno;
1203         }
1204         ret = fscanf(file, "%u", &index);
1205         fclose(file);
1206         if (ret <= 0) {
1207                 rte_errno = errno;
1208                 return -rte_errno;
1209         }
1210         if (ifindex)
1211                 *ifindex = index;
1212
1213         /* read bond device name from symbol link */
1214         if (ifname) {
1215                 if (!if_indextoname(index, ifname)) {
1216                         rte_errno = errno;
1217                         return -rte_errno;
1218                 }
1219         }
1220         return 0;
1221 }
1222
1223 /**
1224  * DPDK callback to retrieve plug-in module EEPROM information (type and size).
1225  *
1226  * @param dev
1227  *   Pointer to Ethernet device structure.
1228  * @param[out] modinfo
1229  *   Storage for plug-in module EEPROM information.
1230  *
1231  * @return
1232  *   0 on success, a negative errno value otherwise and rte_errno is set.
1233  */
1234 int
1235 mlx5_get_module_info(struct rte_eth_dev *dev,
1236                      struct rte_eth_dev_module_info *modinfo)
1237 {
1238         struct ethtool_modinfo info = {
1239                 .cmd = ETHTOOL_GMODULEINFO,
1240         };
1241         struct ifreq ifr = (struct ifreq) {
1242                 .ifr_data = (void *)&info,
1243         };
1244         int ret = 0;
1245
1246         if (!dev) {
1247                 DRV_LOG(WARNING, "missing argument, cannot get module info");
1248                 rte_errno = EINVAL;
1249                 return -rte_errno;
1250         }
1251         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1252         if (ret) {
1253                 DRV_LOG(WARNING, "port %u ioctl(SIOCETHTOOL) failed: %s",
1254                         dev->data->port_id, strerror(rte_errno));
1255                 return ret;
1256         }
1257         modinfo->type = info.type;
1258         modinfo->eeprom_len = info.eeprom_len;
1259         return ret;
1260 }
1261
1262 /**
1263  * DPDK callback to retrieve plug-in module EEPROM data.
1264  *
1265  * @param dev
1266  *   Pointer to Ethernet device structure.
1267  * @param[out] info
1268  *   Storage for plug-in module EEPROM data.
1269  *
1270  * @return
1271  *   0 on success, a negative errno value otherwise and rte_errno is set.
1272  */
1273 int mlx5_get_module_eeprom(struct rte_eth_dev *dev,
1274                            struct rte_dev_eeprom_info *info)
1275 {
1276         struct ethtool_eeprom *eeprom;
1277         struct ifreq ifr;
1278         int ret = 0;
1279
1280         if (!dev) {
1281                 DRV_LOG(WARNING, "missing argument, cannot get module eeprom");
1282                 rte_errno = EINVAL;
1283                 return -rte_errno;
1284         }
1285         eeprom = mlx5_malloc(MLX5_MEM_ZERO,
1286                              (sizeof(struct ethtool_eeprom) + info->length), 0,
1287                              SOCKET_ID_ANY);
1288         if (!eeprom) {
1289                 DRV_LOG(WARNING, "port %u cannot allocate memory for "
1290                         "eeprom data", dev->data->port_id);
1291                 rte_errno = ENOMEM;
1292                 return -rte_errno;
1293         }
1294         eeprom->cmd = ETHTOOL_GMODULEEEPROM;
1295         eeprom->offset = info->offset;
1296         eeprom->len = info->length;
1297         ifr = (struct ifreq) {
1298                 .ifr_data = (void *)eeprom,
1299         };
1300         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1301         if (ret)
1302                 DRV_LOG(WARNING, "port %u ioctl(SIOCETHTOOL) failed: %s",
1303                         dev->data->port_id, strerror(rte_errno));
1304         else
1305                 rte_memcpy(info->data, eeprom->data, info->length);
1306         mlx5_free(eeprom);
1307         return ret;
1308 }
1309
1310 /**
1311  * Read device counters table.
1312  *
1313  * @param dev
1314  *   Pointer to Ethernet device.
1315  * @param[in] pf
1316  *   PF index in case of bonding device, -1 otherwise
1317  * @param[out] stats
1318  *   Counters table output buffer.
1319  *
1320  * @return
1321  *   0 on success and stats is filled, negative errno value otherwise and
1322  *   rte_errno is set.
1323  */
1324 static int
1325 _mlx5_os_read_dev_counters(struct rte_eth_dev *dev, int pf, uint64_t *stats)
1326 {
1327         struct mlx5_priv *priv = dev->data->dev_private;
1328         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
1329         unsigned int i;
1330         struct ifreq ifr;
1331         unsigned int stats_sz = xstats_ctrl->stats_n * sizeof(uint64_t);
1332         unsigned char et_stat_buf[sizeof(struct ethtool_stats) + stats_sz];
1333         struct ethtool_stats *et_stats = (struct ethtool_stats *)et_stat_buf;
1334         int ret;
1335
1336         et_stats->cmd = ETHTOOL_GSTATS;
1337         et_stats->n_stats = xstats_ctrl->stats_n;
1338         ifr.ifr_data = (caddr_t)et_stats;
1339         if (pf >= 0)
1340                 ret = mlx5_ifreq_by_ifname(priv->sh->bond.ports[pf].ifname,
1341                                            SIOCETHTOOL, &ifr);
1342         else
1343                 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1344         if (ret) {
1345                 DRV_LOG(WARNING,
1346                         "port %u unable to read statistic values from device",
1347                         dev->data->port_id);
1348                 return ret;
1349         }
1350         for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
1351                 if (xstats_ctrl->info[i].dev)
1352                         continue;
1353                 stats[i] += (uint64_t)
1354                             et_stats->data[xstats_ctrl->dev_table_idx[i]];
1355         }
1356         return 0;
1357 }
1358
1359 /**
1360  * Read device counters.
1361  *
1362  * @param dev
1363  *   Pointer to Ethernet device.
1364  * @param[out] stats
1365  *   Counters table output buffer.
1366  *
1367  * @return
1368  *   0 on success and stats is filled, negative errno value otherwise and
1369  *   rte_errno is set.
1370  */
1371 int
1372 mlx5_os_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)
1373 {
1374         struct mlx5_priv *priv = dev->data->dev_private;
1375         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
1376         int ret = 0, i;
1377
1378         memset(stats, 0, sizeof(*stats) * xstats_ctrl->mlx5_stats_n);
1379         /* Read ifreq counters. */
1380         if (priv->master && priv->pf_bond >= 0) {
1381                 /* Sum xstats from bonding device member ports. */
1382                 for (i = 0; i < priv->sh->bond.n_port; i++) {
1383                         ret = _mlx5_os_read_dev_counters(dev, i, stats);
1384                         if (ret)
1385                                 return ret;
1386                 }
1387         } else {
1388                 ret = _mlx5_os_read_dev_counters(dev, -1, stats);
1389                 if (ret)
1390                         return ret;
1391         }
1392         /* Read IB counters. */
1393         for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
1394                 if (!xstats_ctrl->info[i].dev)
1395                         continue;
1396                 /* return last xstats counter if fail to read. */
1397                 if (mlx5_os_read_dev_stat(priv, xstats_ctrl->info[i].ctr_name,
1398                             &stats[i]) == 0)
1399                         xstats_ctrl->xstats[i] = stats[i];
1400                 else
1401                         stats[i] = xstats_ctrl->xstats[i];
1402         }
1403         return ret;
1404 }
1405
1406 /**
1407  * Query the number of statistics provided by ETHTOOL.
1408  *
1409  * @param dev
1410  *   Pointer to Ethernet device.
1411  *
1412  * @return
1413  *   Number of statistics on success, negative errno value otherwise and
1414  *   rte_errno is set.
1415  */
1416 int
1417 mlx5_os_get_stats_n(struct rte_eth_dev *dev)
1418 {
1419         struct mlx5_priv *priv = dev->data->dev_private;
1420         struct ethtool_drvinfo drvinfo;
1421         struct ifreq ifr;
1422         int ret;
1423
1424         drvinfo.cmd = ETHTOOL_GDRVINFO;
1425         ifr.ifr_data = (caddr_t)&drvinfo;
1426         if (priv->master && priv->pf_bond >= 0)
1427                 /* Bonding PF. */
1428                 ret = mlx5_ifreq_by_ifname(priv->sh->bond.ports[0].ifname,
1429                                            SIOCETHTOOL, &ifr);
1430         else
1431                 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1432         if (ret) {
1433                 DRV_LOG(WARNING, "port %u unable to query number of statistics",
1434                         dev->data->port_id);
1435                 return ret;
1436         }
1437         return drvinfo.n_stats;
1438 }
1439
1440 static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
1441         {
1442                 .dpdk_name = "rx_unicast_bytes",
1443                 .ctr_name = "rx_vport_unicast_bytes",
1444         },
1445         {
1446                 .dpdk_name = "rx_multicast_bytes",
1447                 .ctr_name = "rx_vport_multicast_bytes",
1448         },
1449         {
1450                 .dpdk_name = "rx_broadcast_bytes",
1451                 .ctr_name = "rx_vport_broadcast_bytes",
1452         },
1453         {
1454                 .dpdk_name = "rx_unicast_packets",
1455                 .ctr_name = "rx_vport_unicast_packets",
1456         },
1457         {
1458                 .dpdk_name = "rx_multicast_packets",
1459                 .ctr_name = "rx_vport_multicast_packets",
1460         },
1461         {
1462                 .dpdk_name = "rx_broadcast_packets",
1463                 .ctr_name = "rx_vport_broadcast_packets",
1464         },
1465         {
1466                 .dpdk_name = "tx_unicast_bytes",
1467                 .ctr_name = "tx_vport_unicast_bytes",
1468         },
1469         {
1470                 .dpdk_name = "tx_multicast_bytes",
1471                 .ctr_name = "tx_vport_multicast_bytes",
1472         },
1473         {
1474                 .dpdk_name = "tx_broadcast_bytes",
1475                 .ctr_name = "tx_vport_broadcast_bytes",
1476         },
1477         {
1478                 .dpdk_name = "tx_unicast_packets",
1479                 .ctr_name = "tx_vport_unicast_packets",
1480         },
1481         {
1482                 .dpdk_name = "tx_multicast_packets",
1483                 .ctr_name = "tx_vport_multicast_packets",
1484         },
1485         {
1486                 .dpdk_name = "tx_broadcast_packets",
1487                 .ctr_name = "tx_vport_broadcast_packets",
1488         },
1489         {
1490                 .dpdk_name = "rx_wqe_errors",
1491                 .ctr_name = "rx_wqe_err",
1492         },
1493         {
1494                 .dpdk_name = "rx_phy_crc_errors",
1495                 .ctr_name = "rx_crc_errors_phy",
1496         },
1497         {
1498                 .dpdk_name = "rx_phy_in_range_len_errors",
1499                 .ctr_name = "rx_in_range_len_errors_phy",
1500         },
1501         {
1502                 .dpdk_name = "rx_phy_symbol_errors",
1503                 .ctr_name = "rx_symbol_err_phy",
1504         },
1505         {
1506                 .dpdk_name = "tx_phy_errors",
1507                 .ctr_name = "tx_errors_phy",
1508         },
1509         {
1510                 .dpdk_name = "rx_out_of_buffer",
1511                 .ctr_name = "out_of_buffer",
1512                 .dev = 1,
1513         },
1514         {
1515                 .dpdk_name = "tx_phy_packets",
1516                 .ctr_name = "tx_packets_phy",
1517         },
1518         {
1519                 .dpdk_name = "rx_phy_packets",
1520                 .ctr_name = "rx_packets_phy",
1521         },
1522         {
1523                 .dpdk_name = "tx_phy_discard_packets",
1524                 .ctr_name = "tx_discards_phy",
1525         },
1526         {
1527                 .dpdk_name = "rx_phy_discard_packets",
1528                 .ctr_name = "rx_discards_phy",
1529         },
1530         {
1531                 .dpdk_name = "rx_prio0_buf_discard_packets",
1532                 .ctr_name = "rx_prio0_buf_discard",
1533         },
1534         {
1535                 .dpdk_name = "rx_prio1_buf_discard_packets",
1536                 .ctr_name = "rx_prio1_buf_discard",
1537         },
1538         {
1539                 .dpdk_name = "rx_prio2_buf_discard_packets",
1540                 .ctr_name = "rx_prio2_buf_discard",
1541         },
1542         {
1543                 .dpdk_name = "rx_prio3_buf_discard_packets",
1544                 .ctr_name = "rx_prio3_buf_discard",
1545         },
1546         {
1547                 .dpdk_name = "rx_prio4_buf_discard_packets",
1548                 .ctr_name = "rx_prio4_buf_discard",
1549         },
1550         {
1551                 .dpdk_name = "rx_prio5_buf_discard_packets",
1552                 .ctr_name = "rx_prio5_buf_discard",
1553         },
1554         {
1555                 .dpdk_name = "rx_prio6_buf_discard_packets",
1556                 .ctr_name = "rx_prio6_buf_discard",
1557         },
1558         {
1559                 .dpdk_name = "rx_prio7_buf_discard_packets",
1560                 .ctr_name = "rx_prio7_buf_discard",
1561         },
1562         {
1563                 .dpdk_name = "rx_prio0_cong_discard_packets",
1564                 .ctr_name = "rx_prio0_cong_discard",
1565         },
1566         {
1567                 .dpdk_name = "rx_prio1_cong_discard_packets",
1568                 .ctr_name = "rx_prio1_cong_discard",
1569         },
1570         {
1571                 .dpdk_name = "rx_prio2_cong_discard_packets",
1572                 .ctr_name = "rx_prio2_cong_discard",
1573         },
1574         {
1575                 .dpdk_name = "rx_prio3_cong_discard_packets",
1576                 .ctr_name = "rx_prio3_cong_discard",
1577         },
1578         {
1579                 .dpdk_name = "rx_prio4_cong_discard_packets",
1580                 .ctr_name = "rx_prio4_cong_discard",
1581         },
1582         {
1583                 .dpdk_name = "rx_prio5_cong_discard_packets",
1584                 .ctr_name = "rx_prio5_cong_discard",
1585         },
1586         {
1587                 .dpdk_name = "rx_prio6_cong_discard_packets",
1588                 .ctr_name = "rx_prio6_cong_discard",
1589         },
1590         {
1591                 .dpdk_name = "rx_prio7_cong_discard_packets",
1592                 .ctr_name = "rx_prio7_cong_discard",
1593         },
1594         {
1595                 .dpdk_name = "tx_phy_bytes",
1596                 .ctr_name = "tx_bytes_phy",
1597         },
1598         {
1599                 .dpdk_name = "rx_phy_bytes",
1600                 .ctr_name = "rx_bytes_phy",
1601         },
1602         /* Representor only */
1603         {
1604                 .dpdk_name = "rx_vport_packets",
1605                 .ctr_name = "vport_rx_packets",
1606         },
1607         {
1608                 .dpdk_name = "rx_vport_bytes",
1609                 .ctr_name = "vport_rx_bytes",
1610         },
1611         {
1612                 .dpdk_name = "tx_vport_packets",
1613                 .ctr_name = "vport_tx_packets",
1614         },
1615         {
1616                 .dpdk_name = "tx_vport_bytes",
1617                 .ctr_name = "vport_tx_bytes",
1618         },
1619 };
1620
1621 static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
1622
1623 /**
1624  * Init the structures to read device counters.
1625  *
1626  * @param dev
1627  *   Pointer to Ethernet device.
1628  */
1629 void
1630 mlx5_os_stats_init(struct rte_eth_dev *dev)
1631 {
1632         struct mlx5_priv *priv = dev->data->dev_private;
1633         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
1634         struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
1635         unsigned int i;
1636         unsigned int j;
1637         struct ifreq ifr;
1638         struct ethtool_gstrings *strings = NULL;
1639         unsigned int dev_stats_n;
1640         unsigned int str_sz;
1641         int ret;
1642
1643         /* So that it won't aggregate for each init. */
1644         xstats_ctrl->mlx5_stats_n = 0;
1645         ret = mlx5_os_get_stats_n(dev);
1646         if (ret < 0) {
1647                 DRV_LOG(WARNING, "port %u no extended statistics available",
1648                         dev->data->port_id);
1649                 return;
1650         }
1651         dev_stats_n = ret;
1652         /* Allocate memory to grab stat names and values. */
1653         str_sz = dev_stats_n * ETH_GSTRING_LEN;
1654         strings = (struct ethtool_gstrings *)
1655                   mlx5_malloc(0, str_sz + sizeof(struct ethtool_gstrings), 0,
1656                               SOCKET_ID_ANY);
1657         if (!strings) {
1658                 DRV_LOG(WARNING, "port %u unable to allocate memory for xstats",
1659                      dev->data->port_id);
1660                 return;
1661         }
1662         strings->cmd = ETHTOOL_GSTRINGS;
1663         strings->string_set = ETH_SS_STATS;
1664         strings->len = dev_stats_n;
1665         ifr.ifr_data = (caddr_t)strings;
1666         if (priv->master && priv->pf_bond >= 0)
1667                 /* Bonding master. */
1668                 ret = mlx5_ifreq_by_ifname(priv->sh->bond.ports[0].ifname,
1669                                            SIOCETHTOOL, &ifr);
1670         else
1671                 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1672         if (ret) {
1673                 DRV_LOG(WARNING, "port %u unable to get statistic names",
1674                         dev->data->port_id);
1675                 goto free;
1676         }
1677         for (i = 0; i != dev_stats_n; ++i) {
1678                 const char *curr_string = (const char *)
1679                         &strings->data[i * ETH_GSTRING_LEN];
1680
1681                 for (j = 0; j != xstats_n; ++j) {
1682                         if (!strcmp(mlx5_counters_init[j].ctr_name,
1683                                     curr_string)) {
1684                                 unsigned int idx = xstats_ctrl->mlx5_stats_n++;
1685
1686                                 xstats_ctrl->dev_table_idx[idx] = i;
1687                                 xstats_ctrl->info[idx] = mlx5_counters_init[j];
1688                                 break;
1689                         }
1690                 }
1691         }
1692         /* Add dev counters. */
1693         MLX5_ASSERT(xstats_ctrl->mlx5_stats_n <= MLX5_MAX_XSTATS);
1694         for (i = 0; i != xstats_n; ++i) {
1695                 if (mlx5_counters_init[i].dev) {
1696                         unsigned int idx = xstats_ctrl->mlx5_stats_n++;
1697
1698                         xstats_ctrl->info[idx] = mlx5_counters_init[i];
1699                         xstats_ctrl->hw_stats[idx] = 0;
1700                 }
1701         }
1702         xstats_ctrl->stats_n = dev_stats_n;
1703         /* Copy to base at first time. */
1704         ret = mlx5_os_read_dev_counters(dev, xstats_ctrl->base);
1705         if (ret)
1706                 DRV_LOG(ERR, "port %u cannot read device counters: %s",
1707                         dev->data->port_id, strerror(rte_errno));
1708         mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
1709         stats_ctrl->imissed = 0;
1710 free:
1711         mlx5_free(strings);
1712 }
1713
1714 /**
1715  * Get MAC address by querying netdevice.
1716  *
1717  * @param[in] dev
1718  *   Pointer to Ethernet device.
1719  * @param[out] mac
1720  *   MAC address output buffer.
1721  *
1722  * @return
1723  *   0 on success, a negative errno value otherwise and rte_errno is set.
1724  */
1725 int
1726 mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[RTE_ETHER_ADDR_LEN])
1727 {
1728         struct ifreq request;
1729         int ret;
1730
1731         ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request);
1732         if (ret)
1733                 return ret;
1734         memcpy(mac, request.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
1735         return 0;
1736 }
1737
1738 /*
1739  * Query dropless_rq private flag value provided by ETHTOOL.
1740  *
1741  * @param dev
1742  *   Pointer to Ethernet device.
1743  *
1744  * @return
1745  *   - 0 on success, flag is not set.
1746  *   - 1 on success, flag is set.
1747  *   - negative errno value otherwise and rte_errno is set.
1748  */
1749 int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev)
1750 {
1751         struct {
1752                 struct ethtool_sset_info hdr;
1753                 uint32_t buf[1];
1754         } sset_info;
1755         struct ethtool_drvinfo drvinfo;
1756         struct ifreq ifr;
1757         struct ethtool_gstrings *strings = NULL;
1758         struct ethtool_value flags;
1759         const int32_t flag_len = sizeof(flags.data) * CHAR_BIT;
1760         int32_t str_sz;
1761         int32_t len;
1762         int32_t i;
1763         int ret;
1764
1765         sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
1766         sset_info.hdr.reserved = 0;
1767         sset_info.hdr.sset_mask = 1ULL << ETH_SS_PRIV_FLAGS;
1768         ifr.ifr_data = (caddr_t)&sset_info;
1769         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1770         if (!ret) {
1771                 const uint32_t *sset_lengths = sset_info.hdr.data;
1772
1773                 len = sset_info.hdr.sset_mask ? sset_lengths[0] : 0;
1774         } else if (ret == -EOPNOTSUPP) {
1775                 drvinfo.cmd = ETHTOOL_GDRVINFO;
1776                 ifr.ifr_data = (caddr_t)&drvinfo;
1777                 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1778                 if (ret) {
1779                         DRV_LOG(WARNING, "port %u cannot get the driver info",
1780                                 dev->data->port_id);
1781                         goto exit;
1782                 }
1783                 len = *(uint32_t *)((char *)&drvinfo +
1784                         offsetof(struct ethtool_drvinfo, n_priv_flags));
1785         } else {
1786                 DRV_LOG(WARNING, "port %u cannot get the sset info",
1787                         dev->data->port_id);
1788                 goto exit;
1789         }
1790         if (!len) {
1791                 DRV_LOG(WARNING, "port %u does not have private flag",
1792                         dev->data->port_id);
1793                 rte_errno = EOPNOTSUPP;
1794                 ret = -rte_errno;
1795                 goto exit;
1796         } else if (len > flag_len) {
1797                 DRV_LOG(WARNING, "port %u maximal private flags number is %d",
1798                         dev->data->port_id, flag_len);
1799                 len = flag_len;
1800         }
1801         str_sz = ETH_GSTRING_LEN * len;
1802         strings = (struct ethtool_gstrings *)
1803                   mlx5_malloc(0, str_sz + sizeof(struct ethtool_gstrings), 0,
1804                               SOCKET_ID_ANY);
1805         if (!strings) {
1806                 DRV_LOG(WARNING, "port %u unable to allocate memory for"
1807                         " private flags", dev->data->port_id);
1808                 rte_errno = ENOMEM;
1809                 ret = -rte_errno;
1810                 goto exit;
1811         }
1812         strings->cmd = ETHTOOL_GSTRINGS;
1813         strings->string_set = ETH_SS_PRIV_FLAGS;
1814         strings->len = len;
1815         ifr.ifr_data = (caddr_t)strings;
1816         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1817         if (ret) {
1818                 DRV_LOG(WARNING, "port %u unable to get private flags strings",
1819                         dev->data->port_id);
1820                 goto exit;
1821         }
1822         for (i = 0; i < len; i++) {
1823                 strings->data[(i + 1) * ETH_GSTRING_LEN - 1] = 0;
1824                 if (!strcmp((const char *)strings->data + i * ETH_GSTRING_LEN,
1825                              "dropless_rq"))
1826                         break;
1827         }
1828         if (i == len) {
1829                 DRV_LOG(WARNING, "port %u does not support dropless_rq",
1830                         dev->data->port_id);
1831                 rte_errno = EOPNOTSUPP;
1832                 ret = -rte_errno;
1833                 goto exit;
1834         }
1835         flags.cmd = ETHTOOL_GPFLAGS;
1836         ifr.ifr_data = (caddr_t)&flags;
1837         ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
1838         if (ret) {
1839                 DRV_LOG(WARNING, "port %u unable to get private flags status",
1840                         dev->data->port_id);
1841                 goto exit;
1842         }
1843         ret = !!(flags.data & (1U << i));
1844 exit:
1845         mlx5_free(strings);
1846         return ret;
1847 }