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 * @return 346 * 0 on success, a negative errno value otherwise and rte_errno is set. 347 */ 348 static int 349 mlx4_rxmode_toggle(struct rte_eth_dev *dev, enum rxmode_toggle toggle) 350 { 351 struct mlx4_priv *priv = dev->data->dev_private; 352 const char *mode; 353 struct rte_flow_error error; 354 int ret; 355 356 switch (toggle) { 357 case RXMODE_TOGGLE_PROMISC_OFF: 358 case RXMODE_TOGGLE_PROMISC_ON: 359 mode = "promiscuous"; 360 dev->data->promiscuous = toggle & 1; 361 break; 362 case RXMODE_TOGGLE_ALLMULTI_OFF: 363 case RXMODE_TOGGLE_ALLMULTI_ON: 364 mode = "all multicast"; 365 dev->data->all_multicast = toggle & 1; 366 break; 367 default: 368 mode = "undefined"; 369 } 370 371 ret = mlx4_flow_sync(priv, &error); 372 if (!ret) 373 return 0; 374 375 ERROR("cannot toggle %s mode (code %d, \"%s\")," 376 " flow error type %d, cause %p, message: %s", 377 mode, rte_errno, strerror(rte_errno), error.type, error.cause, 378 error.message ? error.message : "(unspecified)"); 379 return ret; 380 } 381 382 /** 383 * DPDK callback to enable promiscuous mode. 384 * 385 * @param dev 386 * Pointer to Ethernet device structure. 387 * 388 * @return 389 * 0 on success, a negative errno value otherwise and rte_errno is set. 390 */ 391 int 392 mlx4_promiscuous_enable(struct rte_eth_dev *dev) 393 { 394 return mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_PROMISC_ON); 395 } 396 397 /** 398 * DPDK callback to disable promiscuous mode. 399 * 400 * @param dev 401 * Pointer to Ethernet device structure. 402 * 403 * @return 404 * 0 on success, a negative errno value otherwise and rte_errno is set. 405 */ 406 int 407 mlx4_promiscuous_disable(struct rte_eth_dev *dev) 408 { 409 return mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_PROMISC_OFF); 410 } 411 412 /** 413 * DPDK callback to enable all multicast mode. 414 * 415 * @param dev 416 * Pointer to Ethernet device structure. 417 * 418 * @return 419 * 0 on success, a negative errno value otherwise and rte_errno is set. 420 */ 421 int 422 mlx4_allmulticast_enable(struct rte_eth_dev *dev) 423 { 424 return mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_ALLMULTI_ON); 425 } 426 427 /** 428 * DPDK callback to disable all multicast mode. 429 * 430 * @param dev 431 * Pointer to Ethernet device structure. 432 * 433 * @return 434 * 0 on success, a negative errno value otherwise and rte_errno is set. 435 */ 436 int 437 mlx4_allmulticast_disable(struct rte_eth_dev *dev) 438 { 439 return mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_ALLMULTI_OFF); 440 } 441 442 /** 443 * DPDK callback to remove a MAC address. 444 * 445 * @param dev 446 * Pointer to Ethernet device structure. 447 * @param index 448 * MAC address index. 449 */ 450 void 451 mlx4_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 452 { 453 struct mlx4_priv *priv = dev->data->dev_private; 454 struct rte_flow_error error; 455 456 if (index >= RTE_DIM(priv->mac) - priv->mac_mc) { 457 rte_errno = EINVAL; 458 return; 459 } 460 memset(&priv->mac[index], 0, sizeof(priv->mac[index])); 461 if (!mlx4_flow_sync(priv, &error)) 462 return; 463 ERROR("failed to synchronize flow rules after removing MAC address" 464 " at index %d (code %d, \"%s\")," 465 " flow error type %d, cause %p, message: %s", 466 index, rte_errno, strerror(rte_errno), error.type, error.cause, 467 error.message ? error.message : "(unspecified)"); 468 } 469 470 /** 471 * DPDK callback to add a MAC address. 472 * 473 * @param dev 474 * Pointer to Ethernet device structure. 475 * @param mac_addr 476 * MAC address to register. 477 * @param index 478 * MAC address index. 479 * @param vmdq 480 * VMDq pool index to associate address with (ignored). 481 * 482 * @return 483 * 0 on success, negative errno value otherwise and rte_errno is set. 484 */ 485 int 486 mlx4_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, 487 uint32_t index, uint32_t vmdq) 488 { 489 struct mlx4_priv *priv = dev->data->dev_private; 490 struct rte_flow_error error; 491 int ret; 492 493 (void)vmdq; 494 if (index >= RTE_DIM(priv->mac) - priv->mac_mc) { 495 rte_errno = EINVAL; 496 return -rte_errno; 497 } 498 memcpy(&priv->mac[index], mac_addr, sizeof(priv->mac[index])); 499 ret = mlx4_flow_sync(priv, &error); 500 if (!ret) 501 return 0; 502 ERROR("failed to synchronize flow rules after adding MAC address" 503 " at index %d (code %d, \"%s\")," 504 " flow error type %d, cause %p, message: %s", 505 index, rte_errno, strerror(rte_errno), error.type, error.cause, 506 error.message ? error.message : "(unspecified)"); 507 return ret; 508 } 509 510 /** 511 * DPDK callback to configure multicast addresses. 512 * 513 * @param dev 514 * Pointer to Ethernet device structure. 515 * @param list 516 * List of MAC addresses to register. 517 * @param num 518 * Number of entries in list. 519 * 520 * @return 521 * 0 on success, negative errno value otherwise and rte_errno is set. 522 */ 523 int 524 mlx4_set_mc_addr_list(struct rte_eth_dev *dev, struct rte_ether_addr *list, 525 uint32_t num) 526 { 527 struct mlx4_priv *priv = dev->data->dev_private; 528 struct rte_flow_error error; 529 int ret; 530 531 if (num > RTE_DIM(priv->mac)) { 532 rte_errno = EINVAL; 533 return -rte_errno; 534 } 535 /* 536 * Make sure there is enough room to increase the number of 537 * multicast entries without overwriting standard entries. 538 */ 539 if (num > priv->mac_mc) { 540 unsigned int i; 541 542 for (i = RTE_DIM(priv->mac) - num; 543 i != RTE_DIM(priv->mac) - priv->mac_mc; 544 ++i) 545 if (!rte_is_zero_ether_addr(&priv->mac[i])) { 546 rte_errno = EBUSY; 547 return -rte_errno; 548 } 549 } else if (num < priv->mac_mc) { 550 /* Clear unused entries. */ 551 memset(priv->mac + RTE_DIM(priv->mac) - priv->mac_mc, 552 0, 553 sizeof(priv->mac[0]) * (priv->mac_mc - num)); 554 } 555 memcpy(priv->mac + RTE_DIM(priv->mac) - num, list, sizeof(*list) * num); 556 priv->mac_mc = num; 557 ret = mlx4_flow_sync(priv, &error); 558 if (!ret) 559 return 0; 560 ERROR("failed to synchronize flow rules after modifying MC list," 561 " (code %d, \"%s\"), flow error type %d, cause %p, message: %s", 562 rte_errno, strerror(rte_errno), error.type, error.cause, 563 error.message ? error.message : "(unspecified)"); 564 return ret; 565 } 566 567 /** 568 * DPDK callback to configure a VLAN filter. 569 * 570 * @param dev 571 * Pointer to Ethernet device structure. 572 * @param vlan_id 573 * VLAN ID to filter. 574 * @param on 575 * Toggle filter. 576 * 577 * @return 578 * 0 on success, negative errno value otherwise and rte_errno is set. 579 */ 580 int 581 mlx4_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) 582 { 583 struct mlx4_priv *priv = dev->data->dev_private; 584 struct rte_flow_error error; 585 unsigned int vidx = vlan_id / 64; 586 unsigned int vbit = vlan_id % 64; 587 uint64_t *v; 588 int ret; 589 590 if (vidx >= RTE_DIM(dev->data->vlan_filter_conf.ids)) { 591 rte_errno = EINVAL; 592 return -rte_errno; 593 } 594 v = &dev->data->vlan_filter_conf.ids[vidx]; 595 *v &= ~(UINT64_C(1) << vbit); 596 *v |= (uint64_t)!!on << vbit; 597 ret = mlx4_flow_sync(priv, &error); 598 if (!ret) 599 return 0; 600 ERROR("failed to synchronize flow rules after %s VLAN filter on ID %u" 601 " (code %d, \"%s\"), " 602 " flow error type %d, cause %p, message: %s", 603 on ? "enabling" : "disabling", vlan_id, 604 rte_errno, strerror(rte_errno), error.type, error.cause, 605 error.message ? error.message : "(unspecified)"); 606 return ret; 607 } 608 609 /** 610 * DPDK callback to set the primary MAC address. 611 * 612 * @param dev 613 * Pointer to Ethernet device structure. 614 * @param mac_addr 615 * MAC address to register. 616 * 617 * @return 618 * 0 on success, negative errno value otherwise and rte_errno is set. 619 */ 620 int 621 mlx4_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) 622 { 623 return mlx4_mac_addr_add(dev, mac_addr, 0, 0); 624 } 625 626 /** 627 * DPDK callback to get information about the device. 628 * 629 * @param dev 630 * Pointer to Ethernet device structure. 631 * @param[out] info 632 * Info structure output buffer. 633 */ 634 int 635 mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 636 { 637 struct mlx4_priv *priv = dev->data->dev_private; 638 unsigned int max; 639 640 /* FIXME: we should ask the device for these values. */ 641 info->min_rx_bufsize = 32; 642 info->max_rx_pktlen = 65536; 643 /* 644 * Since we need one CQ per QP, the limit is the minimum number 645 * between the two values. 646 */ 647 max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ? 648 priv->device_attr.max_qp : priv->device_attr.max_cq); 649 /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 650 if (max >= 65535) 651 max = 65535; 652 info->max_rx_queues = max; 653 info->max_tx_queues = max; 654 info->max_mac_addrs = RTE_DIM(priv->mac); 655 info->tx_offload_capa = mlx4_get_tx_port_offloads(priv); 656 info->rx_queue_offload_capa = mlx4_get_rx_queue_offloads(priv); 657 info->rx_offload_capa = (mlx4_get_rx_port_offloads(priv) | 658 info->rx_queue_offload_capa); 659 info->if_index = priv->if_index; 660 info->hash_key_size = MLX4_RSS_HASH_KEY_SIZE; 661 info->speed_capa = 662 ETH_LINK_SPEED_1G | 663 ETH_LINK_SPEED_10G | 664 ETH_LINK_SPEED_20G | 665 ETH_LINK_SPEED_40G | 666 ETH_LINK_SPEED_56G; 667 info->flow_type_rss_offloads = mlx4_conv_rss_types(priv, 0, 1); 668 669 return 0; 670 } 671 672 /** 673 * Get firmware version of a device. 674 * 675 * @param dev 676 * Ethernet device port. 677 * @param fw_ver 678 * String output allocated by caller. 679 * @param fw_size 680 * Size of the output string, including terminating null byte. 681 * 682 * @return 683 * 0 on success, or the size of the non truncated string if too big. 684 */ 685 int mlx4_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 686 { 687 struct mlx4_priv *priv = dev->data->dev_private; 688 struct ibv_device_attr *attr = &priv->device_attr; 689 size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 690 691 if (fw_size < size) 692 return size; 693 if (fw_ver != NULL) 694 strlcpy(fw_ver, attr->fw_ver, fw_size); 695 return 0; 696 } 697 698 /** 699 * DPDK callback to get device statistics. 700 * 701 * @param dev 702 * Pointer to Ethernet device structure. 703 * @param[out] stats 704 * Stats structure output buffer. 705 */ 706 int 707 mlx4_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 708 { 709 struct rte_eth_stats tmp; 710 unsigned int i; 711 unsigned int idx; 712 713 memset(&tmp, 0, sizeof(tmp)); 714 /* Add software counters. */ 715 for (i = 0; i != dev->data->nb_rx_queues; ++i) { 716 struct rxq *rxq = dev->data->rx_queues[i]; 717 718 if (rxq == NULL) 719 continue; 720 idx = rxq->stats.idx; 721 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { 722 tmp.q_ipackets[idx] += rxq->stats.ipackets; 723 tmp.q_ibytes[idx] += rxq->stats.ibytes; 724 tmp.q_errors[idx] += (rxq->stats.idropped + 725 rxq->stats.rx_nombuf); 726 } 727 tmp.ipackets += rxq->stats.ipackets; 728 tmp.ibytes += rxq->stats.ibytes; 729 tmp.ierrors += rxq->stats.idropped; 730 tmp.rx_nombuf += rxq->stats.rx_nombuf; 731 } 732 for (i = 0; i != dev->data->nb_tx_queues; ++i) { 733 struct txq *txq = dev->data->tx_queues[i]; 734 735 if (txq == NULL) 736 continue; 737 idx = txq->stats.idx; 738 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { 739 tmp.q_opackets[idx] += txq->stats.opackets; 740 tmp.q_obytes[idx] += txq->stats.obytes; 741 } 742 tmp.opackets += txq->stats.opackets; 743 tmp.obytes += txq->stats.obytes; 744 tmp.oerrors += txq->stats.odropped; 745 } 746 *stats = tmp; 747 return 0; 748 } 749 750 /** 751 * DPDK callback to clear device statistics. 752 * 753 * @param dev 754 * Pointer to Ethernet device structure. 755 * 756 * @return 757 * alwasy 0 on success 758 */ 759 int 760 mlx4_stats_reset(struct rte_eth_dev *dev) 761 { 762 unsigned int i; 763 764 for (i = 0; i != dev->data->nb_rx_queues; ++i) { 765 struct rxq *rxq = dev->data->rx_queues[i]; 766 767 if (rxq) 768 rxq->stats = (struct mlx4_rxq_stats){ 769 .idx = rxq->stats.idx, 770 }; 771 } 772 for (i = 0; i != dev->data->nb_tx_queues; ++i) { 773 struct txq *txq = dev->data->tx_queues[i]; 774 775 if (txq) 776 txq->stats = (struct mlx4_txq_stats){ 777 .idx = txq->stats.idx, 778 }; 779 } 780 781 return 0; 782 } 783 784 /** 785 * DPDK callback to retrieve physical link information. 786 * 787 * @param dev 788 * Pointer to Ethernet device structure. 789 * @param wait_to_complete 790 * Wait for request completion (ignored). 791 * 792 * @return 793 * 0 on success, negative errno value otherwise and rte_errno is set. 794 */ 795 int 796 mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete) 797 { 798 const struct mlx4_priv *priv = dev->data->dev_private; 799 struct ethtool_cmd edata = { 800 .cmd = ETHTOOL_GSET, 801 }; 802 struct ifreq ifr; 803 struct rte_eth_link dev_link; 804 int link_speed = 0; 805 806 if (priv == NULL) { 807 rte_errno = EINVAL; 808 return -rte_errno; 809 } 810 (void)wait_to_complete; 811 if (mlx4_ifreq(priv, SIOCGIFFLAGS, &ifr)) { 812 WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(rte_errno)); 813 return -rte_errno; 814 } 815 memset(&dev_link, 0, sizeof(dev_link)); 816 dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && 817 (ifr.ifr_flags & IFF_RUNNING)); 818 ifr.ifr_data = (void *)&edata; 819 if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) { 820 WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s", 821 strerror(rte_errno)); 822 return -rte_errno; 823 } 824 link_speed = ethtool_cmd_speed(&edata); 825 if (link_speed == -1) 826 dev_link.link_speed = ETH_SPEED_NUM_NONE; 827 else 828 dev_link.link_speed = link_speed; 829 dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 830 ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 831 dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 832 ETH_LINK_SPEED_FIXED); 833 dev->data->dev_link = dev_link; 834 return 0; 835 } 836 837 /** 838 * DPDK callback to get flow control status. 839 * 840 * @param dev 841 * Pointer to Ethernet device structure. 842 * @param[out] fc_conf 843 * Flow control output buffer. 844 * 845 * @return 846 * 0 on success, negative errno value otherwise and rte_errno is set. 847 */ 848 int 849 mlx4_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 850 { 851 struct mlx4_priv *priv = dev->data->dev_private; 852 struct ifreq ifr; 853 struct ethtool_pauseparam ethpause = { 854 .cmd = ETHTOOL_GPAUSEPARAM, 855 }; 856 int ret; 857 858 ifr.ifr_data = (void *)ðpause; 859 if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) { 860 ret = rte_errno; 861 WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM)" 862 " failed: %s", 863 strerror(rte_errno)); 864 goto out; 865 } 866 fc_conf->autoneg = ethpause.autoneg; 867 if (ethpause.rx_pause && ethpause.tx_pause) 868 fc_conf->mode = RTE_FC_FULL; 869 else if (ethpause.rx_pause) 870 fc_conf->mode = RTE_FC_RX_PAUSE; 871 else if (ethpause.tx_pause) 872 fc_conf->mode = RTE_FC_TX_PAUSE; 873 else 874 fc_conf->mode = RTE_FC_NONE; 875 ret = 0; 876 out: 877 assert(ret >= 0); 878 return -ret; 879 } 880 881 /** 882 * DPDK callback to modify flow control parameters. 883 * 884 * @param dev 885 * Pointer to Ethernet device structure. 886 * @param[in] fc_conf 887 * Flow control parameters. 888 * 889 * @return 890 * 0 on success, negative errno value otherwise and rte_errno is set. 891 */ 892 int 893 mlx4_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 894 { 895 struct mlx4_priv *priv = dev->data->dev_private; 896 struct ifreq ifr; 897 struct ethtool_pauseparam ethpause = { 898 .cmd = ETHTOOL_SPAUSEPARAM, 899 }; 900 int ret; 901 902 ifr.ifr_data = (void *)ðpause; 903 ethpause.autoneg = fc_conf->autoneg; 904 if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 905 (fc_conf->mode & RTE_FC_RX_PAUSE)) 906 ethpause.rx_pause = 1; 907 else 908 ethpause.rx_pause = 0; 909 if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 910 (fc_conf->mode & RTE_FC_TX_PAUSE)) 911 ethpause.tx_pause = 1; 912 else 913 ethpause.tx_pause = 0; 914 if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) { 915 ret = rte_errno; 916 WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 917 " failed: %s", 918 strerror(rte_errno)); 919 goto out; 920 } 921 ret = 0; 922 out: 923 assert(ret >= 0); 924 return -ret; 925 } 926 927 /** 928 * DPDK callback to retrieve the received packet types that are recognized 929 * by the device. 930 * 931 * @param dev 932 * Pointer to Ethernet device structure. 933 * 934 * @return 935 * Pointer to an array of recognized packet types if in Rx burst mode, 936 * NULL otherwise. 937 */ 938 const uint32_t * 939 mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev) 940 { 941 static const uint32_t ptypes[] = { 942 /* refers to rxq_cq_to_pkt_type() */ 943 RTE_PTYPE_L2_ETHER, 944 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 945 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 946 RTE_PTYPE_L4_FRAG, 947 RTE_PTYPE_L4_TCP, 948 RTE_PTYPE_L4_UDP, 949 RTE_PTYPE_UNKNOWN 950 }; 951 static const uint32_t ptypes_l2tun[] = { 952 /* refers to rxq_cq_to_pkt_type() */ 953 RTE_PTYPE_L2_ETHER, 954 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 955 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 956 RTE_PTYPE_L4_FRAG, 957 RTE_PTYPE_L4_TCP, 958 RTE_PTYPE_L4_UDP, 959 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 960 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 961 RTE_PTYPE_UNKNOWN 962 }; 963 struct mlx4_priv *priv = dev->data->dev_private; 964 965 if (dev->rx_pkt_burst == mlx4_rx_burst) { 966 if (priv->hw_csum_l2tun) 967 return ptypes_l2tun; 968 else 969 return ptypes; 970 } 971 return NULL; 972 } 973 974 /** 975 * Check if mlx4 device was removed. 976 * 977 * @param dev 978 * Pointer to Ethernet device structure. 979 * 980 * @return 981 * 1 when device is removed, otherwise 0. 982 */ 983 int 984 mlx4_is_removed(struct rte_eth_dev *dev) 985 { 986 struct ibv_device_attr device_attr; 987 struct mlx4_priv *priv = dev->data->dev_private; 988 989 if (mlx4_glue->query_device(priv->ctx, &device_attr) == EIO) 990 return 1; 991 return 0; 992 } 993