4 * Copyright 2015 6WIND S.A.
5 * Copyright 2015 Mellanox.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
43 #include <sys/ioctl.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
48 /* DPDK headers don't like -pedantic. */
50 #pragma GCC diagnostic ignored "-pedantic"
52 #include <rte_atomic.h>
53 #include <rte_ethdev.h>
55 #include <rte_common.h>
57 #pragma GCC diagnostic error "-pedantic"
61 #include "mlx5_utils.h"
64 * Get interface name from private structure.
67 * Pointer to private structure.
69 * Interface name output buffer.
72 * 0 on success, -1 on failure and errno is set.
75 priv_get_ifname(const struct priv *priv, char (*ifname)[IF_NAMESIZE])
79 unsigned int dev_type = 0;
80 unsigned int dev_port_prev = ~0u;
81 char match[IF_NAMESIZE] = "";
84 MKSTR(path, "%s/device/net", priv->ctx->device->ibdev_path);
90 while ((dent = readdir(dir)) != NULL) {
91 char *name = dent->d_name;
93 unsigned int dev_port;
96 if ((name[0] == '.') &&
98 ((name[1] == '.') && (name[2] == '\0'))))
101 MKSTR(path, "%s/device/net/%s/%s",
102 priv->ctx->device->ibdev_path, name,
103 (dev_type ? "dev_id" : "dev_port"));
105 file = fopen(path, "rb");
110 * Switch to dev_id when dev_port does not exist as
111 * is the case with Linux kernel versions < 3.15.
122 r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port);
127 * Switch to dev_id when dev_port returns the same value for
128 * all ports. May happen when using a MOFED release older than
129 * 3.0 with a Linux kernel >= 3.15.
131 if (dev_port == dev_port_prev)
133 dev_port_prev = dev_port;
134 if (dev_port == (priv->port - 1u))
135 snprintf(match, sizeof(match), "%s", name);
138 if (match[0] == '\0')
140 strncpy(*ifname, match, sizeof(*ifname));
145 * Read from sysfs entry.
148 * Pointer to private structure.
150 * Entry name relative to sysfs path.
152 * Data output buffer.
157 * 0 on success, -1 on failure and errno is set.
160 priv_sysfs_read(const struct priv *priv, const char *entry,
161 char *buf, size_t size)
163 char ifname[IF_NAMESIZE];
168 if (priv_get_ifname(priv, &ifname))
171 MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
174 file = fopen(path, "rb");
177 ret = fread(buf, 1, size, file);
179 if (((size_t)ret < size) && (ferror(file)))
189 * Write to sysfs entry.
192 * Pointer to private structure.
194 * Entry name relative to sysfs path.
201 * 0 on success, -1 on failure and errno is set.
204 priv_sysfs_write(const struct priv *priv, const char *entry,
205 char *buf, size_t size)
207 char ifname[IF_NAMESIZE];
212 if (priv_get_ifname(priv, &ifname))
215 MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
218 file = fopen(path, "wb");
221 ret = fwrite(buf, 1, size, file);
223 if (((size_t)ret < size) || (ferror(file)))
233 * Get unsigned long sysfs property.
236 * Pointer to private structure.
238 * Entry name relative to sysfs path.
240 * Value output buffer.
243 * 0 on success, -1 on failure and errno is set.
246 priv_get_sysfs_ulong(struct priv *priv, const char *name, unsigned long *value)
249 unsigned long value_ret;
252 ret = priv_sysfs_read(priv, name, value_str, (sizeof(value_str) - 1));
254 DEBUG("cannot read %s value from sysfs: %s",
255 name, strerror(errno));
258 value_str[ret] = '\0';
260 value_ret = strtoul(value_str, NULL, 0);
262 DEBUG("invalid %s value `%s': %s", name, value_str,
271 * Set unsigned long sysfs property.
274 * Pointer to private structure.
276 * Entry name relative to sysfs path.
281 * 0 on success, -1 on failure and errno is set.
284 priv_set_sysfs_ulong(struct priv *priv, const char *name, unsigned long value)
287 MKSTR(value_str, "%lu", value);
289 ret = priv_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1));
291 DEBUG("cannot write %s `%s' (%lu) to sysfs: %s",
292 name, value_str, value, strerror(errno));
299 * Perform ifreq ioctl() on associated Ethernet device.
302 * Pointer to private structure.
304 * Request number to pass to ioctl().
306 * Interface request structure output buffer.
309 * 0 on success, -1 on failure and errno is set.
312 priv_ifreq(const struct priv *priv, int req, struct ifreq *ifr)
314 int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
319 if (priv_get_ifname(priv, &ifr->ifr_name) == 0)
320 ret = ioctl(sock, req, ifr);
329 * Pointer to private structure.
331 * MTU value output buffer.
334 * 0 on success, -1 on failure and errno is set.
337 priv_get_mtu(struct priv *priv, uint16_t *mtu)
339 unsigned long ulong_mtu;
341 if (priv_get_sysfs_ulong(priv, "mtu", &ulong_mtu) == -1)
351 * Pointer to private structure.
353 * Bitmask for flags that must remain untouched.
355 * Bitmask for flags to modify.
358 * 0 on success, -1 on failure and errno is set.
361 priv_set_flags(struct priv *priv, unsigned int keep, unsigned int flags)
365 if (priv_get_sysfs_ulong(priv, "flags", &tmp) == -1)
369 return priv_set_sysfs_ulong(priv, "flags", tmp);
373 * Get PCI information from struct ibv_device.
376 * Pointer to Ethernet device structure.
377 * @param[out] pci_addr
378 * PCI bus address output buffer.
381 * 0 on success, -1 on failure and errno is set.
384 mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
385 struct rte_pci_addr *pci_addr)
389 MKSTR(path, "%s/device/uevent", device->ibdev_path);
391 file = fopen(path, "rb");
394 while (fgets(line, sizeof(line), file) == line) {
395 size_t len = strlen(line);
398 /* Truncate long lines. */
399 if (len == (sizeof(line) - 1))
400 while (line[(len - 1)] != '\n') {
404 line[(len - 1)] = ret;
406 /* Extract information. */
409 "%" SCNx16 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
413 &pci_addr->function) == 4) {