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