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