1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. 5 * All rights reserved. 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 Intel Corporation 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 #include <stdio.h> 34 #include <string.h> 35 #include <stdint.h> 36 #include <rte_version.h> 37 #include <rte_ethdev.h> 38 #include <rte_ether.h> 39 #include <rte_pci.h> 40 #ifdef RTE_LIBRTE_IXGBE_PMD 41 #include <rte_pmd_ixgbe.h> 42 #endif 43 #include "rte_ethtool.h" 44 45 #define PKTPOOL_SIZE 512 46 #define PKTPOOL_CACHE 32 47 48 49 int 50 rte_ethtool_get_drvinfo(uint16_t port_id, struct ethtool_drvinfo *drvinfo) 51 { 52 struct rte_eth_dev_info dev_info; 53 struct rte_dev_reg_info reg_info; 54 int n; 55 int ret; 56 57 if (drvinfo == NULL) 58 return -EINVAL; 59 60 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); 61 62 ret = rte_eth_dev_fw_version_get(port_id, drvinfo->fw_version, 63 sizeof(drvinfo->fw_version)); 64 if (ret < 0) 65 printf("firmware version get error: (%s)\n", strerror(-ret)); 66 else if (ret > 0) 67 printf("Insufficient fw version buffer size, " 68 "the minimum size should be %d\n", ret); 69 70 memset(&dev_info, 0, sizeof(dev_info)); 71 rte_eth_dev_info_get(port_id, &dev_info); 72 73 snprintf(drvinfo->driver, sizeof(drvinfo->driver), "%s", 74 dev_info.driver_name); 75 snprintf(drvinfo->version, sizeof(drvinfo->version), "%s", 76 rte_version()); 77 /* TODO: replace bus_info by rte_devargs.name */ 78 if (dev_info.pci_dev) 79 snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), 80 "%04x:%02x:%02x.%x", 81 dev_info.pci_dev->addr.domain, 82 dev_info.pci_dev->addr.bus, 83 dev_info.pci_dev->addr.devid, 84 dev_info.pci_dev->addr.function); 85 else 86 snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), "N/A"); 87 88 memset(®_info, 0, sizeof(reg_info)); 89 rte_eth_dev_get_reg_info(port_id, ®_info); 90 n = reg_info.length; 91 if (n > 0) 92 drvinfo->regdump_len = n; 93 else 94 drvinfo->regdump_len = 0; 95 96 n = rte_eth_dev_get_eeprom_length(port_id); 97 if (n > 0) 98 drvinfo->eedump_len = n; 99 else 100 drvinfo->eedump_len = 0; 101 102 drvinfo->n_stats = sizeof(struct rte_eth_stats) / sizeof(uint64_t); 103 drvinfo->testinfo_len = 0; 104 105 return 0; 106 } 107 108 int 109 rte_ethtool_get_regs_len(uint16_t port_id) 110 { 111 struct rte_dev_reg_info reg_info; 112 int ret; 113 114 memset(®_info, 0, sizeof(reg_info)); 115 116 ret = rte_eth_dev_get_reg_info(port_id, ®_info); 117 if (ret) 118 return ret; 119 120 return reg_info.length * reg_info.width; 121 } 122 123 int 124 rte_ethtool_get_regs(uint16_t port_id, struct ethtool_regs *regs, void *data) 125 { 126 struct rte_dev_reg_info reg_info; 127 int status; 128 129 if (regs == NULL || data == NULL) 130 return -EINVAL; 131 132 reg_info.data = data; 133 reg_info.length = 0; 134 135 status = rte_eth_dev_get_reg_info(port_id, ®_info); 136 if (status) 137 return status; 138 regs->version = reg_info.version; 139 140 return 0; 141 } 142 143 int 144 rte_ethtool_get_link(uint16_t port_id) 145 { 146 struct rte_eth_link link; 147 148 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); 149 rte_eth_link_get(port_id, &link); 150 return link.link_status; 151 } 152 153 int 154 rte_ethtool_get_eeprom_len(uint16_t port_id) 155 { 156 return rte_eth_dev_get_eeprom_length(port_id); 157 } 158 159 int 160 rte_ethtool_get_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom, 161 void *words) 162 { 163 struct rte_dev_eeprom_info eeprom_info; 164 int status; 165 166 if (eeprom == NULL || words == NULL) 167 return -EINVAL; 168 169 eeprom_info.offset = eeprom->offset; 170 eeprom_info.length = eeprom->len; 171 eeprom_info.data = words; 172 173 status = rte_eth_dev_get_eeprom(port_id, &eeprom_info); 174 if (status) 175 return status; 176 177 eeprom->magic = eeprom_info.magic; 178 179 return 0; 180 } 181 182 int 183 rte_ethtool_set_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom, 184 void *words) 185 { 186 struct rte_dev_eeprom_info eeprom_info; 187 int status; 188 189 if (eeprom == NULL || words == NULL || eeprom->offset >= eeprom->len) 190 return -EINVAL; 191 192 eeprom_info.offset = eeprom->offset; 193 eeprom_info.length = eeprom->len; 194 eeprom_info.data = words; 195 196 status = rte_eth_dev_set_eeprom(port_id, &eeprom_info); 197 if (status) 198 return status; 199 200 eeprom->magic = eeprom_info.magic; 201 202 return 0; 203 } 204 205 int 206 rte_ethtool_get_pauseparam(uint16_t port_id, 207 struct ethtool_pauseparam *pause_param) 208 { 209 struct rte_eth_fc_conf fc_conf; 210 int status; 211 212 if (pause_param == NULL) 213 return -EINVAL; 214 215 status = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf); 216 if (status) 217 return status; 218 219 pause_param->tx_pause = 0; 220 pause_param->rx_pause = 0; 221 switch (fc_conf.mode) { 222 case RTE_FC_RX_PAUSE: 223 pause_param->rx_pause = 1; 224 break; 225 case RTE_FC_TX_PAUSE: 226 pause_param->tx_pause = 1; 227 break; 228 case RTE_FC_FULL: 229 pause_param->rx_pause = 1; 230 pause_param->tx_pause = 1; 231 default: 232 /* dummy block to avoid compiler warning */ 233 break; 234 } 235 pause_param->autoneg = (uint32_t)fc_conf.autoneg; 236 237 return 0; 238 } 239 240 int 241 rte_ethtool_set_pauseparam(uint16_t port_id, 242 struct ethtool_pauseparam *pause_param) 243 { 244 struct rte_eth_fc_conf fc_conf; 245 int status; 246 247 if (pause_param == NULL) 248 return -EINVAL; 249 250 /* 251 * Read device flow control parameter first since 252 * ethtool set_pauseparam op doesn't have all the information. 253 * as defined in struct rte_eth_fc_conf. 254 * This API requires the device to support both 255 * rte_eth_dev_flow_ctrl_get and rte_eth_dev_flow_ctrl_set, otherwise 256 * return -ENOTSUP 257 */ 258 status = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf); 259 if (status) 260 return status; 261 262 fc_conf.autoneg = (uint8_t)pause_param->autoneg; 263 264 if (pause_param->tx_pause) { 265 if (pause_param->rx_pause) 266 fc_conf.mode = RTE_FC_FULL; 267 else 268 fc_conf.mode = RTE_FC_TX_PAUSE; 269 } else { 270 if (pause_param->rx_pause) 271 fc_conf.mode = RTE_FC_RX_PAUSE; 272 else 273 fc_conf.mode = RTE_FC_NONE; 274 } 275 276 status = rte_eth_dev_flow_ctrl_set(port_id, &fc_conf); 277 if (status) 278 return status; 279 280 return 0; 281 } 282 283 int 284 rte_ethtool_net_open(uint16_t port_id) 285 { 286 rte_eth_dev_stop(port_id); 287 288 return rte_eth_dev_start(port_id); 289 } 290 291 int 292 rte_ethtool_net_stop(uint16_t port_id) 293 { 294 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); 295 rte_eth_dev_stop(port_id); 296 297 return 0; 298 } 299 300 int 301 rte_ethtool_net_get_mac_addr(uint16_t port_id, struct ether_addr *addr) 302 { 303 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); 304 if (addr == NULL) 305 return -EINVAL; 306 rte_eth_macaddr_get(port_id, addr); 307 308 return 0; 309 } 310 311 int 312 rte_ethtool_net_set_mac_addr(uint16_t port_id, struct ether_addr *addr) 313 { 314 if (addr == NULL) 315 return -EINVAL; 316 return rte_eth_dev_default_mac_addr_set(port_id, addr); 317 } 318 319 int 320 rte_ethtool_net_validate_addr(uint16_t port_id __rte_unused, 321 struct ether_addr *addr) 322 { 323 if (addr == NULL) 324 return -EINVAL; 325 return is_valid_assigned_ether_addr(addr); 326 } 327 328 int 329 rte_ethtool_net_change_mtu(uint16_t port_id, int mtu) 330 { 331 if (mtu < 0 || mtu > UINT16_MAX) 332 return -EINVAL; 333 return rte_eth_dev_set_mtu(port_id, (uint16_t)mtu); 334 } 335 336 int 337 rte_ethtool_net_get_stats64(uint16_t port_id, struct rte_eth_stats *stats) 338 { 339 if (stats == NULL) 340 return -EINVAL; 341 return rte_eth_stats_get(port_id, stats); 342 } 343 344 int 345 rte_ethtool_net_vlan_rx_add_vid(uint16_t port_id, uint16_t vid) 346 { 347 return rte_eth_dev_vlan_filter(port_id, vid, 1); 348 } 349 350 int 351 rte_ethtool_net_vlan_rx_kill_vid(uint16_t port_id, uint16_t vid) 352 { 353 return rte_eth_dev_vlan_filter(port_id, vid, 0); 354 } 355 356 /* 357 * The set_rx_mode provides driver-specific rx mode setting. 358 * This implementation implements rx mode setting based upon 359 * ixgbe/igb drivers. Further improvement is to provide a 360 * callback op field over struct rte_eth_dev::dev_ops so each 361 * driver can register device-specific implementation 362 */ 363 int 364 rte_ethtool_net_set_rx_mode(uint16_t port_id) 365 { 366 uint16_t num_vfs; 367 struct rte_eth_dev_info dev_info; 368 uint16_t vf; 369 370 memset(&dev_info, 0, sizeof(dev_info)); 371 rte_eth_dev_info_get(port_id, &dev_info); 372 num_vfs = dev_info.max_vfs; 373 374 /* Set VF vf_rx_mode, VF unsupport status is discard */ 375 for (vf = 0; vf < num_vfs; vf++) { 376 #ifdef RTE_LIBRTE_IXGBE_PMD 377 rte_pmd_ixgbe_set_vf_rxmode(port_id, vf, 378 ETH_VMDQ_ACCEPT_UNTAG, 0); 379 #endif 380 } 381 382 /* Enable Rx vlan filter, VF unspport status is discard */ 383 rte_eth_dev_set_vlan_offload(port_id, ETH_VLAN_FILTER_MASK); 384 385 return 0; 386 } 387 388 389 int 390 rte_ethtool_get_ringparam(uint16_t port_id, 391 struct ethtool_ringparam *ring_param) 392 { 393 struct rte_eth_dev_info dev_info; 394 struct rte_eth_rxq_info rx_qinfo; 395 struct rte_eth_txq_info tx_qinfo; 396 int stat; 397 398 if (ring_param == NULL) 399 return -EINVAL; 400 401 rte_eth_dev_info_get(port_id, &dev_info); 402 403 stat = rte_eth_rx_queue_info_get(port_id, 0, &rx_qinfo); 404 if (stat != 0) 405 return stat; 406 407 stat = rte_eth_tx_queue_info_get(port_id, 0, &tx_qinfo); 408 if (stat != 0) 409 return stat; 410 411 memset(ring_param, 0, sizeof(*ring_param)); 412 ring_param->rx_pending = rx_qinfo.nb_desc; 413 ring_param->rx_max_pending = dev_info.rx_desc_lim.nb_max; 414 ring_param->tx_pending = tx_qinfo.nb_desc; 415 ring_param->tx_max_pending = dev_info.tx_desc_lim.nb_max; 416 417 return 0; 418 } 419 420 421 int 422 rte_ethtool_set_ringparam(uint16_t port_id, 423 struct ethtool_ringparam *ring_param) 424 { 425 struct rte_eth_rxq_info rx_qinfo; 426 int stat; 427 428 if (ring_param == NULL) 429 return -EINVAL; 430 431 stat = rte_eth_rx_queue_info_get(port_id, 0, &rx_qinfo); 432 if (stat != 0) 433 return stat; 434 435 rte_eth_dev_stop(port_id); 436 437 stat = rte_eth_tx_queue_setup(port_id, 0, ring_param->tx_pending, 438 rte_socket_id(), NULL); 439 if (stat != 0) 440 return stat; 441 442 stat = rte_eth_rx_queue_setup(port_id, 0, ring_param->rx_pending, 443 rte_socket_id(), NULL, rx_qinfo.mp); 444 if (stat != 0) 445 return stat; 446 447 return rte_eth_dev_start(port_id); 448 } 449