mlx5: support flow control
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2015 6WIND S.A.
5  *   Copyright 2015 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stddef.h>
35 #include <assert.h>
36 #include <unistd.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <errno.h>
42 #include <dirent.h>
43 #include <net/if.h>
44 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <linux/if.h>
48 #include <linux/ethtool.h>
49 #include <linux/sockios.h>
50
51 /* DPDK headers don't like -pedantic. */
52 #ifdef PEDANTIC
53 #pragma GCC diagnostic ignored "-pedantic"
54 #endif
55 #include <rte_atomic.h>
56 #include <rte_ethdev.h>
57 #include <rte_mbuf.h>
58 #include <rte_common.h>
59 #ifdef PEDANTIC
60 #pragma GCC diagnostic error "-pedantic"
61 #endif
62
63 #include "mlx5.h"
64 #include "mlx5_rxtx.h"
65 #include "mlx5_utils.h"
66
67 /**
68  * Get interface name from private structure.
69  *
70  * @param[in] priv
71  *   Pointer to private structure.
72  * @param[out] ifname
73  *   Interface name output buffer.
74  *
75  * @return
76  *   0 on success, -1 on failure and errno is set.
77  */
78 int
79 priv_get_ifname(const struct priv *priv, char (*ifname)[IF_NAMESIZE])
80 {
81         DIR *dir;
82         struct dirent *dent;
83         unsigned int dev_type = 0;
84         unsigned int dev_port_prev = ~0u;
85         char match[IF_NAMESIZE] = "";
86
87         {
88                 MKSTR(path, "%s/device/net", priv->ctx->device->ibdev_path);
89
90                 dir = opendir(path);
91                 if (dir == NULL)
92                         return -1;
93         }
94         while ((dent = readdir(dir)) != NULL) {
95                 char *name = dent->d_name;
96                 FILE *file;
97                 unsigned int dev_port;
98                 int r;
99
100                 if ((name[0] == '.') &&
101                     ((name[1] == '\0') ||
102                      ((name[1] == '.') && (name[2] == '\0'))))
103                         continue;
104
105                 MKSTR(path, "%s/device/net/%s/%s",
106                       priv->ctx->device->ibdev_path, name,
107                       (dev_type ? "dev_id" : "dev_port"));
108
109                 file = fopen(path, "rb");
110                 if (file == NULL) {
111                         if (errno != ENOENT)
112                                 continue;
113                         /*
114                          * Switch to dev_id when dev_port does not exist as
115                          * is the case with Linux kernel versions < 3.15.
116                          */
117 try_dev_id:
118                         match[0] = '\0';
119                         if (dev_type)
120                                 break;
121                         dev_type = 1;
122                         dev_port_prev = ~0u;
123                         rewinddir(dir);
124                         continue;
125                 }
126                 r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port);
127                 fclose(file);
128                 if (r != 1)
129                         continue;
130                 /*
131                  * Switch to dev_id when dev_port returns the same value for
132                  * all ports. May happen when using a MOFED release older than
133                  * 3.0 with a Linux kernel >= 3.15.
134                  */
135                 if (dev_port == dev_port_prev)
136                         goto try_dev_id;
137                 dev_port_prev = dev_port;
138                 if (dev_port == (priv->port - 1u))
139                         snprintf(match, sizeof(match), "%s", name);
140         }
141         closedir(dir);
142         if (match[0] == '\0')
143                 return -1;
144         strncpy(*ifname, match, sizeof(*ifname));
145         return 0;
146 }
147
148 /**
149  * Read from sysfs entry.
150  *
151  * @param[in] priv
152  *   Pointer to private structure.
153  * @param[in] entry
154  *   Entry name relative to sysfs path.
155  * @param[out] buf
156  *   Data output buffer.
157  * @param size
158  *   Buffer size.
159  *
160  * @return
161  *   0 on success, -1 on failure and errno is set.
162  */
163 static int
164 priv_sysfs_read(const struct priv *priv, const char *entry,
165                 char *buf, size_t size)
166 {
167         char ifname[IF_NAMESIZE];
168         FILE *file;
169         int ret;
170         int err;
171
172         if (priv_get_ifname(priv, &ifname))
173                 return -1;
174
175         MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
176               ifname, entry);
177
178         file = fopen(path, "rb");
179         if (file == NULL)
180                 return -1;
181         ret = fread(buf, 1, size, file);
182         err = errno;
183         if (((size_t)ret < size) && (ferror(file)))
184                 ret = -1;
185         else
186                 ret = size;
187         fclose(file);
188         errno = err;
189         return ret;
190 }
191
192 /**
193  * Write to sysfs entry.
194  *
195  * @param[in] priv
196  *   Pointer to private structure.
197  * @param[in] entry
198  *   Entry name relative to sysfs path.
199  * @param[in] buf
200  *   Data buffer.
201  * @param size
202  *   Buffer size.
203  *
204  * @return
205  *   0 on success, -1 on failure and errno is set.
206  */
207 static int
208 priv_sysfs_write(const struct priv *priv, const char *entry,
209                  char *buf, size_t size)
210 {
211         char ifname[IF_NAMESIZE];
212         FILE *file;
213         int ret;
214         int err;
215
216         if (priv_get_ifname(priv, &ifname))
217                 return -1;
218
219         MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
220               ifname, entry);
221
222         file = fopen(path, "wb");
223         if (file == NULL)
224                 return -1;
225         ret = fwrite(buf, 1, size, file);
226         err = errno;
227         if (((size_t)ret < size) || (ferror(file)))
228                 ret = -1;
229         else
230                 ret = size;
231         fclose(file);
232         errno = err;
233         return ret;
234 }
235
236 /**
237  * Get unsigned long sysfs property.
238  *
239  * @param priv
240  *   Pointer to private structure.
241  * @param[in] name
242  *   Entry name relative to sysfs path.
243  * @param[out] value
244  *   Value output buffer.
245  *
246  * @return
247  *   0 on success, -1 on failure and errno is set.
248  */
249 static int
250 priv_get_sysfs_ulong(struct priv *priv, const char *name, unsigned long *value)
251 {
252         int ret;
253         unsigned long value_ret;
254         char value_str[32];
255
256         ret = priv_sysfs_read(priv, name, value_str, (sizeof(value_str) - 1));
257         if (ret == -1) {
258                 DEBUG("cannot read %s value from sysfs: %s",
259                       name, strerror(errno));
260                 return -1;
261         }
262         value_str[ret] = '\0';
263         errno = 0;
264         value_ret = strtoul(value_str, NULL, 0);
265         if (errno) {
266                 DEBUG("invalid %s value `%s': %s", name, value_str,
267                       strerror(errno));
268                 return -1;
269         }
270         *value = value_ret;
271         return 0;
272 }
273
274 /**
275  * Set unsigned long sysfs property.
276  *
277  * @param priv
278  *   Pointer to private structure.
279  * @param[in] name
280  *   Entry name relative to sysfs path.
281  * @param value
282  *   Value to set.
283  *
284  * @return
285  *   0 on success, -1 on failure and errno is set.
286  */
287 static int
288 priv_set_sysfs_ulong(struct priv *priv, const char *name, unsigned long value)
289 {
290         int ret;
291         MKSTR(value_str, "%lu", value);
292
293         ret = priv_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1));
294         if (ret == -1) {
295                 DEBUG("cannot write %s `%s' (%lu) to sysfs: %s",
296                       name, value_str, value, strerror(errno));
297                 return -1;
298         }
299         return 0;
300 }
301
302 /**
303  * Perform ifreq ioctl() on associated Ethernet device.
304  *
305  * @param[in] priv
306  *   Pointer to private structure.
307  * @param req
308  *   Request number to pass to ioctl().
309  * @param[out] ifr
310  *   Interface request structure output buffer.
311  *
312  * @return
313  *   0 on success, -1 on failure and errno is set.
314  */
315 int
316 priv_ifreq(const struct priv *priv, int req, struct ifreq *ifr)
317 {
318         int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
319         int ret = -1;
320
321         if (sock == -1)
322                 return ret;
323         if (priv_get_ifname(priv, &ifr->ifr_name) == 0)
324                 ret = ioctl(sock, req, ifr);
325         close(sock);
326         return ret;
327 }
328
329 /**
330  * Get device MTU.
331  *
332  * @param priv
333  *   Pointer to private structure.
334  * @param[out] mtu
335  *   MTU value output buffer.
336  *
337  * @return
338  *   0 on success, -1 on failure and errno is set.
339  */
340 int
341 priv_get_mtu(struct priv *priv, uint16_t *mtu)
342 {
343         unsigned long ulong_mtu;
344
345         if (priv_get_sysfs_ulong(priv, "mtu", &ulong_mtu) == -1)
346                 return -1;
347         *mtu = ulong_mtu;
348         return 0;
349 }
350
351 /**
352  * Set device MTU.
353  *
354  * @param priv
355  *   Pointer to private structure.
356  * @param mtu
357  *   MTU value to set.
358  *
359  * @return
360  *   0 on success, -1 on failure and errno is set.
361  */
362 static int
363 priv_set_mtu(struct priv *priv, uint16_t mtu)
364 {
365         return priv_set_sysfs_ulong(priv, "mtu", mtu);
366 }
367
368 /**
369  * Set device flags.
370  *
371  * @param priv
372  *   Pointer to private structure.
373  * @param keep
374  *   Bitmask for flags that must remain untouched.
375  * @param flags
376  *   Bitmask for flags to modify.
377  *
378  * @return
379  *   0 on success, -1 on failure and errno is set.
380  */
381 int
382 priv_set_flags(struct priv *priv, unsigned int keep, unsigned int flags)
383 {
384         unsigned long tmp;
385
386         if (priv_get_sysfs_ulong(priv, "flags", &tmp) == -1)
387                 return -1;
388         tmp &= keep;
389         tmp |= flags;
390         return priv_set_sysfs_ulong(priv, "flags", tmp);
391 }
392
393 /**
394  * Ethernet device configuration.
395  *
396  * Prepare the driver for a given number of TX and RX queues.
397  * Allocate parent RSS queue when several RX queues are requested.
398  *
399  * @param dev
400  *   Pointer to Ethernet device structure.
401  *
402  * @return
403  *   0 on success, errno value on failure.
404  */
405 static int
406 dev_configure(struct rte_eth_dev *dev)
407 {
408         struct priv *priv = dev->data->dev_private;
409         unsigned int rxqs_n = dev->data->nb_rx_queues;
410         unsigned int txqs_n = dev->data->nb_tx_queues;
411         unsigned int tmp;
412         int ret;
413
414         priv->rxqs = (void *)dev->data->rx_queues;
415         priv->txqs = (void *)dev->data->tx_queues;
416         if (txqs_n != priv->txqs_n) {
417                 INFO("%p: TX queues number update: %u -> %u",
418                      (void *)dev, priv->txqs_n, txqs_n);
419                 priv->txqs_n = txqs_n;
420         }
421         if (rxqs_n == priv->rxqs_n)
422                 return 0;
423         INFO("%p: RX queues number update: %u -> %u",
424              (void *)dev, priv->rxqs_n, rxqs_n);
425         /* If RSS is enabled, disable it first. */
426         if (priv->rss) {
427                 unsigned int i;
428
429                 /* Only if there are no remaining child RX queues. */
430                 for (i = 0; (i != priv->rxqs_n); ++i)
431                         if ((*priv->rxqs)[i] != NULL)
432                                 return EINVAL;
433                 rxq_cleanup(&priv->rxq_parent);
434                 priv->rss = 0;
435                 priv->rxqs_n = 0;
436         }
437         if (rxqs_n <= 1) {
438                 /* Nothing else to do. */
439                 priv->rxqs_n = rxqs_n;
440                 return 0;
441         }
442         /* Allocate a new RSS parent queue if supported by hardware. */
443         if (!priv->hw_rss) {
444                 ERROR("%p: only a single RX queue can be configured when"
445                       " hardware doesn't support RSS",
446                       (void *)dev);
447                 return EINVAL;
448         }
449         /* Fail if hardware doesn't support that many RSS queues. */
450         if (rxqs_n >= priv->max_rss_tbl_sz) {
451                 ERROR("%p: only %u RX queues can be configured for RSS",
452                       (void *)dev, priv->max_rss_tbl_sz);
453                 return EINVAL;
454         }
455         priv->rss = 1;
456         tmp = priv->rxqs_n;
457         priv->rxqs_n = rxqs_n;
458         ret = rxq_setup(dev, &priv->rxq_parent, 0, 0, NULL, NULL);
459         if (!ret)
460                 return 0;
461         /* Failure, rollback. */
462         priv->rss = 0;
463         priv->rxqs_n = tmp;
464         assert(ret > 0);
465         return ret;
466 }
467
468 /**
469  * DPDK callback for Ethernet device configuration.
470  *
471  * @param dev
472  *   Pointer to Ethernet device structure.
473  *
474  * @return
475  *   0 on success, negative errno value on failure.
476  */
477 int
478 mlx5_dev_configure(struct rte_eth_dev *dev)
479 {
480         struct priv *priv = dev->data->dev_private;
481         int ret;
482
483         priv_lock(priv);
484         ret = dev_configure(dev);
485         assert(ret >= 0);
486         priv_unlock(priv);
487         return -ret;
488 }
489
490 /**
491  * DPDK callback to get information about the device.
492  *
493  * @param dev
494  *   Pointer to Ethernet device structure.
495  * @param[out] info
496  *   Info structure output buffer.
497  */
498 void
499 mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
500 {
501         struct priv *priv = dev->data->dev_private;
502         unsigned int max;
503         char ifname[IF_NAMESIZE];
504
505         priv_lock(priv);
506         /* FIXME: we should ask the device for these values. */
507         info->min_rx_bufsize = 32;
508         info->max_rx_pktlen = 65536;
509         /*
510          * Since we need one CQ per QP, the limit is the minimum number
511          * between the two values.
512          */
513         max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ?
514                priv->device_attr.max_qp : priv->device_attr.max_cq);
515         /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
516         if (max >= 65535)
517                 max = 65535;
518         info->max_rx_queues = max;
519         info->max_tx_queues = max;
520         /* Last array entry is reserved for broadcast. */
521         info->max_mac_addrs = (RTE_DIM(priv->mac) - 1);
522         info->rx_offload_capa =
523                 (priv->hw_csum ?
524                  (DEV_RX_OFFLOAD_IPV4_CKSUM |
525                   DEV_RX_OFFLOAD_UDP_CKSUM |
526                   DEV_RX_OFFLOAD_TCP_CKSUM) :
527                  0);
528         info->tx_offload_capa =
529                 (priv->hw_csum ?
530                  (DEV_TX_OFFLOAD_IPV4_CKSUM |
531                   DEV_TX_OFFLOAD_UDP_CKSUM |
532                   DEV_TX_OFFLOAD_TCP_CKSUM) :
533                  0);
534         if (priv_get_ifname(priv, &ifname) == 0)
535                 info->if_index = if_nametoindex(ifname);
536         priv_unlock(priv);
537 }
538
539 /**
540  * DPDK callback to retrieve physical link information (unlocked version).
541  *
542  * @param dev
543  *   Pointer to Ethernet device structure.
544  * @param wait_to_complete
545  *   Wait for request completion (ignored).
546  */
547 static int
548 mlx5_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
549 {
550         struct priv *priv = dev->data->dev_private;
551         struct ethtool_cmd edata = {
552                 .cmd = ETHTOOL_GSET
553         };
554         struct ifreq ifr;
555         struct rte_eth_link dev_link;
556         int link_speed = 0;
557
558         (void)wait_to_complete;
559         if (priv_ifreq(priv, SIOCGIFFLAGS, &ifr)) {
560                 WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno));
561                 return -1;
562         }
563         memset(&dev_link, 0, sizeof(dev_link));
564         dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
565                                 (ifr.ifr_flags & IFF_RUNNING));
566         ifr.ifr_data = &edata;
567         if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) {
568                 WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
569                      strerror(errno));
570                 return -1;
571         }
572         link_speed = ethtool_cmd_speed(&edata);
573         if (link_speed == -1)
574                 dev_link.link_speed = 0;
575         else
576                 dev_link.link_speed = link_speed;
577         dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
578                                 ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
579         if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) {
580                 /* Link status changed. */
581                 dev->data->dev_link = dev_link;
582                 return 0;
583         }
584         /* Link status is still the same. */
585         return -1;
586 }
587
588 /**
589  * DPDK callback to retrieve physical link information.
590  *
591  * @param dev
592  *   Pointer to Ethernet device structure.
593  * @param wait_to_complete
594  *   Wait for request completion (ignored).
595  */
596 int
597 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
598 {
599         struct priv *priv = dev->data->dev_private;
600         int ret;
601
602         priv_lock(priv);
603         ret = mlx5_link_update_unlocked(dev, wait_to_complete);
604         priv_unlock(priv);
605         return ret;
606 }
607
608 /**
609  * DPDK callback to change the MTU.
610  *
611  * Setting the MTU affects hardware MRU (packets larger than the MTU cannot be
612  * received). Use this as a hint to enable/disable scattered packets support
613  * and improve performance when not needed.
614  * Since failure is not an option, reconfiguring queues on the fly is not
615  * recommended.
616  *
617  * @param dev
618  *   Pointer to Ethernet device structure.
619  * @param in_mtu
620  *   New MTU.
621  *
622  * @return
623  *   0 on success, negative errno value on failure.
624  */
625 int
626 mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
627 {
628         struct priv *priv = dev->data->dev_private;
629         int ret = 0;
630         unsigned int i;
631         uint16_t (*rx_func)(void *, struct rte_mbuf **, uint16_t) =
632                 mlx5_rx_burst;
633
634         priv_lock(priv);
635         /* Set kernel interface MTU first. */
636         if (priv_set_mtu(priv, mtu)) {
637                 ret = errno;
638                 WARN("cannot set port %u MTU to %u: %s", priv->port, mtu,
639                      strerror(ret));
640                 goto out;
641         } else
642                 DEBUG("adapter port %u MTU set to %u", priv->port, mtu);
643         priv->mtu = mtu;
644         /* Temporarily replace RX handler with a fake one, assuming it has not
645          * been copied elsewhere. */
646         dev->rx_pkt_burst = removed_rx_burst;
647         /* Make sure everyone has left mlx5_rx_burst() and uses
648          * removed_rx_burst() instead. */
649         rte_wmb();
650         usleep(1000);
651         /* Reconfigure each RX queue. */
652         for (i = 0; (i != priv->rxqs_n); ++i) {
653                 struct rxq *rxq = (*priv->rxqs)[i];
654                 unsigned int max_frame_len;
655                 int sp;
656
657                 if (rxq == NULL)
658                         continue;
659                 /* Calculate new maximum frame length according to MTU and
660                  * toggle scattered support (sp) if necessary. */
661                 max_frame_len = (priv->mtu + ETHER_HDR_LEN +
662                                  (ETHER_MAX_VLAN_FRAME_LEN - ETHER_MAX_LEN));
663                 sp = (max_frame_len > (rxq->mb_len - RTE_PKTMBUF_HEADROOM));
664                 /* Provide new values to rxq_setup(). */
665                 dev->data->dev_conf.rxmode.jumbo_frame = sp;
666                 dev->data->dev_conf.rxmode.max_rx_pkt_len = max_frame_len;
667                 ret = rxq_rehash(dev, rxq);
668                 if (ret) {
669                         /* Force SP RX if that queue requires it and abort. */
670                         if (rxq->sp)
671                                 rx_func = mlx5_rx_burst_sp;
672                         break;
673                 }
674                 /* Reenable non-RSS queue attributes. No need to check
675                  * for errors at this stage. */
676                 if (!priv->rss) {
677                         if (priv->started)
678                                 rxq_mac_addrs_add(rxq);
679                         if (priv->started && priv->promisc_req)
680                                 rxq_promiscuous_enable(rxq);
681                         if (priv->started && priv->allmulti_req)
682                                 rxq_allmulticast_enable(rxq);
683                 }
684                 /* Scattered burst function takes priority. */
685                 if (rxq->sp)
686                         rx_func = mlx5_rx_burst_sp;
687         }
688         /* Burst functions can now be called again. */
689         rte_wmb();
690         dev->rx_pkt_burst = rx_func;
691 out:
692         priv_unlock(priv);
693         assert(ret >= 0);
694         return -ret;
695 }
696
697 /**
698  * DPDK callback to get flow control status.
699  *
700  * @param dev
701  *   Pointer to Ethernet device structure.
702  * @param[out] fc_conf
703  *   Flow control output buffer.
704  *
705  * @return
706  *   0 on success, negative errno value on failure.
707  */
708 int
709 mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
710 {
711         struct priv *priv = dev->data->dev_private;
712         struct ifreq ifr;
713         struct ethtool_pauseparam ethpause = {
714                 .cmd = ETHTOOL_GPAUSEPARAM
715         };
716         int ret;
717
718         ifr.ifr_data = &ethpause;
719         priv_lock(priv);
720         if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) {
721                 ret = errno;
722                 WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM)"
723                      " failed: %s",
724                      strerror(ret));
725                 goto out;
726         }
727
728         fc_conf->autoneg = ethpause.autoneg;
729         if (ethpause.rx_pause && ethpause.tx_pause)
730                 fc_conf->mode = RTE_FC_FULL;
731         else if (ethpause.rx_pause)
732                 fc_conf->mode = RTE_FC_RX_PAUSE;
733         else if (ethpause.tx_pause)
734                 fc_conf->mode = RTE_FC_TX_PAUSE;
735         else
736                 fc_conf->mode = RTE_FC_NONE;
737         ret = 0;
738
739 out:
740         priv_unlock(priv);
741         assert(ret >= 0);
742         return -ret;
743 }
744
745 /**
746  * DPDK callback to modify flow control parameters.
747  *
748  * @param dev
749  *   Pointer to Ethernet device structure.
750  * @param[in] fc_conf
751  *   Flow control parameters.
752  *
753  * @return
754  *   0 on success, negative errno value on failure.
755  */
756 int
757 mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
758 {
759         struct priv *priv = dev->data->dev_private;
760         struct ifreq ifr;
761         struct ethtool_pauseparam ethpause = {
762                 .cmd = ETHTOOL_SPAUSEPARAM
763         };
764         int ret;
765
766         ifr.ifr_data = &ethpause;
767         ethpause.autoneg = fc_conf->autoneg;
768         if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
769             (fc_conf->mode & RTE_FC_RX_PAUSE))
770                 ethpause.rx_pause = 1;
771         else
772                 ethpause.rx_pause = 0;
773
774         if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
775             (fc_conf->mode & RTE_FC_TX_PAUSE))
776                 ethpause.tx_pause = 1;
777         else
778                 ethpause.tx_pause = 0;
779
780         priv_lock(priv);
781         if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) {
782                 ret = errno;
783                 WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
784                      " failed: %s",
785                      strerror(ret));
786                 goto out;
787         }
788         ret = 0;
789
790 out:
791         priv_unlock(priv);
792         assert(ret >= 0);
793         return -ret;
794 }
795
796 /**
797  * Get PCI information from struct ibv_device.
798  *
799  * @param device
800  *   Pointer to Ethernet device structure.
801  * @param[out] pci_addr
802  *   PCI bus address output buffer.
803  *
804  * @return
805  *   0 on success, -1 on failure and errno is set.
806  */
807 int
808 mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
809                             struct rte_pci_addr *pci_addr)
810 {
811         FILE *file;
812         char line[32];
813         MKSTR(path, "%s/device/uevent", device->ibdev_path);
814
815         file = fopen(path, "rb");
816         if (file == NULL)
817                 return -1;
818         while (fgets(line, sizeof(line), file) == line) {
819                 size_t len = strlen(line);
820                 int ret;
821
822                 /* Truncate long lines. */
823                 if (len == (sizeof(line) - 1))
824                         while (line[(len - 1)] != '\n') {
825                                 ret = fgetc(file);
826                                 if (ret == EOF)
827                                         break;
828                                 line[(len - 1)] = ret;
829                         }
830                 /* Extract information. */
831                 if (sscanf(line,
832                            "PCI_SLOT_NAME="
833                            "%" SCNx16 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
834                            &pci_addr->domain,
835                            &pci_addr->bus,
836                            &pci_addr->devid,
837                            &pci_addr->function) == 4) {
838                         ret = 0;
839                         break;
840                 }
841         }
842         fclose(file);
843         return 0;
844 }