1/******************************************************************************* 2 * 3 * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver 4 * Copyright(c) 2013 - 2015 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 * The full GNU General Public License is included in this distribution in 19 * the file called "COPYING". 20 * 21 * Contact Information: 22 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 23 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 24 * 25 ******************************************************************************/ 26 27/* ethtool support for i40evf */ 28#include "i40evf.h" 29 30#include <linux/uaccess.h> 31 32struct i40evf_stats { 33 char stat_string[ETH_GSTRING_LEN]; 34 int stat_offset; 35}; 36 37#define I40EVF_STAT(_name, _stat) { \ 38 .stat_string = _name, \ 39 .stat_offset = offsetof(struct i40evf_adapter, _stat) \ 40} 41 42/* All stats are u64, so we don't need to track the size of the field. */ 43static const struct i40evf_stats i40evf_gstrings_stats[] = { 44 I40EVF_STAT("rx_bytes", current_stats.rx_bytes), 45 I40EVF_STAT("rx_unicast", current_stats.rx_unicast), 46 I40EVF_STAT("rx_multicast", current_stats.rx_multicast), 47 I40EVF_STAT("rx_broadcast", current_stats.rx_broadcast), 48 I40EVF_STAT("rx_discards", current_stats.rx_discards), 49 I40EVF_STAT("rx_unknown_protocol", current_stats.rx_unknown_protocol), 50 I40EVF_STAT("tx_bytes", current_stats.tx_bytes), 51 I40EVF_STAT("tx_unicast", current_stats.tx_unicast), 52 I40EVF_STAT("tx_multicast", current_stats.tx_multicast), 53 I40EVF_STAT("tx_broadcast", current_stats.tx_broadcast), 54 I40EVF_STAT("tx_discards", current_stats.tx_discards), 55 I40EVF_STAT("tx_errors", current_stats.tx_errors), 56}; 57 58#define I40EVF_GLOBAL_STATS_LEN ARRAY_SIZE(i40evf_gstrings_stats) 59#define I40EVF_QUEUE_STATS_LEN(_dev) \ 60 (((struct i40evf_adapter *)\ 61 netdev_priv(_dev))->num_active_queues \ 62 * 2 * (sizeof(struct i40e_queue_stats) / sizeof(u64))) 63#define I40EVF_STATS_LEN(_dev) \ 64 (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev)) 65 66/** 67 * i40evf_get_settings - Get Link Speed and Duplex settings 68 * @netdev: network interface device structure 69 * @ecmd: ethtool command 70 * 71 * Reports speed/duplex settings. Because this is a VF, we don't know what 72 * kind of link we really have, so we fake it. 73 **/ 74static int i40evf_get_settings(struct net_device *netdev, 75 struct ethtool_cmd *ecmd) 76{ 77 /* In the future the VF will be able to query the PF for 78 * some information - for now use a dummy value 79 */ 80 ecmd->supported = 0; 81 ecmd->autoneg = AUTONEG_DISABLE; 82 ecmd->transceiver = XCVR_DUMMY1; 83 ecmd->port = PORT_NONE; 84 85 return 0; 86} 87 88/** 89 * i40evf_get_sset_count - Get length of string set 90 * @netdev: network interface device structure 91 * @sset: id of string set 92 * 93 * Reports size of string table. This driver only supports 94 * strings for statistics. 95 **/ 96static int i40evf_get_sset_count(struct net_device *netdev, int sset) 97{ 98 if (sset == ETH_SS_STATS) 99 return I40EVF_STATS_LEN(netdev); 100 else 101 return -EINVAL; 102} 103 104/** 105 * i40evf_get_ethtool_stats - report device statistics 106 * @netdev: network interface device structure 107 * @stats: ethtool statistics structure 108 * @data: pointer to data buffer 109 * 110 * All statistics are added to the data buffer as an array of u64. 111 **/ 112static void i40evf_get_ethtool_stats(struct net_device *netdev, 113 struct ethtool_stats *stats, u64 *data) 114{ 115 struct i40evf_adapter *adapter = netdev_priv(netdev); 116 int i, j; 117 char *p; 118 119 for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) { 120 p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset; 121 data[i] = *(u64 *)p; 122 } 123 for (j = 0; j < adapter->num_active_queues; j++) { 124 data[i++] = adapter->tx_rings[j]->stats.packets; 125 data[i++] = adapter->tx_rings[j]->stats.bytes; 126 } 127 for (j = 0; j < adapter->num_active_queues; j++) { 128 data[i++] = adapter->rx_rings[j]->stats.packets; 129 data[i++] = adapter->rx_rings[j]->stats.bytes; 130 } 131} 132 133/** 134 * i40evf_get_strings - Get string set 135 * @netdev: network interface device structure 136 * @sset: id of string set 137 * @data: buffer for string data 138 * 139 * Builds stats string table. 140 **/ 141static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data) 142{ 143 struct i40evf_adapter *adapter = netdev_priv(netdev); 144 u8 *p = data; 145 int i; 146 147 if (sset == ETH_SS_STATS) { 148 for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) { 149 memcpy(p, i40evf_gstrings_stats[i].stat_string, 150 ETH_GSTRING_LEN); 151 p += ETH_GSTRING_LEN; 152 } 153 for (i = 0; i < adapter->num_active_queues; i++) { 154 snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i); 155 p += ETH_GSTRING_LEN; 156 snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i); 157 p += ETH_GSTRING_LEN; 158 } 159 for (i = 0; i < adapter->num_active_queues; i++) { 160 snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i); 161 p += ETH_GSTRING_LEN; 162 snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i); 163 p += ETH_GSTRING_LEN; 164 } 165 } 166} 167 168/** 169 * i40evf_get_msglevel - Get debug message level 170 * @netdev: network interface device structure 171 * 172 * Returns current debug message level. 173 **/ 174static u32 i40evf_get_msglevel(struct net_device *netdev) 175{ 176 struct i40evf_adapter *adapter = netdev_priv(netdev); 177 178 return adapter->msg_enable; 179} 180 181/** 182 * i40evf_set_msglevel - Set debug message level 183 * @netdev: network interface device structure 184 * @data: message level 185 * 186 * Set current debug message level. Higher values cause the driver to 187 * be noisier. 188 **/ 189static void i40evf_set_msglevel(struct net_device *netdev, u32 data) 190{ 191 struct i40evf_adapter *adapter = netdev_priv(netdev); 192 193 if (I40E_DEBUG_USER & data) 194 adapter->hw.debug_mask = data; 195 adapter->msg_enable = data; 196} 197 198/** 199 * i40evf_get_drvinfo - Get driver info 200 * @netdev: network interface device structure 201 * @drvinfo: ethool driver info structure 202 * 203 * Returns information about the driver and device for display to the user. 204 **/ 205static void i40evf_get_drvinfo(struct net_device *netdev, 206 struct ethtool_drvinfo *drvinfo) 207{ 208 struct i40evf_adapter *adapter = netdev_priv(netdev); 209 210 strlcpy(drvinfo->driver, i40evf_driver_name, 32); 211 strlcpy(drvinfo->version, i40evf_driver_version, 32); 212 strlcpy(drvinfo->fw_version, "N/A", 4); 213 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); 214} 215 216/** 217 * i40evf_get_ringparam - Get ring parameters 218 * @netdev: network interface device structure 219 * @ring: ethtool ringparam structure 220 * 221 * Returns current ring parameters. TX and RX rings are reported separately, 222 * but the number of rings is not reported. 223 **/ 224static void i40evf_get_ringparam(struct net_device *netdev, 225 struct ethtool_ringparam *ring) 226{ 227 struct i40evf_adapter *adapter = netdev_priv(netdev); 228 229 ring->rx_max_pending = I40EVF_MAX_RXD; 230 ring->tx_max_pending = I40EVF_MAX_TXD; 231 ring->rx_pending = adapter->rx_desc_count; 232 ring->tx_pending = adapter->tx_desc_count; 233} 234 235/** 236 * i40evf_set_ringparam - Set ring parameters 237 * @netdev: network interface device structure 238 * @ring: ethtool ringparam structure 239 * 240 * Sets ring parameters. TX and RX rings are controlled separately, but the 241 * number of rings is not specified, so all rings get the same settings. 242 **/ 243static int i40evf_set_ringparam(struct net_device *netdev, 244 struct ethtool_ringparam *ring) 245{ 246 struct i40evf_adapter *adapter = netdev_priv(netdev); 247 u32 new_rx_count, new_tx_count; 248 249 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 250 return -EINVAL; 251 252 new_tx_count = clamp_t(u32, ring->tx_pending, 253 I40EVF_MIN_TXD, 254 I40EVF_MAX_TXD); 255 new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE); 256 257 new_rx_count = clamp_t(u32, ring->rx_pending, 258 I40EVF_MIN_RXD, 259 I40EVF_MAX_RXD); 260 new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE); 261 262 /* if nothing to do return success */ 263 if ((new_tx_count == adapter->tx_desc_count) && 264 (new_rx_count == adapter->rx_desc_count)) 265 return 0; 266 267 adapter->tx_desc_count = new_tx_count; 268 adapter->rx_desc_count = new_rx_count; 269 270 if (netif_running(netdev)) 271 i40evf_reinit_locked(adapter); 272 273 return 0; 274} 275 276/** 277 * i40evf_get_coalesce - Get interrupt coalescing settings 278 * @netdev: network interface device structure 279 * @ec: ethtool coalesce structure 280 * 281 * Returns current coalescing settings. This is referred to elsewhere in the 282 * driver as Interrupt Throttle Rate, as this is how the hardware describes 283 * this functionality. 284 **/ 285static int i40evf_get_coalesce(struct net_device *netdev, 286 struct ethtool_coalesce *ec) 287{ 288 struct i40evf_adapter *adapter = netdev_priv(netdev); 289 struct i40e_vsi *vsi = &adapter->vsi; 290 291 ec->tx_max_coalesced_frames = vsi->work_limit; 292 ec->rx_max_coalesced_frames = vsi->work_limit; 293 294 if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) 295 ec->use_adaptive_rx_coalesce = 1; 296 297 if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) 298 ec->use_adaptive_tx_coalesce = 1; 299 300 ec->rx_coalesce_usecs = vsi->rx_itr_setting & ~I40E_ITR_DYNAMIC; 301 ec->tx_coalesce_usecs = vsi->tx_itr_setting & ~I40E_ITR_DYNAMIC; 302 303 return 0; 304} 305 306/** 307 * i40evf_set_coalesce - Set interrupt coalescing settings 308 * @netdev: network interface device structure 309 * @ec: ethtool coalesce structure 310 * 311 * Change current coalescing settings. 312 **/ 313static int i40evf_set_coalesce(struct net_device *netdev, 314 struct ethtool_coalesce *ec) 315{ 316 struct i40evf_adapter *adapter = netdev_priv(netdev); 317 struct i40e_hw *hw = &adapter->hw; 318 struct i40e_vsi *vsi = &adapter->vsi; 319 struct i40e_q_vector *q_vector; 320 int i; 321 322 if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) 323 vsi->work_limit = ec->tx_max_coalesced_frames_irq; 324 325 if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && 326 (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) 327 vsi->rx_itr_setting = ec->rx_coalesce_usecs; 328 329 else 330 return -EINVAL; 331 332 if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && 333 (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) 334 vsi->tx_itr_setting = ec->tx_coalesce_usecs; 335 else if (ec->use_adaptive_tx_coalesce) 336 vsi->tx_itr_setting = (I40E_ITR_DYNAMIC | 337 ITR_REG_TO_USEC(I40E_ITR_RX_DEF)); 338 else 339 return -EINVAL; 340 341 if (ec->use_adaptive_rx_coalesce) 342 vsi->rx_itr_setting |= I40E_ITR_DYNAMIC; 343 else 344 vsi->rx_itr_setting &= ~I40E_ITR_DYNAMIC; 345 346 if (ec->use_adaptive_tx_coalesce) 347 vsi->tx_itr_setting |= I40E_ITR_DYNAMIC; 348 else 349 vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC; 350 351 for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) { 352 q_vector = adapter->q_vector[i]; 353 q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); 354 wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr); 355 q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting); 356 wr32(hw, I40E_VFINT_ITRN1(1, i), q_vector->tx.itr); 357 i40e_flush(hw); 358 } 359 360 return 0; 361} 362 363/** 364 * i40e_get_rss_hash_opts - Get RSS hash Input Set for each flow type 365 * @adapter: board private structure 366 * @cmd: ethtool rxnfc command 367 * 368 * Returns Success if the flow is supported, else Invalid Input. 369 **/ 370static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter, 371 struct ethtool_rxnfc *cmd) 372{ 373 struct i40e_hw *hw = &adapter->hw; 374 u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) | 375 ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32); 376 377 /* We always hash on IP src and dest addresses */ 378 cmd->data = RXH_IP_SRC | RXH_IP_DST; 379 380 switch (cmd->flow_type) { 381 case TCP_V4_FLOW: 382 if (hena & ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP)) 383 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 384 break; 385 case UDP_V4_FLOW: 386 if (hena & ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP)) 387 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 388 break; 389 390 case SCTP_V4_FLOW: 391 case AH_ESP_V4_FLOW: 392 case AH_V4_FLOW: 393 case ESP_V4_FLOW: 394 case IPV4_FLOW: 395 break; 396 397 case TCP_V6_FLOW: 398 if (hena & ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP)) 399 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 400 break; 401 case UDP_V6_FLOW: 402 if (hena & ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP)) 403 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 404 break; 405 406 case SCTP_V6_FLOW: 407 case AH_ESP_V6_FLOW: 408 case AH_V6_FLOW: 409 case ESP_V6_FLOW: 410 case IPV6_FLOW: 411 break; 412 default: 413 cmd->data = 0; 414 return -EINVAL; 415 } 416 417 return 0; 418} 419 420/** 421 * i40evf_get_rxnfc - command to get RX flow classification rules 422 * @netdev: network interface device structure 423 * @cmd: ethtool rxnfc command 424 * 425 * Returns Success if the command is supported. 426 **/ 427static int i40evf_get_rxnfc(struct net_device *netdev, 428 struct ethtool_rxnfc *cmd, 429 u32 *rule_locs) 430{ 431 struct i40evf_adapter *adapter = netdev_priv(netdev); 432 int ret = -EOPNOTSUPP; 433 434 switch (cmd->cmd) { 435 case ETHTOOL_GRXRINGS: 436 cmd->data = adapter->num_active_queues; 437 ret = 0; 438 break; 439 case ETHTOOL_GRXFH: 440 ret = i40evf_get_rss_hash_opts(adapter, cmd); 441 break; 442 default: 443 break; 444 } 445 446 return ret; 447} 448 449/** 450 * i40evf_set_rss_hash_opt - Enable/Disable flow types for RSS hash 451 * @adapter: board private structure 452 * @cmd: ethtool rxnfc command 453 * 454 * Returns Success if the flow input set is supported. 455 **/ 456static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, 457 struct ethtool_rxnfc *nfc) 458{ 459 struct i40e_hw *hw = &adapter->hw; 460 461 u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) | 462 ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32); 463 464 /* RSS does not support anything other than hashing 465 * to queues on src and dst IPs and ports 466 */ 467 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | 468 RXH_L4_B_0_1 | RXH_L4_B_2_3)) 469 return -EINVAL; 470 471 /* We need at least the IP SRC and DEST fields for hashing */ 472 if (!(nfc->data & RXH_IP_SRC) || 473 !(nfc->data & RXH_IP_DST)) 474 return -EINVAL; 475 476 switch (nfc->flow_type) { 477 case TCP_V4_FLOW: 478 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 479 case 0: 480 hena &= ~((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP); 481 break; 482 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 483 hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP); 484 break; 485 default: 486 return -EINVAL; 487 } 488 break; 489 case TCP_V6_FLOW: 490 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 491 case 0: 492 hena &= ~((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP); 493 break; 494 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 495 hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP); 496 break; 497 default: 498 return -EINVAL; 499 } 500 break; 501 case UDP_V4_FLOW: 502 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 503 case 0: 504 hena &= ~(((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | 505 ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4)); 506 break; 507 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 508 hena |= (((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | 509 ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4)); 510 break; 511 default: 512 return -EINVAL; 513 } 514 break; 515 case UDP_V6_FLOW: 516 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 517 case 0: 518 hena &= ~(((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | 519 ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6)); 520 break; 521 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 522 hena |= (((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | 523 ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6)); 524 break; 525 default: 526 return -EINVAL; 527 } 528 break; 529 case AH_ESP_V4_FLOW: 530 case AH_V4_FLOW: 531 case ESP_V4_FLOW: 532 case SCTP_V4_FLOW: 533 if ((nfc->data & RXH_L4_B_0_1) || 534 (nfc->data & RXH_L4_B_2_3)) 535 return -EINVAL; 536 hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER); 537 break; 538 case AH_ESP_V6_FLOW: 539 case AH_V6_FLOW: 540 case ESP_V6_FLOW: 541 case SCTP_V6_FLOW: 542 if ((nfc->data & RXH_L4_B_0_1) || 543 (nfc->data & RXH_L4_B_2_3)) 544 return -EINVAL; 545 hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER); 546 break; 547 case IPV4_FLOW: 548 hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | 549 ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4); 550 break; 551 case IPV6_FLOW: 552 hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | 553 ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6); 554 break; 555 default: 556 return -EINVAL; 557 } 558 559 wr32(hw, I40E_VFQF_HENA(0), (u32)hena); 560 wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); 561 i40e_flush(hw); 562 563 return 0; 564} 565 566/** 567 * i40evf_set_rxnfc - command to set RX flow classification rules 568 * @netdev: network interface device structure 569 * @cmd: ethtool rxnfc command 570 * 571 * Returns Success if the command is supported. 572 **/ 573static int i40evf_set_rxnfc(struct net_device *netdev, 574 struct ethtool_rxnfc *cmd) 575{ 576 struct i40evf_adapter *adapter = netdev_priv(netdev); 577 int ret = -EOPNOTSUPP; 578 579 switch (cmd->cmd) { 580 case ETHTOOL_SRXFH: 581 ret = i40evf_set_rss_hash_opt(adapter, cmd); 582 break; 583 default: 584 break; 585 } 586 587 return ret; 588} 589 590/** 591 * i40evf_get_channels: get the number of channels supported by the device 592 * @netdev: network interface device structure 593 * @ch: channel information structure 594 * 595 * For the purposes of our device, we only use combined channels, i.e. a tx/rx 596 * queue pair. Report one extra channel to match our "other" MSI-X vector. 597 **/ 598static void i40evf_get_channels(struct net_device *netdev, 599 struct ethtool_channels *ch) 600{ 601 struct i40evf_adapter *adapter = netdev_priv(netdev); 602 603 /* Report maximum channels */ 604 ch->max_combined = adapter->num_active_queues; 605 606 ch->max_other = NONQ_VECS; 607 ch->other_count = NONQ_VECS; 608 609 ch->combined_count = adapter->num_active_queues; 610} 611 612/** 613 * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size 614 * @netdev: network interface device structure 615 * 616 * Returns the table size. 617 **/ 618static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev) 619{ 620 return (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4; 621} 622 623/** 624 * i40evf_get_rxfh - get the rx flow hash indirection table 625 * @netdev: network interface device structure 626 * @indir: indirection table 627 * @key: hash key 628 * 629 * Reads the indirection table directly from the hardware. Always returns 0. 630 **/ 631static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 632 u8 *hfunc) 633{ 634 struct i40evf_adapter *adapter = netdev_priv(netdev); 635 struct i40e_hw *hw = &adapter->hw; 636 u32 hlut_val; 637 int i, j; 638 639 if (hfunc) 640 *hfunc = ETH_RSS_HASH_TOP; 641 if (!indir) 642 return 0; 643 644 if (indir) { 645 for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { 646 hlut_val = rd32(hw, I40E_VFQF_HLUT(i)); 647 indir[j++] = hlut_val & 0xff; 648 indir[j++] = (hlut_val >> 8) & 0xff; 649 indir[j++] = (hlut_val >> 16) & 0xff; 650 indir[j++] = (hlut_val >> 24) & 0xff; 651 } 652 } 653 return 0; 654} 655 656/** 657 * i40evf_set_rxfh - set the rx flow hash indirection table 658 * @netdev: network interface device structure 659 * @indir: indirection table 660 * @key: hash key 661 * 662 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise 663 * returns 0 after programming the table. 664 **/ 665static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir, 666 const u8 *key, const u8 hfunc) 667{ 668 struct i40evf_adapter *adapter = netdev_priv(netdev); 669 struct i40e_hw *hw = &adapter->hw; 670 u32 hlut_val; 671 int i, j; 672 673 /* We do not allow change in unsupported parameters */ 674 if (key || 675 (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) 676 return -EOPNOTSUPP; 677 if (!indir) 678 return 0; 679 680 for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { 681 hlut_val = indir[j++]; 682 hlut_val |= indir[j++] << 8; 683 hlut_val |= indir[j++] << 16; 684 hlut_val |= indir[j++] << 24; 685 wr32(hw, I40E_VFQF_HLUT(i), hlut_val); 686 } 687 688 return 0; 689} 690 691static const struct ethtool_ops i40evf_ethtool_ops = { 692 .get_settings = i40evf_get_settings, 693 .get_drvinfo = i40evf_get_drvinfo, 694 .get_link = ethtool_op_get_link, 695 .get_ringparam = i40evf_get_ringparam, 696 .set_ringparam = i40evf_set_ringparam, 697 .get_strings = i40evf_get_strings, 698 .get_ethtool_stats = i40evf_get_ethtool_stats, 699 .get_sset_count = i40evf_get_sset_count, 700 .get_msglevel = i40evf_get_msglevel, 701 .set_msglevel = i40evf_set_msglevel, 702 .get_coalesce = i40evf_get_coalesce, 703 .set_coalesce = i40evf_set_coalesce, 704 .get_rxnfc = i40evf_get_rxnfc, 705 .set_rxnfc = i40evf_set_rxnfc, 706 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size, 707 .get_rxfh = i40evf_get_rxfh, 708 .set_rxfh = i40evf_set_rxfh, 709 .get_channels = i40evf_get_channels, 710}; 711 712/** 713 * i40evf_set_ethtool_ops - Initialize ethtool ops struct 714 * @netdev: network interface device structure 715 * 716 * Sets ethtool ops struct in our netdev so that ethtool can call 717 * our functions. 718 **/ 719void i40evf_set_ethtool_ops(struct net_device *netdev) 720{ 721 netdev->ethtool_ops = &i40evf_ethtool_ops; 722} 723