linux/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
   4 * Copyright(c) 2013 - 2016 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        struct i40evf_adapter *adapter = netdev_priv(netdev);
  78
  79        ecmd->supported = 0;
  80        ecmd->autoneg = AUTONEG_DISABLE;
  81        ecmd->transceiver = XCVR_DUMMY1;
  82        ecmd->port = PORT_NONE;
  83        /* Set speed and duplex */
  84        switch (adapter->link_speed) {
  85        case I40E_LINK_SPEED_40GB:
  86                ethtool_cmd_speed_set(ecmd, SPEED_40000);
  87                break;
  88        case I40E_LINK_SPEED_20GB:
  89                ethtool_cmd_speed_set(ecmd, SPEED_20000);
  90                break;
  91        case I40E_LINK_SPEED_10GB:
  92                ethtool_cmd_speed_set(ecmd, SPEED_10000);
  93                break;
  94        case I40E_LINK_SPEED_1GB:
  95                ethtool_cmd_speed_set(ecmd, SPEED_1000);
  96                break;
  97        case I40E_LINK_SPEED_100MB:
  98                ethtool_cmd_speed_set(ecmd, SPEED_100);
  99                break;
 100        default:
 101                break;
 102        }
 103        ecmd->duplex = DUPLEX_FULL;
 104
 105        return 0;
 106}
 107
 108/**
 109 * i40evf_get_sset_count - Get length of string set
 110 * @netdev: network interface device structure
 111 * @sset: id of string set
 112 *
 113 * Reports size of string table. This driver only supports
 114 * strings for statistics.
 115 **/
 116static int i40evf_get_sset_count(struct net_device *netdev, int sset)
 117{
 118        if (sset == ETH_SS_STATS)
 119                return I40EVF_STATS_LEN(netdev);
 120        else
 121                return -EINVAL;
 122}
 123
 124/**
 125 * i40evf_get_ethtool_stats - report device statistics
 126 * @netdev: network interface device structure
 127 * @stats: ethtool statistics structure
 128 * @data: pointer to data buffer
 129 *
 130 * All statistics are added to the data buffer as an array of u64.
 131 **/
 132static void i40evf_get_ethtool_stats(struct net_device *netdev,
 133                                     struct ethtool_stats *stats, u64 *data)
 134{
 135        struct i40evf_adapter *adapter = netdev_priv(netdev);
 136        int i, j;
 137        char *p;
 138
 139        for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
 140                p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset;
 141                data[i] =  *(u64 *)p;
 142        }
 143        for (j = 0; j < adapter->num_active_queues; j++) {
 144                data[i++] = adapter->tx_rings[j].stats.packets;
 145                data[i++] = adapter->tx_rings[j].stats.bytes;
 146        }
 147        for (j = 0; j < adapter->num_active_queues; j++) {
 148                data[i++] = adapter->rx_rings[j].stats.packets;
 149                data[i++] = adapter->rx_rings[j].stats.bytes;
 150        }
 151}
 152
 153/**
 154 * i40evf_get_strings - Get string set
 155 * @netdev: network interface device structure
 156 * @sset: id of string set
 157 * @data: buffer for string data
 158 *
 159 * Builds stats string table.
 160 **/
 161static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
 162{
 163        struct i40evf_adapter *adapter = netdev_priv(netdev);
 164        u8 *p = data;
 165        int i;
 166
 167        if (sset == ETH_SS_STATS) {
 168                for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
 169                        memcpy(p, i40evf_gstrings_stats[i].stat_string,
 170                               ETH_GSTRING_LEN);
 171                        p += ETH_GSTRING_LEN;
 172                }
 173                for (i = 0; i < adapter->num_active_queues; i++) {
 174                        snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i);
 175                        p += ETH_GSTRING_LEN;
 176                        snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i);
 177                        p += ETH_GSTRING_LEN;
 178                }
 179                for (i = 0; i < adapter->num_active_queues; i++) {
 180                        snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i);
 181                        p += ETH_GSTRING_LEN;
 182                        snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
 183                        p += ETH_GSTRING_LEN;
 184                }
 185        }
 186}
 187
 188/**
 189 * i40evf_get_msglevel - Get debug message level
 190 * @netdev: network interface device structure
 191 *
 192 * Returns current debug message level.
 193 **/
 194static u32 i40evf_get_msglevel(struct net_device *netdev)
 195{
 196        struct i40evf_adapter *adapter = netdev_priv(netdev);
 197
 198        return adapter->msg_enable;
 199}
 200
 201/**
 202 * i40evf_set_msglevel - Set debug message level
 203 * @netdev: network interface device structure
 204 * @data: message level
 205 *
 206 * Set current debug message level. Higher values cause the driver to
 207 * be noisier.
 208 **/
 209static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
 210{
 211        struct i40evf_adapter *adapter = netdev_priv(netdev);
 212
 213        if (I40E_DEBUG_USER & data)
 214                adapter->hw.debug_mask = data;
 215        adapter->msg_enable = data;
 216}
 217
 218/**
 219 * i40evf_get_drvinfo - Get driver info
 220 * @netdev: network interface device structure
 221 * @drvinfo: ethool driver info structure
 222 *
 223 * Returns information about the driver and device for display to the user.
 224 **/
 225static void i40evf_get_drvinfo(struct net_device *netdev,
 226                               struct ethtool_drvinfo *drvinfo)
 227{
 228        struct i40evf_adapter *adapter = netdev_priv(netdev);
 229
 230        strlcpy(drvinfo->driver, i40evf_driver_name, 32);
 231        strlcpy(drvinfo->version, i40evf_driver_version, 32);
 232        strlcpy(drvinfo->fw_version, "N/A", 4);
 233        strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
 234}
 235
 236/**
 237 * i40evf_get_ringparam - Get ring parameters
 238 * @netdev: network interface device structure
 239 * @ring: ethtool ringparam structure
 240 *
 241 * Returns current ring parameters. TX and RX rings are reported separately,
 242 * but the number of rings is not reported.
 243 **/
 244static void i40evf_get_ringparam(struct net_device *netdev,
 245                                 struct ethtool_ringparam *ring)
 246{
 247        struct i40evf_adapter *adapter = netdev_priv(netdev);
 248
 249        ring->rx_max_pending = I40EVF_MAX_RXD;
 250        ring->tx_max_pending = I40EVF_MAX_TXD;
 251        ring->rx_pending = adapter->rx_desc_count;
 252        ring->tx_pending = adapter->tx_desc_count;
 253}
 254
 255/**
 256 * i40evf_set_ringparam - Set ring parameters
 257 * @netdev: network interface device structure
 258 * @ring: ethtool ringparam structure
 259 *
 260 * Sets ring parameters. TX and RX rings are controlled separately, but the
 261 * number of rings is not specified, so all rings get the same settings.
 262 **/
 263static int i40evf_set_ringparam(struct net_device *netdev,
 264                                struct ethtool_ringparam *ring)
 265{
 266        struct i40evf_adapter *adapter = netdev_priv(netdev);
 267        u32 new_rx_count, new_tx_count;
 268
 269        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 270                return -EINVAL;
 271
 272        new_tx_count = clamp_t(u32, ring->tx_pending,
 273                               I40EVF_MIN_TXD,
 274                               I40EVF_MAX_TXD);
 275        new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
 276
 277        new_rx_count = clamp_t(u32, ring->rx_pending,
 278                               I40EVF_MIN_RXD,
 279                               I40EVF_MAX_RXD);
 280        new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
 281
 282        /* if nothing to do return success */
 283        if ((new_tx_count == adapter->tx_desc_count) &&
 284            (new_rx_count == adapter->rx_desc_count))
 285                return 0;
 286
 287        adapter->tx_desc_count = new_tx_count;
 288        adapter->rx_desc_count = new_rx_count;
 289
 290        if (netif_running(netdev)) {
 291                adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
 292                schedule_work(&adapter->reset_task);
 293        }
 294
 295        return 0;
 296}
 297
 298/**
 299 * __i40evf_get_coalesce - get per-queue coalesce settings
 300 * @netdev: the netdev to check
 301 * @ec: ethtool coalesce data structure
 302 * @queue: which queue to pick
 303 *
 304 * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs
 305 * are per queue. If queue is <0 then we default to queue 0 as the
 306 * representative value.
 307 **/
 308static int __i40evf_get_coalesce(struct net_device *netdev,
 309                                 struct ethtool_coalesce *ec,
 310                                 int queue)
 311{
 312        struct i40evf_adapter *adapter = netdev_priv(netdev);
 313        struct i40e_vsi *vsi = &adapter->vsi;
 314        struct i40e_ring *rx_ring, *tx_ring;
 315
 316        ec->tx_max_coalesced_frames = vsi->work_limit;
 317        ec->rx_max_coalesced_frames = vsi->work_limit;
 318
 319        /* Rx and Tx usecs per queue value. If user doesn't specify the
 320         * queue, return queue 0's value to represent.
 321         */
 322        if (queue < 0)
 323                queue = 0;
 324        else if (queue >= adapter->num_active_queues)
 325                return -EINVAL;
 326
 327        rx_ring = &adapter->rx_rings[queue];
 328        tx_ring = &adapter->tx_rings[queue];
 329
 330        if (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))
 331                ec->use_adaptive_rx_coalesce = 1;
 332
 333        if (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))
 334                ec->use_adaptive_tx_coalesce = 1;
 335
 336        ec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;
 337        ec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;
 338
 339        return 0;
 340}
 341
 342/**
 343 * i40evf_get_coalesce - Get interrupt coalescing settings
 344 * @netdev: network interface device structure
 345 * @ec: ethtool coalesce structure
 346 *
 347 * Returns current coalescing settings. This is referred to elsewhere in the
 348 * driver as Interrupt Throttle Rate, as this is how the hardware describes
 349 * this functionality. Note that if per-queue settings have been modified this
 350 * only represents the settings of queue 0.
 351 **/
 352static int i40evf_get_coalesce(struct net_device *netdev,
 353                               struct ethtool_coalesce *ec)
 354{
 355        return __i40evf_get_coalesce(netdev, ec, -1);
 356}
 357
 358/**
 359 * i40evf_get_per_queue_coalesce - get coalesce values for specific queue
 360 * @netdev: netdev to read
 361 * @ec: coalesce settings from ethtool
 362 * @queue: the queue to read
 363 *
 364 * Read specific queue's coalesce settings.
 365 **/
 366static int i40evf_get_per_queue_coalesce(struct net_device *netdev,
 367                                         u32 queue,
 368                                         struct ethtool_coalesce *ec)
 369{
 370        return __i40evf_get_coalesce(netdev, ec, queue);
 371}
 372
 373/**
 374 * i40evf_set_itr_per_queue - set ITR values for specific queue
 375 * @vsi: the VSI to set values for
 376 * @ec: coalesce settings from ethtool
 377 * @queue: the queue to modify
 378 *
 379 * Change the ITR settings for a specific queue.
 380 **/
 381static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
 382                                     struct ethtool_coalesce *ec,
 383                                     int queue)
 384{
 385        struct i40e_vsi *vsi = &adapter->vsi;
 386        struct i40e_hw *hw = &adapter->hw;
 387        struct i40e_q_vector *q_vector;
 388        u16 vector;
 389
 390        adapter->rx_rings[queue].rx_itr_setting = ec->rx_coalesce_usecs;
 391        adapter->tx_rings[queue].tx_itr_setting = ec->tx_coalesce_usecs;
 392
 393        if (ec->use_adaptive_rx_coalesce)
 394                adapter->rx_rings[queue].rx_itr_setting |= I40E_ITR_DYNAMIC;
 395        else
 396                adapter->rx_rings[queue].rx_itr_setting &= ~I40E_ITR_DYNAMIC;
 397
 398        if (ec->use_adaptive_tx_coalesce)
 399                adapter->tx_rings[queue].tx_itr_setting |= I40E_ITR_DYNAMIC;
 400        else
 401                adapter->tx_rings[queue].tx_itr_setting &= ~I40E_ITR_DYNAMIC;
 402
 403        q_vector = adapter->rx_rings[queue].q_vector;
 404        q_vector->rx.itr = ITR_TO_REG(adapter->rx_rings[queue].rx_itr_setting);
 405        vector = vsi->base_vector + q_vector->v_idx;
 406        wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, vector - 1), q_vector->rx.itr);
 407
 408        q_vector = adapter->tx_rings[queue].q_vector;
 409        q_vector->tx.itr = ITR_TO_REG(adapter->tx_rings[queue].tx_itr_setting);
 410        vector = vsi->base_vector + q_vector->v_idx;
 411        wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, vector - 1), q_vector->tx.itr);
 412
 413        i40e_flush(hw);
 414}
 415
 416/**
 417 * __i40evf_set_coalesce - set coalesce settings for particular queue
 418 * @netdev: the netdev to change
 419 * @ec: ethtool coalesce settings
 420 * @queue: the queue to change
 421 *
 422 * Sets the coalesce settings for a particular queue.
 423 **/
 424static int __i40evf_set_coalesce(struct net_device *netdev,
 425                                 struct ethtool_coalesce *ec,
 426                                 int queue)
 427{
 428        struct i40evf_adapter *adapter = netdev_priv(netdev);
 429        struct i40e_vsi *vsi = &adapter->vsi;
 430        int i;
 431
 432        if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
 433                vsi->work_limit = ec->tx_max_coalesced_frames_irq;
 434
 435        if (ec->rx_coalesce_usecs == 0) {
 436                if (ec->use_adaptive_rx_coalesce)
 437                        netif_info(adapter, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n");
 438        } else if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
 439                   (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
 440                netif_info(adapter, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
 441                return -EINVAL;
 442        }
 443
 444        else
 445        if (ec->tx_coalesce_usecs == 0) {
 446                if (ec->use_adaptive_tx_coalesce)
 447                        netif_info(adapter, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n");
 448        } else if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
 449                   (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
 450                netif_info(adapter, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
 451                return -EINVAL;
 452        }
 453
 454        /* Rx and Tx usecs has per queue value. If user doesn't specify the
 455         * queue, apply to all queues.
 456         */
 457        if (queue < 0) {
 458                for (i = 0; i < adapter->num_active_queues; i++)
 459                        i40evf_set_itr_per_queue(adapter, ec, i);
 460        } else if (queue < adapter->num_active_queues) {
 461                i40evf_set_itr_per_queue(adapter, ec, queue);
 462        } else {
 463                netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
 464                           adapter->num_active_queues - 1);
 465                return -EINVAL;
 466        }
 467
 468        return 0;
 469}
 470
 471/**
 472 * i40evf_set_coalesce - Set interrupt coalescing settings
 473 * @netdev: network interface device structure
 474 * @ec: ethtool coalesce structure
 475 *
 476 * Change current coalescing settings for every queue.
 477 **/
 478static int i40evf_set_coalesce(struct net_device *netdev,
 479                               struct ethtool_coalesce *ec)
 480{
 481        return __i40evf_set_coalesce(netdev, ec, -1);
 482}
 483
 484/**
 485 * i40evf_set_per_queue_coalesce - set specific queue's coalesce settings
 486 * @netdev: the netdev to change
 487 * @ec: ethtool's coalesce settings
 488 * @queue: the queue to modify
 489 *
 490 * Modifies a specific queue's coalesce settings.
 491 */
 492static int i40evf_set_per_queue_coalesce(struct net_device *netdev,
 493                                         u32 queue,
 494                                         struct ethtool_coalesce *ec)
 495{
 496        return __i40evf_set_coalesce(netdev, ec, queue);
 497}
 498
 499/**
 500 * i40evf_get_rxnfc - command to get RX flow classification rules
 501 * @netdev: network interface device structure
 502 * @cmd: ethtool rxnfc command
 503 *
 504 * Returns Success if the command is supported.
 505 **/
 506static int i40evf_get_rxnfc(struct net_device *netdev,
 507                            struct ethtool_rxnfc *cmd,
 508                            u32 *rule_locs)
 509{
 510        struct i40evf_adapter *adapter = netdev_priv(netdev);
 511        int ret = -EOPNOTSUPP;
 512
 513        switch (cmd->cmd) {
 514        case ETHTOOL_GRXRINGS:
 515                cmd->data = adapter->num_active_queues;
 516                ret = 0;
 517                break;
 518        case ETHTOOL_GRXFH:
 519                netdev_info(netdev,
 520                            "RSS hash info is not available to vf, use pf.\n");
 521                break;
 522        default:
 523                break;
 524        }
 525
 526        return ret;
 527}
 528/**
 529 * i40evf_get_channels: get the number of channels supported by the device
 530 * @netdev: network interface device structure
 531 * @ch: channel information structure
 532 *
 533 * For the purposes of our device, we only use combined channels, i.e. a tx/rx
 534 * queue pair. Report one extra channel to match our "other" MSI-X vector.
 535 **/
 536static void i40evf_get_channels(struct net_device *netdev,
 537                                struct ethtool_channels *ch)
 538{
 539        struct i40evf_adapter *adapter = netdev_priv(netdev);
 540
 541        /* Report maximum channels */
 542        ch->max_combined = adapter->num_active_queues;
 543
 544        ch->max_other = NONQ_VECS;
 545        ch->other_count = NONQ_VECS;
 546
 547        ch->combined_count = adapter->num_active_queues;
 548}
 549
 550/**
 551 * i40evf_get_rxfh_key_size - get the RSS hash key size
 552 * @netdev: network interface device structure
 553 *
 554 * Returns the table size.
 555 **/
 556static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
 557{
 558        struct i40evf_adapter *adapter = netdev_priv(netdev);
 559
 560        return adapter->rss_key_size;
 561}
 562
 563/**
 564 * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
 565 * @netdev: network interface device structure
 566 *
 567 * Returns the table size.
 568 **/
 569static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
 570{
 571        struct i40evf_adapter *adapter = netdev_priv(netdev);
 572
 573        return adapter->rss_lut_size;
 574}
 575
 576/**
 577 * i40evf_get_rxfh - get the rx flow hash indirection table
 578 * @netdev: network interface device structure
 579 * @indir: indirection table
 580 * @key: hash key
 581 *
 582 * Reads the indirection table directly from the hardware. Always returns 0.
 583 **/
 584static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
 585                           u8 *hfunc)
 586{
 587        struct i40evf_adapter *adapter = netdev_priv(netdev);
 588        u16 i;
 589
 590        if (hfunc)
 591                *hfunc = ETH_RSS_HASH_TOP;
 592        if (!indir)
 593                return 0;
 594
 595        memcpy(key, adapter->rss_key, adapter->rss_key_size);
 596
 597        /* Each 32 bits pointed by 'indir' is stored with a lut entry */
 598        for (i = 0; i < adapter->rss_lut_size; i++)
 599                indir[i] = (u32)adapter->rss_lut[i];
 600
 601        return 0;
 602}
 603
 604/**
 605 * i40evf_set_rxfh - set the rx flow hash indirection table
 606 * @netdev: network interface device structure
 607 * @indir: indirection table
 608 * @key: hash key
 609 *
 610 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
 611 * returns 0 after programming the table.
 612 **/
 613static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
 614                           const u8 *key, const u8 hfunc)
 615{
 616        struct i40evf_adapter *adapter = netdev_priv(netdev);
 617        u16 i;
 618
 619        /* We do not allow change in unsupported parameters */
 620        if (key ||
 621            (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
 622                return -EOPNOTSUPP;
 623        if (!indir)
 624                return 0;
 625
 626        if (key) {
 627                memcpy(adapter->rss_key, key, adapter->rss_key_size);
 628        }
 629
 630        /* Each 32 bits pointed by 'indir' is stored with a lut entry */
 631        for (i = 0; i < adapter->rss_lut_size; i++)
 632                adapter->rss_lut[i] = (u8)(indir[i]);
 633
 634        return i40evf_config_rss(adapter);
 635}
 636
 637static const struct ethtool_ops i40evf_ethtool_ops = {
 638        .get_settings           = i40evf_get_settings,
 639        .get_drvinfo            = i40evf_get_drvinfo,
 640        .get_link               = ethtool_op_get_link,
 641        .get_ringparam          = i40evf_get_ringparam,
 642        .set_ringparam          = i40evf_set_ringparam,
 643        .get_strings            = i40evf_get_strings,
 644        .get_ethtool_stats      = i40evf_get_ethtool_stats,
 645        .get_sset_count         = i40evf_get_sset_count,
 646        .get_msglevel           = i40evf_get_msglevel,
 647        .set_msglevel           = i40evf_set_msglevel,
 648        .get_coalesce           = i40evf_get_coalesce,
 649        .set_coalesce           = i40evf_set_coalesce,
 650        .get_per_queue_coalesce = i40evf_get_per_queue_coalesce,
 651        .set_per_queue_coalesce = i40evf_set_per_queue_coalesce,
 652        .get_rxnfc              = i40evf_get_rxnfc,
 653        .get_rxfh_indir_size    = i40evf_get_rxfh_indir_size,
 654        .get_rxfh               = i40evf_get_rxfh,
 655        .set_rxfh               = i40evf_set_rxfh,
 656        .get_channels           = i40evf_get_channels,
 657        .get_rxfh_key_size      = i40evf_get_rxfh_key_size,
 658};
 659
 660/**
 661 * i40evf_set_ethtool_ops - Initialize ethtool ops struct
 662 * @netdev: network interface device structure
 663 *
 664 * Sets ethtool ops struct in our netdev so that ethtool can call
 665 * our functions.
 666 **/
 667void i40evf_set_ethtool_ops(struct net_device *netdev)
 668{
 669        netdev->ethtool_ops = &i40evf_ethtool_ops;
 670}
 671