1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2017 6WIND S.A. 3 * Copyright 2017 Mellanox Technologies, Ltd 4 */ 5 6 /** 7 * @file 8 * Miscellaneous control operations for mlx4 driver. 9 */ 10 11 #include <assert.h> 12 #include <dirent.h> 13 #include <errno.h> 14 #include <linux/ethtool.h> 15 #include <linux/sockios.h> 16 #include <net/if.h> 17 #include <netinet/ip.h> 18 #include <stddef.h> 19 #include <stdint.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <sys/ioctl.h> 24 #include <sys/socket.h> 25 #include <unistd.h> 26 27 /* Verbs headers do not support -pedantic. */ 28 #ifdef PEDANTIC 29 #pragma GCC diagnostic ignored "-Wpedantic" 30 #endif 31 #include <infiniband/verbs.h> 32 #ifdef PEDANTIC 33 #pragma GCC diagnostic error "-Wpedantic" 34 #endif 35 36 #include <rte_bus_pci.h> 37 #include <rte_errno.h> 38 #include <rte_ethdev_driver.h> 39 #include <rte_ether.h> 40 #include <rte_flow.h> 41 #include <rte_pci.h> 42 #include <rte_string_fns.h> 43 44 #include "mlx4.h" 45 #include "mlx4_flow.h" 46 #include "mlx4_glue.h" 47 #include "mlx4_rxtx.h" 48 #include "mlx4_utils.h" 49 50 /** 51 * Get interface name from private structure. 52 * 53 * @param[in] priv 54 * Pointer to private structure. 55 * @param[out] ifname 56 * Interface name output buffer. 57 * 58 * @return 59 * 0 on success, negative errno value otherwise and rte_errno is set. 60 */ 61 int 62 mlx4_get_ifname(const struct mlx4_priv *priv, char (*ifname)[IF_NAMESIZE]) 63 { 64 DIR *dir; 65 struct dirent *dent; 66 unsigned int dev_type = 0; 67 unsigned int dev_port_prev = ~0u; 68 char match[IF_NAMESIZE] = ""; 69 70 { 71 MKSTR(path, "%s/device/net", priv->ctx->device->ibdev_path); 72 73 dir = opendir(path); 74 if (dir == NULL) { 75 rte_errno = errno; 76 return -rte_errno; 77 } 78 } 79 while ((dent = readdir(dir)) != NULL) { 80 char *name = dent->d_name; 81 FILE *file; 82 unsigned int dev_port; 83 int r; 84 85 if ((name[0] == '.') && 86 ((name[1] == '\0') || 87 ((name[1] == '.') && (name[2] == '\0')))) 88 continue; 89 90 MKSTR(path, "%s/device/net/%s/%s", 91 priv->ctx->device->ibdev_path, name, 92 (dev_type ? "dev_id" : "dev_port")); 93 94 file = fopen(path, "rb"); 95 if (file == NULL) { 96 if (errno != ENOENT) 97 continue; 98 /* 99 * Switch to dev_id when dev_port does not exist as 100 * is the case with Linux kernel versions < 3.15. 101 */ 102 try_dev_id: 103 match[0] = '\0'; 104 if (dev_type) 105 break; 106 dev_type = 1; 107 dev_port_prev = ~0u; 108 rewinddir(dir); 109 continue; 110 } 111 r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 112 fclose(file); 113 if (r != 1) 114 continue; 115 /* 116 * Switch to dev_id when dev_port returns the same value for 117 * all ports. May happen when using a MOFED release older than 118 * 3.0 with a Linux kernel >= 3.15. 119 */ 120 if (dev_port == dev_port_prev) 121 goto try_dev_id; 122 dev_port_prev = dev_port; 123 if (dev_port == (priv->port - 1u)) 124 strlcpy(match, name, sizeof(match)); 125 } 126 closedir(dir); 127 if (match[0] == '\0') { 128 rte_errno = ENODEV; 129 return -rte_errno; 130 } 131 strncpy(*ifname, match, sizeof(*ifname)); 132 return 0; 133 } 134 135 /** 136 * Perform ifreq ioctl() on associated Ethernet device. 137 * 138 * @param[in] priv 139 * Pointer to private structure. 140 * @param req 141 * Request number to pass to ioctl(). 142 * @param[out] ifr 143 * Interface request structure output buffer. 144 * 145 * @return 146 * 0 on success, negative errno value otherwise and rte_errno is set. 147 */ 148 static int 149 mlx4_ifreq(const struct mlx4_priv *priv, int req, struct ifreq *ifr) 150 { 151 int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 152 int ret; 153 154 if (sock == -1) { 155 rte_errno = errno; 156 return -rte_errno; 157 } 158 ret = mlx4_get_ifname(priv, &ifr->ifr_name); 159 if (!ret && ioctl(sock, req, ifr) == -1) { 160 rte_errno = errno; 161 ret = -rte_errno; 162 } 163 close(sock); 164 return ret; 165 } 166 167 /** 168 * Get MAC address by querying netdevice. 169 * 170 * @param[in] priv 171 * Pointer to private structure. 172 * @param[out] mac 173 * MAC address output buffer. 174 * 175 * @return 176 * 0 on success, negative errno value otherwise and rte_errno is set. 177 */ 178 int 179 mlx4_get_mac(struct mlx4_priv *priv, uint8_t (*mac)[RTE_ETHER_ADDR_LEN]) 180 { 181 struct ifreq request; 182 int ret = mlx4_ifreq(priv, SIOCGIFHWADDR, &request); 183 184 if (ret) 185 return ret; 186 memcpy(mac, request.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN); 187 return 0; 188 } 189 190 /** 191 * Get device MTU. 192 * 193 * @param priv 194 * Pointer to private structure. 195 * @param[out] mtu 196 * MTU value output buffer. 197 * 198 * @return 199 * 0 on success, negative errno value otherwise and rte_errno is set. 200 */ 201 int 202 mlx4_mtu_get(struct mlx4_priv *priv, uint16_t *mtu) 203 { 204 struct ifreq request; 205 int ret = mlx4_ifreq(priv, SIOCGIFMTU, &request); 206 207 if (ret) 208 return ret; 209 *mtu = request.ifr_mtu; 210 return 0; 211 } 212 213 /** 214 * DPDK callback to change the MTU. 215 * 216 * @param priv 217 * Pointer to Ethernet device structure. 218 * @param mtu 219 * MTU value to set. 220 * 221 * @return 222 * 0 on success, negative errno value otherwise and rte_errno is set. 223 */ 224 int 225 mlx4_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) 226 { 227 struct mlx4_priv *priv = dev->data->dev_private; 228 struct ifreq request = { .ifr_mtu = mtu, }; 229 int ret = mlx4_ifreq(priv, SIOCSIFMTU, &request); 230 231 if (ret) 232 return ret; 233 priv->mtu = mtu; 234 return 0; 235 } 236 237 /** 238 * Set device flags. 239 * 240 * @param priv 241 * Pointer to private structure. 242 * @param keep 243 * Bitmask for flags that must remain untouched. 244 * @param flags 245 * Bitmask for flags to modify. 246 * 247 * @return 248 * 0 on success, negative errno value otherwise and rte_errno is set. 249 */ 250 static int 251 mlx4_set_flags(struct mlx4_priv *priv, unsigned int keep, unsigned int flags) 252 { 253 struct ifreq request; 254 int ret = mlx4_ifreq(priv, SIOCGIFFLAGS, &request); 255 256 if (ret) 257 return ret; 258 request.ifr_flags &= keep; 259 request.ifr_flags |= flags & ~keep; 260 return mlx4_ifreq(priv, SIOCSIFFLAGS, &request); 261 } 262 263 /** 264 * Change the link state (UP / DOWN). 265 * 266 * @param priv 267 * Pointer to Ethernet device private data. 268 * @param up 269 * Nonzero for link up, otherwise link down. 270 * 271 * @return 272 * 0 on success, negative errno value otherwise and rte_errno is set. 273 */ 274 static int 275 mlx4_dev_set_link(struct mlx4_priv *priv, int up) 276 { 277 int err; 278 279 if (up) { 280 err = mlx4_set_flags(priv, ~IFF_UP, IFF_UP); 281 if (err) 282 return err; 283 } else { 284 err = mlx4_set_flags(priv, ~IFF_UP, ~IFF_UP); 285 if (err) 286 return err; 287 } 288 return 0; 289 } 290 291 /** 292 * DPDK callback to bring the link DOWN. 293 * 294 * @param dev 295 * Pointer to Ethernet device structure. 296 * 297 * @return 298 * 0 on success, negative errno value otherwise and rte_errno is set. 299 */ 300 int 301 mlx4_dev_set_link_down(struct rte_eth_dev *dev) 302 { 303 struct mlx4_priv *priv = dev->data->dev_private; 304 305 return mlx4_dev_set_link(priv, 0); 306 } 307 308 /** 309 * DPDK callback to bring the link UP. 310 * 311 * @param dev 312 * Pointer to Ethernet device structure. 313 * 314 * @return 315 * 0 on success, negative errno value otherwise and rte_errno is set. 316 */ 317 int 318 mlx4_dev_set_link_up(struct rte_eth_dev *dev) 319 { 320 struct mlx4_priv *priv = dev->data->dev_private; 321 322 return mlx4_dev_set_link(priv, 1); 323 } 324 325 /** 326 * Supported Rx mode toggles. 327 * 328 * Even and odd values respectively stand for off and on. 329 */ 330 enum rxmode_toggle { 331 RXMODE_TOGGLE_PROMISC_OFF, 332 RXMODE_TOGGLE_PROMISC_ON, 333 RXMODE_TOGGLE_ALLMULTI_OFF, 334 RXMODE_TOGGLE_ALLMULTI_ON, 335 }; 336 337 /** 338 * Helper function to toggle promiscuous and all multicast modes. 339 * 340 * @param dev 341 * Pointer to Ethernet device structure. 342 * @param toggle 343 * Toggle to set. 344 */ 345 static void 346 mlx4_rxmode_toggle(struct rte_eth_dev *dev, enum rxmode_toggle toggle) 347 { 348 struct mlx4_priv *priv = dev->data->dev_private; 349 const char *mode; 350 struct rte_flow_error error; 351 352 switch (toggle) { 353 case RXMODE_TOGGLE_PROMISC_OFF: 354 case RXMODE_TOGGLE_PROMISC_ON: 355 mode = "promiscuous"; 356 dev->data->promiscuous = toggle & 1; 357 break; 358 case RXMODE_TOGGLE_ALLMULTI_OFF: 359 case RXMODE_TOGGLE_ALLMULTI_ON: 360 mode = "all multicast"; 361 dev->data->all_multicast = toggle & 1; 362 break; 363 default: 364 mode = "undefined"; 365 } 366 if (!mlx4_flow_sync(priv, &error)) 367 return; 368 ERROR("cannot toggle %s mode (code %d, \"%s\")," 369 " flow error type %d, cause %p, message: %s", 370 mode, rte_errno, strerror(rte_errno), error.type, error.cause, 371 error.message ? error.message : "(unspecified)"); 372 } 373 374 /** 375 * DPDK callback to enable promiscuous mode. 376 * 377 * @param dev 378 * Pointer to Ethernet device structure. 379 */ 380 void 381 mlx4_promiscuous_enable(struct rte_eth_dev *dev) 382 { 383 mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_PROMISC_ON); 384 } 385 386 /** 387 * DPDK callback to disable promiscuous mode. 388 * 389 * @param dev 390 * Pointer to Ethernet device structure. 391 */ 392 void 393 mlx4_promiscuous_disable(struct rte_eth_dev *dev) 394 { 395 mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_PROMISC_OFF); 396 } 397 398 /** 399 * DPDK callback to enable all multicast mode. 400 * 401 * @param dev 402 * Pointer to Ethernet device structure. 403 */ 404 void 405 mlx4_allmulticast_enable(struct rte_eth_dev *dev) 406 { 407 mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_ALLMULTI_ON); 408 } 409 410 /** 411 * DPDK callback to disable all multicast mode. 412 * 413 * @param dev 414 * Pointer to Ethernet device structure. 415 */ 416 void 417 mlx4_allmulticast_disable(struct rte_eth_dev *dev) 418 { 419 mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_ALLMULTI_OFF); 420 } 421 422 /** 423 * DPDK callback to remove a MAC address. 424 * 425 * @param dev 426 * Pointer to Ethernet device structure. 427 * @param index 428 * MAC address index. 429 */ 430 void 431 mlx4_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 432 { 433 struct mlx4_priv *priv = dev->data->dev_private; 434 struct rte_flow_error error; 435 436 if (index >= RTE_DIM(priv->mac) - priv->mac_mc) { 437 rte_errno = EINVAL; 438 return; 439 } 440 memset(&priv->mac[index], 0, sizeof(priv->mac[index])); 441 if (!mlx4_flow_sync(priv, &error)) 442 return; 443 ERROR("failed to synchronize flow rules after removing MAC address" 444 " at index %d (code %d, \"%s\")," 445 " flow error type %d, cause %p, message: %s", 446 index, rte_errno, strerror(rte_errno), error.type, error.cause, 447 error.message ? error.message : "(unspecified)"); 448 } 449 450 /** 451 * DPDK callback to add a MAC address. 452 * 453 * @param dev 454 * Pointer to Ethernet device structure. 455 * @param mac_addr 456 * MAC address to register. 457 * @param index 458 * MAC address index. 459 * @param vmdq 460 * VMDq pool index to associate address with (ignored). 461 * 462 * @return 463 * 0 on success, negative errno value otherwise and rte_errno is set. 464 */ 465 int 466 mlx4_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, 467 uint32_t index, uint32_t vmdq) 468 { 469 struct mlx4_priv *priv = dev->data->dev_private; 470 struct rte_flow_error error; 471 int ret; 472 473 (void)vmdq; 474 if (index >= RTE_DIM(priv->mac) - priv->mac_mc) { 475 rte_errno = EINVAL; 476 return -rte_errno; 477 } 478 memcpy(&priv->mac[index], mac_addr, sizeof(priv->mac[index])); 479 ret = mlx4_flow_sync(priv, &error); 480 if (!ret) 481 return 0; 482 ERROR("failed to synchronize flow rules after adding MAC address" 483 " at index %d (code %d, \"%s\")," 484 " flow error type %d, cause %p, message: %s", 485 index, rte_errno, strerror(rte_errno), error.type, error.cause, 486 error.message ? error.message : "(unspecified)"); 487 return ret; 488 } 489 490 /** 491 * DPDK callback to configure multicast addresses. 492 * 493 * @param dev 494 * Pointer to Ethernet device structure. 495 * @param list 496 * List of MAC addresses to register. 497 * @param num 498 * Number of entries in list. 499 * 500 * @return 501 * 0 on success, negative errno value otherwise and rte_errno is set. 502 */ 503 int 504 mlx4_set_mc_addr_list(struct rte_eth_dev *dev, struct rte_ether_addr *list, 505 uint32_t num) 506 { 507 struct mlx4_priv *priv = dev->data->dev_private; 508 struct rte_flow_error error; 509 int ret; 510 511 if (num > RTE_DIM(priv->mac)) { 512 rte_errno = EINVAL; 513 return -rte_errno; 514 } 515 /* 516 * Make sure there is enough room to increase the number of 517 * multicast entries without overwriting standard entries. 518 */ 519 if (num > priv->mac_mc) { 520 unsigned int i; 521 522 for (i = RTE_DIM(priv->mac) - num; 523 i != RTE_DIM(priv->mac) - priv->mac_mc; 524 ++i) 525 if (!rte_is_zero_ether_addr(&priv->mac[i])) { 526 rte_errno = EBUSY; 527 return -rte_errno; 528 } 529 } else if (num < priv->mac_mc) { 530 /* Clear unused entries. */ 531 memset(priv->mac + RTE_DIM(priv->mac) - priv->mac_mc, 532 0, 533 sizeof(priv->mac[0]) * (priv->mac_mc - num)); 534 } 535 memcpy(priv->mac + RTE_DIM(priv->mac) - num, list, sizeof(*list) * num); 536 priv->mac_mc = num; 537 ret = mlx4_flow_sync(priv, &error); 538 if (!ret) 539 return 0; 540 ERROR("failed to synchronize flow rules after modifying MC list," 541 " (code %d, \"%s\"), flow error type %d, cause %p, message: %s", 542 rte_errno, strerror(rte_errno), error.type, error.cause, 543 error.message ? error.message : "(unspecified)"); 544 return ret; 545 } 546 547 /** 548 * DPDK callback to configure a VLAN filter. 549 * 550 * @param dev 551 * Pointer to Ethernet device structure. 552 * @param vlan_id 553 * VLAN ID to filter. 554 * @param on 555 * Toggle filter. 556 * 557 * @return 558 * 0 on success, negative errno value otherwise and rte_errno is set. 559 */ 560 int 561 mlx4_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) 562 { 563 struct mlx4_priv *priv = dev->data->dev_private; 564 struct rte_flow_error error; 565 unsigned int vidx = vlan_id / 64; 566 unsigned int vbit = vlan_id % 64; 567 uint64_t *v; 568 int ret; 569 570 if (vidx >= RTE_DIM(dev->data->vlan_filter_conf.ids)) { 571 rte_errno = EINVAL; 572 return -rte_errno; 573 } 574 v = &dev->data->vlan_filter_conf.ids[vidx]; 575 *v &= ~(UINT64_C(1) << vbit); 576 *v |= (uint64_t)!!on << vbit; 577 ret = mlx4_flow_sync(priv, &error); 578 if (!ret) 579 return 0; 580 ERROR("failed to synchronize flow rules after %s VLAN filter on ID %u" 581 " (code %d, \"%s\"), " 582 " flow error type %d, cause %p, message: %s", 583 on ? "enabling" : "disabling", vlan_id, 584 rte_errno, strerror(rte_errno), error.type, error.cause, 585 error.message ? error.message : "(unspecified)"); 586 return ret; 587 } 588 589 /** 590 * DPDK callback to set the primary MAC address. 591 * 592 * @param dev 593 * Pointer to Ethernet device structure. 594 * @param mac_addr 595 * MAC address to register. 596 * 597 * @return 598 * 0 on success, negative errno value otherwise and rte_errno is set. 599 */ 600 int 601 mlx4_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) 602 { 603 return mlx4_mac_addr_add(dev, mac_addr, 0, 0); 604 } 605 606 /** 607 * DPDK callback to get information about the device. 608 * 609 * @param dev 610 * Pointer to Ethernet device structure. 611 * @param[out] info 612 * Info structure output buffer. 613 */ 614 void 615 mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 616 { 617 struct mlx4_priv *priv = dev->data->dev_private; 618 unsigned int max; 619 char ifname[IF_NAMESIZE]; 620 621 /* FIXME: we should ask the device for these values. */ 622 info->min_rx_bufsize = 32; 623 info->max_rx_pktlen = 65536; 624 /* 625 * Since we need one CQ per QP, the limit is the minimum number 626 * between the two values. 627 */ 628 max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ? 629 priv->device_attr.max_qp : priv->device_attr.max_cq); 630 /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 631 if (max >= 65535) 632 max = 65535; 633 info->max_rx_queues = max; 634 info->max_tx_queues = max; 635 info->max_mac_addrs = RTE_DIM(priv->mac); 636 info->tx_offload_capa = mlx4_get_tx_port_offloads(priv); 637 info->rx_queue_offload_capa = mlx4_get_rx_queue_offloads(priv); 638 info->rx_offload_capa = (mlx4_get_rx_port_offloads(priv) | 639 info->rx_queue_offload_capa); 640 if (mlx4_get_ifname(priv, &ifname) == 0) 641 info->if_index = if_nametoindex(ifname); 642 info->hash_key_size = MLX4_RSS_HASH_KEY_SIZE; 643 info->speed_capa = 644 ETH_LINK_SPEED_1G | 645 ETH_LINK_SPEED_10G | 646 ETH_LINK_SPEED_20G | 647 ETH_LINK_SPEED_40G | 648 ETH_LINK_SPEED_56G; 649 info->flow_type_rss_offloads = mlx4_conv_rss_types(priv, 0, 1); 650 } 651 652 /** 653 * Get firmware version of a device. 654 * 655 * @param dev 656 * Ethernet device port. 657 * @param fw_ver 658 * String output allocated by caller. 659 * @param fw_size 660 * Size of the output string, including terminating null byte. 661 * 662 * @return 663 * 0 on success, or the size of the non truncated string if too big. 664 */ 665 int mlx4_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 666 { 667 struct mlx4_priv *priv = dev->data->dev_private; 668 struct ibv_device_attr *attr = &priv->device_attr; 669 size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 670 671 if (fw_size < size) 672 return size; 673 if (fw_ver != NULL) 674 strlcpy(fw_ver, attr->fw_ver, fw_size); 675 return 0; 676 } 677 678 /** 679 * DPDK callback to get device statistics. 680 * 681 * @param dev 682 * Pointer to Ethernet device structure. 683 * @param[out] stats 684 * Stats structure output buffer. 685 */ 686 int 687 mlx4_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 688 { 689 struct rte_eth_stats tmp; 690 unsigned int i; 691 unsigned int idx; 692 693 memset(&tmp, 0, sizeof(tmp)); 694 /* Add software counters. */ 695 for (i = 0; i != dev->data->nb_rx_queues; ++i) { 696 struct rxq *rxq = dev->data->rx_queues[i]; 697 698 if (rxq == NULL) 699 continue; 700 idx = rxq->stats.idx; 701 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { 702 tmp.q_ipackets[idx] += rxq->stats.ipackets; 703 tmp.q_ibytes[idx] += rxq->stats.ibytes; 704 tmp.q_errors[idx] += (rxq->stats.idropped + 705 rxq->stats.rx_nombuf); 706 } 707 tmp.ipackets += rxq->stats.ipackets; 708 tmp.ibytes += rxq->stats.ibytes; 709 tmp.ierrors += rxq->stats.idropped; 710 tmp.rx_nombuf += rxq->stats.rx_nombuf; 711 } 712 for (i = 0; i != dev->data->nb_tx_queues; ++i) { 713 struct txq *txq = dev->data->tx_queues[i]; 714 715 if (txq == NULL) 716 continue; 717 idx = txq->stats.idx; 718 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { 719 tmp.q_opackets[idx] += txq->stats.opackets; 720 tmp.q_obytes[idx] += txq->stats.obytes; 721 tmp.q_errors[idx] += txq->stats.odropped; 722 } 723 tmp.opackets += txq->stats.opackets; 724 tmp.obytes += txq->stats.obytes; 725 tmp.oerrors += txq->stats.odropped; 726 } 727 *stats = tmp; 728 return 0; 729 } 730 731 /** 732 * DPDK callback to clear device statistics. 733 * 734 * @param dev 735 * Pointer to Ethernet device structure. 736 */ 737 void 738 mlx4_stats_reset(struct rte_eth_dev *dev) 739 { 740 unsigned int i; 741 742 for (i = 0; i != dev->data->nb_rx_queues; ++i) { 743 struct rxq *rxq = dev->data->rx_queues[i]; 744 745 if (rxq) 746 rxq->stats = (struct mlx4_rxq_stats){ 747 .idx = rxq->stats.idx, 748 }; 749 } 750 for (i = 0; i != dev->data->nb_tx_queues; ++i) { 751 struct txq *txq = dev->data->tx_queues[i]; 752 753 if (txq) 754 txq->stats = (struct mlx4_txq_stats){ 755 .idx = txq->stats.idx, 756 }; 757 } 758 } 759 760 /** 761 * DPDK callback to retrieve physical link information. 762 * 763 * @param dev 764 * Pointer to Ethernet device structure. 765 * @param wait_to_complete 766 * Wait for request completion (ignored). 767 * 768 * @return 769 * 0 on success, negative errno value otherwise and rte_errno is set. 770 */ 771 int 772 mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete) 773 { 774 const struct mlx4_priv *priv = dev->data->dev_private; 775 struct ethtool_cmd edata = { 776 .cmd = ETHTOOL_GSET, 777 }; 778 struct ifreq ifr; 779 struct rte_eth_link dev_link; 780 int link_speed = 0; 781 782 if (priv == NULL) { 783 rte_errno = EINVAL; 784 return -rte_errno; 785 } 786 (void)wait_to_complete; 787 if (mlx4_ifreq(priv, SIOCGIFFLAGS, &ifr)) { 788 WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(rte_errno)); 789 return -rte_errno; 790 } 791 memset(&dev_link, 0, sizeof(dev_link)); 792 dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && 793 (ifr.ifr_flags & IFF_RUNNING)); 794 ifr.ifr_data = (void *)&edata; 795 if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) { 796 WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s", 797 strerror(rte_errno)); 798 return -rte_errno; 799 } 800 link_speed = ethtool_cmd_speed(&edata); 801 if (link_speed == -1) 802 dev_link.link_speed = ETH_SPEED_NUM_NONE; 803 else 804 dev_link.link_speed = link_speed; 805 dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 806 ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 807 dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 808 ETH_LINK_SPEED_FIXED); 809 dev->data->dev_link = dev_link; 810 return 0; 811 } 812 813 /** 814 * DPDK callback to get flow control status. 815 * 816 * @param dev 817 * Pointer to Ethernet device structure. 818 * @param[out] fc_conf 819 * Flow control output buffer. 820 * 821 * @return 822 * 0 on success, negative errno value otherwise and rte_errno is set. 823 */ 824 int 825 mlx4_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 826 { 827 struct mlx4_priv *priv = dev->data->dev_private; 828 struct ifreq ifr; 829 struct ethtool_pauseparam ethpause = { 830 .cmd = ETHTOOL_GPAUSEPARAM, 831 }; 832 int ret; 833 834 ifr.ifr_data = (void *)ðpause; 835 if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) { 836 ret = rte_errno; 837 WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM)" 838 " failed: %s", 839 strerror(rte_errno)); 840 goto out; 841 } 842 fc_conf->autoneg = ethpause.autoneg; 843 if (ethpause.rx_pause && ethpause.tx_pause) 844 fc_conf->mode = RTE_FC_FULL; 845 else if (ethpause.rx_pause) 846 fc_conf->mode = RTE_FC_RX_PAUSE; 847 else if (ethpause.tx_pause) 848 fc_conf->mode = RTE_FC_TX_PAUSE; 849 else 850 fc_conf->mode = RTE_FC_NONE; 851 ret = 0; 852 out: 853 assert(ret >= 0); 854 return -ret; 855 } 856 857 /** 858 * DPDK callback to modify flow control parameters. 859 * 860 * @param dev 861 * Pointer to Ethernet device structure. 862 * @param[in] fc_conf 863 * Flow control parameters. 864 * 865 * @return 866 * 0 on success, negative errno value otherwise and rte_errno is set. 867 */ 868 int 869 mlx4_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 870 { 871 struct mlx4_priv *priv = dev->data->dev_private; 872 struct ifreq ifr; 873 struct ethtool_pauseparam ethpause = { 874 .cmd = ETHTOOL_SPAUSEPARAM, 875 }; 876 int ret; 877 878 ifr.ifr_data = (void *)ðpause; 879 ethpause.autoneg = fc_conf->autoneg; 880 if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 881 (fc_conf->mode & RTE_FC_RX_PAUSE)) 882 ethpause.rx_pause = 1; 883 else 884 ethpause.rx_pause = 0; 885 if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 886 (fc_conf->mode & RTE_FC_TX_PAUSE)) 887 ethpause.tx_pause = 1; 888 else 889 ethpause.tx_pause = 0; 890 if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) { 891 ret = rte_errno; 892 WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 893 " failed: %s", 894 strerror(rte_errno)); 895 goto out; 896 } 897 ret = 0; 898 out: 899 assert(ret >= 0); 900 return -ret; 901 } 902 903 /** 904 * DPDK callback to retrieve the received packet types that are recognized 905 * by the device. 906 * 907 * @param dev 908 * Pointer to Ethernet device structure. 909 * 910 * @return 911 * Pointer to an array of recognized packet types if in Rx burst mode, 912 * NULL otherwise. 913 */ 914 const uint32_t * 915 mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev) 916 { 917 static const uint32_t ptypes[] = { 918 /* refers to rxq_cq_to_pkt_type() */ 919 RTE_PTYPE_L2_ETHER, 920 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 921 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 922 RTE_PTYPE_L4_FRAG, 923 RTE_PTYPE_L4_TCP, 924 RTE_PTYPE_L4_UDP, 925 RTE_PTYPE_UNKNOWN 926 }; 927 static const uint32_t ptypes_l2tun[] = { 928 /* refers to rxq_cq_to_pkt_type() */ 929 RTE_PTYPE_L2_ETHER, 930 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 931 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 932 RTE_PTYPE_L4_FRAG, 933 RTE_PTYPE_L4_TCP, 934 RTE_PTYPE_L4_UDP, 935 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 936 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 937 RTE_PTYPE_UNKNOWN 938 }; 939 struct mlx4_priv *priv = dev->data->dev_private; 940 941 if (dev->rx_pkt_burst == mlx4_rx_burst) { 942 if (priv->hw_csum_l2tun) 943 return ptypes_l2tun; 944 else 945 return ptypes; 946 } 947 return NULL; 948 } 949 950 /** 951 * Check if mlx4 device was removed. 952 * 953 * @param dev 954 * Pointer to Ethernet device structure. 955 * 956 * @return 957 * 1 when device is removed, otherwise 0. 958 */ 959 int 960 mlx4_is_removed(struct rte_eth_dev *dev) 961 { 962 struct ibv_device_attr device_attr; 963 struct mlx4_priv *priv = dev->data->dev_private; 964 965 if (mlx4_glue->query_device(priv->ctx, &device_attr) == EIO) 966 return 1; 967 return 0; 968 } 969