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