1771fa900SAdrien Mazarguil /*- 2771fa900SAdrien Mazarguil * BSD LICENSE 3771fa900SAdrien Mazarguil * 4771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 5771fa900SAdrien Mazarguil * Copyright 2015 Mellanox. 6771fa900SAdrien Mazarguil * 7771fa900SAdrien Mazarguil * Redistribution and use in source and binary forms, with or without 8771fa900SAdrien Mazarguil * modification, are permitted provided that the following conditions 9771fa900SAdrien Mazarguil * are met: 10771fa900SAdrien Mazarguil * 11771fa900SAdrien Mazarguil * * Redistributions of source code must retain the above copyright 12771fa900SAdrien Mazarguil * notice, this list of conditions and the following disclaimer. 13771fa900SAdrien Mazarguil * * Redistributions in binary form must reproduce the above copyright 14771fa900SAdrien Mazarguil * notice, this list of conditions and the following disclaimer in 15771fa900SAdrien Mazarguil * the documentation and/or other materials provided with the 16771fa900SAdrien Mazarguil * distribution. 17771fa900SAdrien Mazarguil * * Neither the name of 6WIND S.A. nor the names of its 18771fa900SAdrien Mazarguil * contributors may be used to endorse or promote products derived 19771fa900SAdrien Mazarguil * from this software without specific prior written permission. 20771fa900SAdrien Mazarguil * 21771fa900SAdrien Mazarguil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22771fa900SAdrien Mazarguil * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23771fa900SAdrien Mazarguil * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24771fa900SAdrien Mazarguil * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25771fa900SAdrien Mazarguil * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26771fa900SAdrien Mazarguil * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27771fa900SAdrien Mazarguil * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28771fa900SAdrien Mazarguil * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29771fa900SAdrien Mazarguil * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30771fa900SAdrien Mazarguil * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31771fa900SAdrien Mazarguil * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32771fa900SAdrien Mazarguil */ 33771fa900SAdrien Mazarguil 34771fa900SAdrien Mazarguil #include <stddef.h> 35*e60fbd5bSAdrien Mazarguil #include <assert.h> 36771fa900SAdrien Mazarguil #include <unistd.h> 37771fa900SAdrien Mazarguil #include <stdint.h> 38771fa900SAdrien Mazarguil #include <stdio.h> 39771fa900SAdrien Mazarguil #include <string.h> 40771fa900SAdrien Mazarguil #include <stdlib.h> 41771fa900SAdrien Mazarguil #include <errno.h> 42771fa900SAdrien Mazarguil #include <dirent.h> 43771fa900SAdrien Mazarguil #include <net/if.h> 44771fa900SAdrien Mazarguil #include <sys/ioctl.h> 45771fa900SAdrien Mazarguil #include <sys/socket.h> 46771fa900SAdrien Mazarguil #include <netinet/in.h> 47771fa900SAdrien Mazarguil #include <linux/if.h> 48771fa900SAdrien Mazarguil 49771fa900SAdrien Mazarguil /* DPDK headers don't like -pedantic. */ 50771fa900SAdrien Mazarguil #ifdef PEDANTIC 51771fa900SAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic" 52771fa900SAdrien Mazarguil #endif 53771fa900SAdrien Mazarguil #include <rte_atomic.h> 54771fa900SAdrien Mazarguil #include <rte_ethdev.h> 55771fa900SAdrien Mazarguil #include <rte_mbuf.h> 56771fa900SAdrien Mazarguil #include <rte_common.h> 57771fa900SAdrien Mazarguil #ifdef PEDANTIC 58771fa900SAdrien Mazarguil #pragma GCC diagnostic error "-pedantic" 59771fa900SAdrien Mazarguil #endif 60771fa900SAdrien Mazarguil 61771fa900SAdrien Mazarguil #include "mlx5.h" 62*e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 63771fa900SAdrien Mazarguil #include "mlx5_utils.h" 64771fa900SAdrien Mazarguil 65771fa900SAdrien Mazarguil /** 66771fa900SAdrien Mazarguil * Get interface name from private structure. 67771fa900SAdrien Mazarguil * 68771fa900SAdrien Mazarguil * @param[in] priv 69771fa900SAdrien Mazarguil * Pointer to private structure. 70771fa900SAdrien Mazarguil * @param[out] ifname 71771fa900SAdrien Mazarguil * Interface name output buffer. 72771fa900SAdrien Mazarguil * 73771fa900SAdrien Mazarguil * @return 74771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 75771fa900SAdrien Mazarguil */ 76771fa900SAdrien Mazarguil int 77771fa900SAdrien Mazarguil priv_get_ifname(const struct priv *priv, char (*ifname)[IF_NAMESIZE]) 78771fa900SAdrien Mazarguil { 79771fa900SAdrien Mazarguil DIR *dir; 80771fa900SAdrien Mazarguil struct dirent *dent; 81771fa900SAdrien Mazarguil unsigned int dev_type = 0; 82771fa900SAdrien Mazarguil unsigned int dev_port_prev = ~0u; 83771fa900SAdrien Mazarguil char match[IF_NAMESIZE] = ""; 84771fa900SAdrien Mazarguil 85771fa900SAdrien Mazarguil { 86771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net", priv->ctx->device->ibdev_path); 87771fa900SAdrien Mazarguil 88771fa900SAdrien Mazarguil dir = opendir(path); 89771fa900SAdrien Mazarguil if (dir == NULL) 90771fa900SAdrien Mazarguil return -1; 91771fa900SAdrien Mazarguil } 92771fa900SAdrien Mazarguil while ((dent = readdir(dir)) != NULL) { 93771fa900SAdrien Mazarguil char *name = dent->d_name; 94771fa900SAdrien Mazarguil FILE *file; 95771fa900SAdrien Mazarguil unsigned int dev_port; 96771fa900SAdrien Mazarguil int r; 97771fa900SAdrien Mazarguil 98771fa900SAdrien Mazarguil if ((name[0] == '.') && 99771fa900SAdrien Mazarguil ((name[1] == '\0') || 100771fa900SAdrien Mazarguil ((name[1] == '.') && (name[2] == '\0')))) 101771fa900SAdrien Mazarguil continue; 102771fa900SAdrien Mazarguil 103771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", 104771fa900SAdrien Mazarguil priv->ctx->device->ibdev_path, name, 105771fa900SAdrien Mazarguil (dev_type ? "dev_id" : "dev_port")); 106771fa900SAdrien Mazarguil 107771fa900SAdrien Mazarguil file = fopen(path, "rb"); 108771fa900SAdrien Mazarguil if (file == NULL) { 109771fa900SAdrien Mazarguil if (errno != ENOENT) 110771fa900SAdrien Mazarguil continue; 111771fa900SAdrien Mazarguil /* 112771fa900SAdrien Mazarguil * Switch to dev_id when dev_port does not exist as 113771fa900SAdrien Mazarguil * is the case with Linux kernel versions < 3.15. 114771fa900SAdrien Mazarguil */ 115771fa900SAdrien Mazarguil try_dev_id: 116771fa900SAdrien Mazarguil match[0] = '\0'; 117771fa900SAdrien Mazarguil if (dev_type) 118771fa900SAdrien Mazarguil break; 119771fa900SAdrien Mazarguil dev_type = 1; 120771fa900SAdrien Mazarguil dev_port_prev = ~0u; 121771fa900SAdrien Mazarguil rewinddir(dir); 122771fa900SAdrien Mazarguil continue; 123771fa900SAdrien Mazarguil } 124771fa900SAdrien Mazarguil r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 125771fa900SAdrien Mazarguil fclose(file); 126771fa900SAdrien Mazarguil if (r != 1) 127771fa900SAdrien Mazarguil continue; 128771fa900SAdrien Mazarguil /* 129771fa900SAdrien Mazarguil * Switch to dev_id when dev_port returns the same value for 130771fa900SAdrien Mazarguil * all ports. May happen when using a MOFED release older than 131771fa900SAdrien Mazarguil * 3.0 with a Linux kernel >= 3.15. 132771fa900SAdrien Mazarguil */ 133771fa900SAdrien Mazarguil if (dev_port == dev_port_prev) 134771fa900SAdrien Mazarguil goto try_dev_id; 135771fa900SAdrien Mazarguil dev_port_prev = dev_port; 136771fa900SAdrien Mazarguil if (dev_port == (priv->port - 1u)) 137771fa900SAdrien Mazarguil snprintf(match, sizeof(match), "%s", name); 138771fa900SAdrien Mazarguil } 139771fa900SAdrien Mazarguil closedir(dir); 140771fa900SAdrien Mazarguil if (match[0] == '\0') 141771fa900SAdrien Mazarguil return -1; 142771fa900SAdrien Mazarguil strncpy(*ifname, match, sizeof(*ifname)); 143771fa900SAdrien Mazarguil return 0; 144771fa900SAdrien Mazarguil } 145771fa900SAdrien Mazarguil 146771fa900SAdrien Mazarguil /** 147771fa900SAdrien Mazarguil * Read from sysfs entry. 148771fa900SAdrien Mazarguil * 149771fa900SAdrien Mazarguil * @param[in] priv 150771fa900SAdrien Mazarguil * Pointer to private structure. 151771fa900SAdrien Mazarguil * @param[in] entry 152771fa900SAdrien Mazarguil * Entry name relative to sysfs path. 153771fa900SAdrien Mazarguil * @param[out] buf 154771fa900SAdrien Mazarguil * Data output buffer. 155771fa900SAdrien Mazarguil * @param size 156771fa900SAdrien Mazarguil * Buffer size. 157771fa900SAdrien Mazarguil * 158771fa900SAdrien Mazarguil * @return 159771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 160771fa900SAdrien Mazarguil */ 161771fa900SAdrien Mazarguil static int 162771fa900SAdrien Mazarguil priv_sysfs_read(const struct priv *priv, const char *entry, 163771fa900SAdrien Mazarguil char *buf, size_t size) 164771fa900SAdrien Mazarguil { 165771fa900SAdrien Mazarguil char ifname[IF_NAMESIZE]; 166771fa900SAdrien Mazarguil FILE *file; 167771fa900SAdrien Mazarguil int ret; 168771fa900SAdrien Mazarguil int err; 169771fa900SAdrien Mazarguil 170771fa900SAdrien Mazarguil if (priv_get_ifname(priv, &ifname)) 171771fa900SAdrien Mazarguil return -1; 172771fa900SAdrien Mazarguil 173771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path, 174771fa900SAdrien Mazarguil ifname, entry); 175771fa900SAdrien Mazarguil 176771fa900SAdrien Mazarguil file = fopen(path, "rb"); 177771fa900SAdrien Mazarguil if (file == NULL) 178771fa900SAdrien Mazarguil return -1; 179771fa900SAdrien Mazarguil ret = fread(buf, 1, size, file); 180771fa900SAdrien Mazarguil err = errno; 181771fa900SAdrien Mazarguil if (((size_t)ret < size) && (ferror(file))) 182771fa900SAdrien Mazarguil ret = -1; 183771fa900SAdrien Mazarguil else 184771fa900SAdrien Mazarguil ret = size; 185771fa900SAdrien Mazarguil fclose(file); 186771fa900SAdrien Mazarguil errno = err; 187771fa900SAdrien Mazarguil return ret; 188771fa900SAdrien Mazarguil } 189771fa900SAdrien Mazarguil 190771fa900SAdrien Mazarguil /** 191771fa900SAdrien Mazarguil * Write to sysfs entry. 192771fa900SAdrien Mazarguil * 193771fa900SAdrien Mazarguil * @param[in] priv 194771fa900SAdrien Mazarguil * Pointer to private structure. 195771fa900SAdrien Mazarguil * @param[in] entry 196771fa900SAdrien Mazarguil * Entry name relative to sysfs path. 197771fa900SAdrien Mazarguil * @param[in] buf 198771fa900SAdrien Mazarguil * Data buffer. 199771fa900SAdrien Mazarguil * @param size 200771fa900SAdrien Mazarguil * Buffer size. 201771fa900SAdrien Mazarguil * 202771fa900SAdrien Mazarguil * @return 203771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 204771fa900SAdrien Mazarguil */ 205771fa900SAdrien Mazarguil static int 206771fa900SAdrien Mazarguil priv_sysfs_write(const struct priv *priv, const char *entry, 207771fa900SAdrien Mazarguil char *buf, size_t size) 208771fa900SAdrien Mazarguil { 209771fa900SAdrien Mazarguil char ifname[IF_NAMESIZE]; 210771fa900SAdrien Mazarguil FILE *file; 211771fa900SAdrien Mazarguil int ret; 212771fa900SAdrien Mazarguil int err; 213771fa900SAdrien Mazarguil 214771fa900SAdrien Mazarguil if (priv_get_ifname(priv, &ifname)) 215771fa900SAdrien Mazarguil return -1; 216771fa900SAdrien Mazarguil 217771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path, 218771fa900SAdrien Mazarguil ifname, entry); 219771fa900SAdrien Mazarguil 220771fa900SAdrien Mazarguil file = fopen(path, "wb"); 221771fa900SAdrien Mazarguil if (file == NULL) 222771fa900SAdrien Mazarguil return -1; 223771fa900SAdrien Mazarguil ret = fwrite(buf, 1, size, file); 224771fa900SAdrien Mazarguil err = errno; 225771fa900SAdrien Mazarguil if (((size_t)ret < size) || (ferror(file))) 226771fa900SAdrien Mazarguil ret = -1; 227771fa900SAdrien Mazarguil else 228771fa900SAdrien Mazarguil ret = size; 229771fa900SAdrien Mazarguil fclose(file); 230771fa900SAdrien Mazarguil errno = err; 231771fa900SAdrien Mazarguil return ret; 232771fa900SAdrien Mazarguil } 233771fa900SAdrien Mazarguil 234771fa900SAdrien Mazarguil /** 235771fa900SAdrien Mazarguil * Get unsigned long sysfs property. 236771fa900SAdrien Mazarguil * 237771fa900SAdrien Mazarguil * @param priv 238771fa900SAdrien Mazarguil * Pointer to private structure. 239771fa900SAdrien Mazarguil * @param[in] name 240771fa900SAdrien Mazarguil * Entry name relative to sysfs path. 241771fa900SAdrien Mazarguil * @param[out] value 242771fa900SAdrien Mazarguil * Value output buffer. 243771fa900SAdrien Mazarguil * 244771fa900SAdrien Mazarguil * @return 245771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 246771fa900SAdrien Mazarguil */ 247771fa900SAdrien Mazarguil static int 248771fa900SAdrien Mazarguil priv_get_sysfs_ulong(struct priv *priv, const char *name, unsigned long *value) 249771fa900SAdrien Mazarguil { 250771fa900SAdrien Mazarguil int ret; 251771fa900SAdrien Mazarguil unsigned long value_ret; 252771fa900SAdrien Mazarguil char value_str[32]; 253771fa900SAdrien Mazarguil 254771fa900SAdrien Mazarguil ret = priv_sysfs_read(priv, name, value_str, (sizeof(value_str) - 1)); 255771fa900SAdrien Mazarguil if (ret == -1) { 256771fa900SAdrien Mazarguil DEBUG("cannot read %s value from sysfs: %s", 257771fa900SAdrien Mazarguil name, strerror(errno)); 258771fa900SAdrien Mazarguil return -1; 259771fa900SAdrien Mazarguil } 260771fa900SAdrien Mazarguil value_str[ret] = '\0'; 261771fa900SAdrien Mazarguil errno = 0; 262771fa900SAdrien Mazarguil value_ret = strtoul(value_str, NULL, 0); 263771fa900SAdrien Mazarguil if (errno) { 264771fa900SAdrien Mazarguil DEBUG("invalid %s value `%s': %s", name, value_str, 265771fa900SAdrien Mazarguil strerror(errno)); 266771fa900SAdrien Mazarguil return -1; 267771fa900SAdrien Mazarguil } 268771fa900SAdrien Mazarguil *value = value_ret; 269771fa900SAdrien Mazarguil return 0; 270771fa900SAdrien Mazarguil } 271771fa900SAdrien Mazarguil 272771fa900SAdrien Mazarguil /** 273771fa900SAdrien Mazarguil * Set unsigned long sysfs property. 274771fa900SAdrien Mazarguil * 275771fa900SAdrien Mazarguil * @param priv 276771fa900SAdrien Mazarguil * Pointer to private structure. 277771fa900SAdrien Mazarguil * @param[in] name 278771fa900SAdrien Mazarguil * Entry name relative to sysfs path. 279771fa900SAdrien Mazarguil * @param value 280771fa900SAdrien Mazarguil * Value to set. 281771fa900SAdrien Mazarguil * 282771fa900SAdrien Mazarguil * @return 283771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 284771fa900SAdrien Mazarguil */ 285771fa900SAdrien Mazarguil static int 286771fa900SAdrien Mazarguil priv_set_sysfs_ulong(struct priv *priv, const char *name, unsigned long value) 287771fa900SAdrien Mazarguil { 288771fa900SAdrien Mazarguil int ret; 289771fa900SAdrien Mazarguil MKSTR(value_str, "%lu", value); 290771fa900SAdrien Mazarguil 291771fa900SAdrien Mazarguil ret = priv_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1)); 292771fa900SAdrien Mazarguil if (ret == -1) { 293771fa900SAdrien Mazarguil DEBUG("cannot write %s `%s' (%lu) to sysfs: %s", 294771fa900SAdrien Mazarguil name, value_str, value, strerror(errno)); 295771fa900SAdrien Mazarguil return -1; 296771fa900SAdrien Mazarguil } 297771fa900SAdrien Mazarguil return 0; 298771fa900SAdrien Mazarguil } 299771fa900SAdrien Mazarguil 300771fa900SAdrien Mazarguil /** 301771fa900SAdrien Mazarguil * Perform ifreq ioctl() on associated Ethernet device. 302771fa900SAdrien Mazarguil * 303771fa900SAdrien Mazarguil * @param[in] priv 304771fa900SAdrien Mazarguil * Pointer to private structure. 305771fa900SAdrien Mazarguil * @param req 306771fa900SAdrien Mazarguil * Request number to pass to ioctl(). 307771fa900SAdrien Mazarguil * @param[out] ifr 308771fa900SAdrien Mazarguil * Interface request structure output buffer. 309771fa900SAdrien Mazarguil * 310771fa900SAdrien Mazarguil * @return 311771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 312771fa900SAdrien Mazarguil */ 313771fa900SAdrien Mazarguil int 314771fa900SAdrien Mazarguil priv_ifreq(const struct priv *priv, int req, struct ifreq *ifr) 315771fa900SAdrien Mazarguil { 316771fa900SAdrien Mazarguil int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 317771fa900SAdrien Mazarguil int ret = -1; 318771fa900SAdrien Mazarguil 319771fa900SAdrien Mazarguil if (sock == -1) 320771fa900SAdrien Mazarguil return ret; 321771fa900SAdrien Mazarguil if (priv_get_ifname(priv, &ifr->ifr_name) == 0) 322771fa900SAdrien Mazarguil ret = ioctl(sock, req, ifr); 323771fa900SAdrien Mazarguil close(sock); 324771fa900SAdrien Mazarguil return ret; 325771fa900SAdrien Mazarguil } 326771fa900SAdrien Mazarguil 327771fa900SAdrien Mazarguil /** 328771fa900SAdrien Mazarguil * Get device MTU. 329771fa900SAdrien Mazarguil * 330771fa900SAdrien Mazarguil * @param priv 331771fa900SAdrien Mazarguil * Pointer to private structure. 332771fa900SAdrien Mazarguil * @param[out] mtu 333771fa900SAdrien Mazarguil * MTU value output buffer. 334771fa900SAdrien Mazarguil * 335771fa900SAdrien Mazarguil * @return 336771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 337771fa900SAdrien Mazarguil */ 338771fa900SAdrien Mazarguil int 339771fa900SAdrien Mazarguil priv_get_mtu(struct priv *priv, uint16_t *mtu) 340771fa900SAdrien Mazarguil { 341771fa900SAdrien Mazarguil unsigned long ulong_mtu; 342771fa900SAdrien Mazarguil 343771fa900SAdrien Mazarguil if (priv_get_sysfs_ulong(priv, "mtu", &ulong_mtu) == -1) 344771fa900SAdrien Mazarguil return -1; 345771fa900SAdrien Mazarguil *mtu = ulong_mtu; 346771fa900SAdrien Mazarguil return 0; 347771fa900SAdrien Mazarguil } 348771fa900SAdrien Mazarguil 349771fa900SAdrien Mazarguil /** 350771fa900SAdrien Mazarguil * Set device flags. 351771fa900SAdrien Mazarguil * 352771fa900SAdrien Mazarguil * @param priv 353771fa900SAdrien Mazarguil * Pointer to private structure. 354771fa900SAdrien Mazarguil * @param keep 355771fa900SAdrien Mazarguil * Bitmask for flags that must remain untouched. 356771fa900SAdrien Mazarguil * @param flags 357771fa900SAdrien Mazarguil * Bitmask for flags to modify. 358771fa900SAdrien Mazarguil * 359771fa900SAdrien Mazarguil * @return 360771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 361771fa900SAdrien Mazarguil */ 362771fa900SAdrien Mazarguil int 363771fa900SAdrien Mazarguil priv_set_flags(struct priv *priv, unsigned int keep, unsigned int flags) 364771fa900SAdrien Mazarguil { 365771fa900SAdrien Mazarguil unsigned long tmp; 366771fa900SAdrien Mazarguil 367771fa900SAdrien Mazarguil if (priv_get_sysfs_ulong(priv, "flags", &tmp) == -1) 368771fa900SAdrien Mazarguil return -1; 369771fa900SAdrien Mazarguil tmp &= keep; 370771fa900SAdrien Mazarguil tmp |= flags; 371771fa900SAdrien Mazarguil return priv_set_sysfs_ulong(priv, "flags", tmp); 372771fa900SAdrien Mazarguil } 373771fa900SAdrien Mazarguil 374771fa900SAdrien Mazarguil /** 375*e60fbd5bSAdrien Mazarguil * Ethernet device configuration. 376*e60fbd5bSAdrien Mazarguil * 377*e60fbd5bSAdrien Mazarguil * Prepare the driver for a given number of TX and RX queues. 378*e60fbd5bSAdrien Mazarguil * Allocate parent RSS queue when several RX queues are requested. 379*e60fbd5bSAdrien Mazarguil * 380*e60fbd5bSAdrien Mazarguil * @param dev 381*e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 382*e60fbd5bSAdrien Mazarguil * 383*e60fbd5bSAdrien Mazarguil * @return 384*e60fbd5bSAdrien Mazarguil * 0 on success, errno value on failure. 385*e60fbd5bSAdrien Mazarguil */ 386*e60fbd5bSAdrien Mazarguil static int 387*e60fbd5bSAdrien Mazarguil dev_configure(struct rte_eth_dev *dev) 388*e60fbd5bSAdrien Mazarguil { 389*e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 390*e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 391*e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 392*e60fbd5bSAdrien Mazarguil unsigned int tmp; 393*e60fbd5bSAdrien Mazarguil int ret; 394*e60fbd5bSAdrien Mazarguil 395*e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 396*e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 397*e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 398*e60fbd5bSAdrien Mazarguil INFO("%p: TX queues number update: %u -> %u", 399*e60fbd5bSAdrien Mazarguil (void *)dev, priv->txqs_n, txqs_n); 400*e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 401*e60fbd5bSAdrien Mazarguil } 402*e60fbd5bSAdrien Mazarguil if (rxqs_n == priv->rxqs_n) 403*e60fbd5bSAdrien Mazarguil return 0; 404*e60fbd5bSAdrien Mazarguil INFO("%p: RX queues number update: %u -> %u", 405*e60fbd5bSAdrien Mazarguil (void *)dev, priv->rxqs_n, rxqs_n); 406*e60fbd5bSAdrien Mazarguil /* If RSS is enabled, disable it first. */ 407*e60fbd5bSAdrien Mazarguil if (priv->rss) { 408*e60fbd5bSAdrien Mazarguil unsigned int i; 409*e60fbd5bSAdrien Mazarguil 410*e60fbd5bSAdrien Mazarguil /* Only if there are no remaining child RX queues. */ 411*e60fbd5bSAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) 412*e60fbd5bSAdrien Mazarguil if ((*priv->rxqs)[i] != NULL) 413*e60fbd5bSAdrien Mazarguil return EINVAL; 414*e60fbd5bSAdrien Mazarguil rxq_cleanup(&priv->rxq_parent); 415*e60fbd5bSAdrien Mazarguil priv->rss = 0; 416*e60fbd5bSAdrien Mazarguil priv->rxqs_n = 0; 417*e60fbd5bSAdrien Mazarguil } 418*e60fbd5bSAdrien Mazarguil if (rxqs_n <= 1) { 419*e60fbd5bSAdrien Mazarguil /* Nothing else to do. */ 420*e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 421*e60fbd5bSAdrien Mazarguil return 0; 422*e60fbd5bSAdrien Mazarguil } 423*e60fbd5bSAdrien Mazarguil /* Allocate a new RSS parent queue if supported by hardware. */ 424*e60fbd5bSAdrien Mazarguil if (!priv->hw_rss) { 425*e60fbd5bSAdrien Mazarguil ERROR("%p: only a single RX queue can be configured when" 426*e60fbd5bSAdrien Mazarguil " hardware doesn't support RSS", 427*e60fbd5bSAdrien Mazarguil (void *)dev); 428*e60fbd5bSAdrien Mazarguil return EINVAL; 429*e60fbd5bSAdrien Mazarguil } 430*e60fbd5bSAdrien Mazarguil /* Fail if hardware doesn't support that many RSS queues. */ 431*e60fbd5bSAdrien Mazarguil if (rxqs_n >= priv->max_rss_tbl_sz) { 432*e60fbd5bSAdrien Mazarguil ERROR("%p: only %u RX queues can be configured for RSS", 433*e60fbd5bSAdrien Mazarguil (void *)dev, priv->max_rss_tbl_sz); 434*e60fbd5bSAdrien Mazarguil return EINVAL; 435*e60fbd5bSAdrien Mazarguil } 436*e60fbd5bSAdrien Mazarguil priv->rss = 1; 437*e60fbd5bSAdrien Mazarguil tmp = priv->rxqs_n; 438*e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 439*e60fbd5bSAdrien Mazarguil ret = rxq_setup(dev, &priv->rxq_parent, 0, 0, NULL, NULL); 440*e60fbd5bSAdrien Mazarguil if (!ret) 441*e60fbd5bSAdrien Mazarguil return 0; 442*e60fbd5bSAdrien Mazarguil /* Failure, rollback. */ 443*e60fbd5bSAdrien Mazarguil priv->rss = 0; 444*e60fbd5bSAdrien Mazarguil priv->rxqs_n = tmp; 445*e60fbd5bSAdrien Mazarguil assert(ret > 0); 446*e60fbd5bSAdrien Mazarguil return ret; 447*e60fbd5bSAdrien Mazarguil } 448*e60fbd5bSAdrien Mazarguil 449*e60fbd5bSAdrien Mazarguil /** 450*e60fbd5bSAdrien Mazarguil * DPDK callback for Ethernet device configuration. 451*e60fbd5bSAdrien Mazarguil * 452*e60fbd5bSAdrien Mazarguil * @param dev 453*e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 454*e60fbd5bSAdrien Mazarguil * 455*e60fbd5bSAdrien Mazarguil * @return 456*e60fbd5bSAdrien Mazarguil * 0 on success, negative errno value on failure. 457*e60fbd5bSAdrien Mazarguil */ 458*e60fbd5bSAdrien Mazarguil int 459*e60fbd5bSAdrien Mazarguil mlx5_dev_configure(struct rte_eth_dev *dev) 460*e60fbd5bSAdrien Mazarguil { 461*e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 462*e60fbd5bSAdrien Mazarguil int ret; 463*e60fbd5bSAdrien Mazarguil 464*e60fbd5bSAdrien Mazarguil priv_lock(priv); 465*e60fbd5bSAdrien Mazarguil ret = dev_configure(dev); 466*e60fbd5bSAdrien Mazarguil assert(ret >= 0); 467*e60fbd5bSAdrien Mazarguil priv_unlock(priv); 468*e60fbd5bSAdrien Mazarguil return -ret; 469*e60fbd5bSAdrien Mazarguil } 470*e60fbd5bSAdrien Mazarguil 471*e60fbd5bSAdrien Mazarguil /** 472*e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 473*e60fbd5bSAdrien Mazarguil * 474*e60fbd5bSAdrien Mazarguil * @param dev 475*e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 476*e60fbd5bSAdrien Mazarguil * @param[out] info 477*e60fbd5bSAdrien Mazarguil * Info structure output buffer. 478*e60fbd5bSAdrien Mazarguil */ 479*e60fbd5bSAdrien Mazarguil void 480*e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 481*e60fbd5bSAdrien Mazarguil { 482*e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 483*e60fbd5bSAdrien Mazarguil unsigned int max; 484*e60fbd5bSAdrien Mazarguil char ifname[IF_NAMESIZE]; 485*e60fbd5bSAdrien Mazarguil 486*e60fbd5bSAdrien Mazarguil priv_lock(priv); 487*e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 488*e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 489*e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 490*e60fbd5bSAdrien Mazarguil /* 491*e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 492*e60fbd5bSAdrien Mazarguil * between the two values. 493*e60fbd5bSAdrien Mazarguil */ 494*e60fbd5bSAdrien Mazarguil max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ? 495*e60fbd5bSAdrien Mazarguil priv->device_attr.max_qp : priv->device_attr.max_cq); 496*e60fbd5bSAdrien Mazarguil /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 497*e60fbd5bSAdrien Mazarguil if (max >= 65535) 498*e60fbd5bSAdrien Mazarguil max = 65535; 499*e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 500*e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 501*e60fbd5bSAdrien Mazarguil /* Last array entry is reserved for broadcast. */ 502*e60fbd5bSAdrien Mazarguil info->max_mac_addrs = (RTE_DIM(priv->mac) - 1); 503*e60fbd5bSAdrien Mazarguil info->rx_offload_capa = 504*e60fbd5bSAdrien Mazarguil (priv->hw_csum ? 505*e60fbd5bSAdrien Mazarguil (DEV_RX_OFFLOAD_IPV4_CKSUM | 506*e60fbd5bSAdrien Mazarguil DEV_RX_OFFLOAD_UDP_CKSUM | 507*e60fbd5bSAdrien Mazarguil DEV_RX_OFFLOAD_TCP_CKSUM) : 508*e60fbd5bSAdrien Mazarguil 0); 509*e60fbd5bSAdrien Mazarguil info->tx_offload_capa = 510*e60fbd5bSAdrien Mazarguil (priv->hw_csum ? 511*e60fbd5bSAdrien Mazarguil (DEV_TX_OFFLOAD_IPV4_CKSUM | 512*e60fbd5bSAdrien Mazarguil DEV_TX_OFFLOAD_UDP_CKSUM | 513*e60fbd5bSAdrien Mazarguil DEV_TX_OFFLOAD_TCP_CKSUM) : 514*e60fbd5bSAdrien Mazarguil 0); 515*e60fbd5bSAdrien Mazarguil if (priv_get_ifname(priv, &ifname) == 0) 516*e60fbd5bSAdrien Mazarguil info->if_index = if_nametoindex(ifname); 517*e60fbd5bSAdrien Mazarguil priv_unlock(priv); 518*e60fbd5bSAdrien Mazarguil } 519*e60fbd5bSAdrien Mazarguil 520*e60fbd5bSAdrien Mazarguil /** 521771fa900SAdrien Mazarguil * Get PCI information from struct ibv_device. 522771fa900SAdrien Mazarguil * 523771fa900SAdrien Mazarguil * @param device 524771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 525771fa900SAdrien Mazarguil * @param[out] pci_addr 526771fa900SAdrien Mazarguil * PCI bus address output buffer. 527771fa900SAdrien Mazarguil * 528771fa900SAdrien Mazarguil * @return 529771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 530771fa900SAdrien Mazarguil */ 531771fa900SAdrien Mazarguil int 532771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device, 533771fa900SAdrien Mazarguil struct rte_pci_addr *pci_addr) 534771fa900SAdrien Mazarguil { 535771fa900SAdrien Mazarguil FILE *file; 536771fa900SAdrien Mazarguil char line[32]; 537771fa900SAdrien Mazarguil MKSTR(path, "%s/device/uevent", device->ibdev_path); 538771fa900SAdrien Mazarguil 539771fa900SAdrien Mazarguil file = fopen(path, "rb"); 540771fa900SAdrien Mazarguil if (file == NULL) 541771fa900SAdrien Mazarguil return -1; 542771fa900SAdrien Mazarguil while (fgets(line, sizeof(line), file) == line) { 543771fa900SAdrien Mazarguil size_t len = strlen(line); 544771fa900SAdrien Mazarguil int ret; 545771fa900SAdrien Mazarguil 546771fa900SAdrien Mazarguil /* Truncate long lines. */ 547771fa900SAdrien Mazarguil if (len == (sizeof(line) - 1)) 548771fa900SAdrien Mazarguil while (line[(len - 1)] != '\n') { 549771fa900SAdrien Mazarguil ret = fgetc(file); 550771fa900SAdrien Mazarguil if (ret == EOF) 551771fa900SAdrien Mazarguil break; 552771fa900SAdrien Mazarguil line[(len - 1)] = ret; 553771fa900SAdrien Mazarguil } 554771fa900SAdrien Mazarguil /* Extract information. */ 555771fa900SAdrien Mazarguil if (sscanf(line, 556771fa900SAdrien Mazarguil "PCI_SLOT_NAME=" 557771fa900SAdrien Mazarguil "%" SCNx16 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", 558771fa900SAdrien Mazarguil &pci_addr->domain, 559771fa900SAdrien Mazarguil &pci_addr->bus, 560771fa900SAdrien Mazarguil &pci_addr->devid, 561771fa900SAdrien Mazarguil &pci_addr->function) == 4) { 562771fa900SAdrien Mazarguil ret = 0; 563771fa900SAdrien Mazarguil break; 564771fa900SAdrien Mazarguil } 565771fa900SAdrien Mazarguil } 566771fa900SAdrien Mazarguil fclose(file); 567771fa900SAdrien Mazarguil return 0; 568771fa900SAdrien Mazarguil } 569