linux/drivers/net/igbvf/ethtool.c
<<
>>
Prefs
   1/*******************************************************************************
   2
   3  Intel(R) 82576 Virtual Function Linux driver
   4  Copyright(c) 2009 - 2010 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 with
  16  this program; if not, write to the Free Software Foundation, Inc.,
  17  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  18
  19  The full GNU General Public License is included in this distribution in
  20  the file called "COPYING".
  21
  22  Contact Information:
  23  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  24  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  25
  26*******************************************************************************/
  27
  28/* ethtool support for igbvf */
  29
  30#include <linux/netdevice.h>
  31#include <linux/ethtool.h>
  32#include <linux/pci.h>
  33#include <linux/vmalloc.h>
  34#include <linux/delay.h>
  35
  36#include "igbvf.h"
  37#include <linux/if_vlan.h>
  38
  39
  40struct igbvf_stats {
  41        char stat_string[ETH_GSTRING_LEN];
  42        int sizeof_stat;
  43        int stat_offset;
  44        int base_stat_offset;
  45};
  46
  47#define IGBVF_STAT(current, base) \
  48                sizeof(((struct igbvf_adapter *)0)->current), \
  49                offsetof(struct igbvf_adapter, current), \
  50                offsetof(struct igbvf_adapter, base)
  51
  52static const struct igbvf_stats igbvf_gstrings_stats[] = {
  53        { "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
  54        { "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
  55        { "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
  56        { "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
  57        { "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
  58        { "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
  59        { "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
  60        { "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
  61        { "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) },
  62        { "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
  63        { "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
  64        { "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
  65        { "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
  66};
  67
  68#define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
  69
  70static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
  71        "Link test   (on/offline)"
  72};
  73
  74#define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
  75
  76static int igbvf_get_settings(struct net_device *netdev,
  77                              struct ethtool_cmd *ecmd)
  78{
  79        struct igbvf_adapter *adapter = netdev_priv(netdev);
  80        struct e1000_hw *hw = &adapter->hw;
  81        u32 status;
  82
  83        ecmd->supported   = SUPPORTED_1000baseT_Full;
  84
  85        ecmd->advertising = ADVERTISED_1000baseT_Full;
  86
  87        ecmd->port = -1;
  88        ecmd->transceiver = XCVR_DUMMY1;
  89
  90        status = er32(STATUS);
  91        if (status & E1000_STATUS_LU) {
  92                if (status & E1000_STATUS_SPEED_1000)
  93                        ecmd->speed = 1000;
  94                else if (status & E1000_STATUS_SPEED_100)
  95                        ecmd->speed = 100;
  96                else
  97                        ecmd->speed = 10;
  98
  99                if (status & E1000_STATUS_FD)
 100                        ecmd->duplex = DUPLEX_FULL;
 101                else
 102                        ecmd->duplex = DUPLEX_HALF;
 103        } else {
 104                ecmd->speed = -1;
 105                ecmd->duplex = -1;
 106        }
 107
 108        ecmd->autoneg = AUTONEG_DISABLE;
 109
 110        return 0;
 111}
 112
 113static int igbvf_set_settings(struct net_device *netdev,
 114                              struct ethtool_cmd *ecmd)
 115{
 116        return -EOPNOTSUPP;
 117}
 118
 119static void igbvf_get_pauseparam(struct net_device *netdev,
 120                                 struct ethtool_pauseparam *pause)
 121{
 122        return;
 123}
 124
 125static int igbvf_set_pauseparam(struct net_device *netdev,
 126                                struct ethtool_pauseparam *pause)
 127{
 128        return -EOPNOTSUPP;
 129}
 130
 131static u32 igbvf_get_rx_csum(struct net_device *netdev)
 132{
 133        struct igbvf_adapter *adapter = netdev_priv(netdev);
 134        return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
 135}
 136
 137static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
 138{
 139        struct igbvf_adapter *adapter = netdev_priv(netdev);
 140
 141        if (data)
 142                adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
 143        else
 144                adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
 145
 146        return 0;
 147}
 148
 149static u32 igbvf_get_tx_csum(struct net_device *netdev)
 150{
 151        return (netdev->features & NETIF_F_IP_CSUM) != 0;
 152}
 153
 154static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
 155{
 156        if (data)
 157                netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 158        else
 159                netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 160        return 0;
 161}
 162
 163static int igbvf_set_tso(struct net_device *netdev, u32 data)
 164{
 165        struct igbvf_adapter *adapter = netdev_priv(netdev);
 166
 167        if (data) {
 168                netdev->features |= NETIF_F_TSO;
 169                netdev->features |= NETIF_F_TSO6;
 170        } else {
 171                netdev->features &= ~NETIF_F_TSO;
 172                netdev->features &= ~NETIF_F_TSO6;
 173        }
 174
 175        dev_info(&adapter->pdev->dev, "TSO is %s\n",
 176                 data ? "Enabled" : "Disabled");
 177        return 0;
 178}
 179
 180static u32 igbvf_get_msglevel(struct net_device *netdev)
 181{
 182        struct igbvf_adapter *adapter = netdev_priv(netdev);
 183        return adapter->msg_enable;
 184}
 185
 186static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
 187{
 188        struct igbvf_adapter *adapter = netdev_priv(netdev);
 189        adapter->msg_enable = data;
 190}
 191
 192static int igbvf_get_regs_len(struct net_device *netdev)
 193{
 194#define IGBVF_REGS_LEN 8
 195        return IGBVF_REGS_LEN * sizeof(u32);
 196}
 197
 198static void igbvf_get_regs(struct net_device *netdev,
 199                           struct ethtool_regs *regs, void *p)
 200{
 201        struct igbvf_adapter *adapter = netdev_priv(netdev);
 202        struct e1000_hw *hw = &adapter->hw;
 203        u32 *regs_buff = p;
 204        u8 revision_id;
 205
 206        memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
 207
 208        pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
 209
 210        regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
 211
 212        regs_buff[0] = er32(CTRL);
 213        regs_buff[1] = er32(STATUS);
 214
 215        regs_buff[2] = er32(RDLEN(0));
 216        regs_buff[3] = er32(RDH(0));
 217        regs_buff[4] = er32(RDT(0));
 218
 219        regs_buff[5] = er32(TDLEN(0));
 220        regs_buff[6] = er32(TDH(0));
 221        regs_buff[7] = er32(TDT(0));
 222}
 223
 224static int igbvf_get_eeprom_len(struct net_device *netdev)
 225{
 226        return 0;
 227}
 228
 229static int igbvf_get_eeprom(struct net_device *netdev,
 230                            struct ethtool_eeprom *eeprom, u8 *bytes)
 231{
 232        return -EOPNOTSUPP;
 233}
 234
 235static int igbvf_set_eeprom(struct net_device *netdev,
 236                            struct ethtool_eeprom *eeprom, u8 *bytes)
 237{
 238        return -EOPNOTSUPP;
 239}
 240
 241static void igbvf_get_drvinfo(struct net_device *netdev,
 242                              struct ethtool_drvinfo *drvinfo)
 243{
 244        struct igbvf_adapter *adapter = netdev_priv(netdev);
 245        char firmware_version[32] = "N/A";
 246
 247        strncpy(drvinfo->driver,  igbvf_driver_name, 32);
 248        strncpy(drvinfo->version, igbvf_driver_version, 32);
 249        strncpy(drvinfo->fw_version, firmware_version, 32);
 250        strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
 251        drvinfo->regdump_len = igbvf_get_regs_len(netdev);
 252        drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
 253}
 254
 255static void igbvf_get_ringparam(struct net_device *netdev,
 256                                struct ethtool_ringparam *ring)
 257{
 258        struct igbvf_adapter *adapter = netdev_priv(netdev);
 259        struct igbvf_ring *tx_ring = adapter->tx_ring;
 260        struct igbvf_ring *rx_ring = adapter->rx_ring;
 261
 262        ring->rx_max_pending = IGBVF_MAX_RXD;
 263        ring->tx_max_pending = IGBVF_MAX_TXD;
 264        ring->rx_mini_max_pending = 0;
 265        ring->rx_jumbo_max_pending = 0;
 266        ring->rx_pending = rx_ring->count;
 267        ring->tx_pending = tx_ring->count;
 268        ring->rx_mini_pending = 0;
 269        ring->rx_jumbo_pending = 0;
 270}
 271
 272static int igbvf_set_ringparam(struct net_device *netdev,
 273                               struct ethtool_ringparam *ring)
 274{
 275        struct igbvf_adapter *adapter = netdev_priv(netdev);
 276        struct igbvf_ring *temp_ring;
 277        int err = 0;
 278        u32 new_rx_count, new_tx_count;
 279
 280        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 281                return -EINVAL;
 282
 283        new_rx_count = max(ring->rx_pending, (u32)IGBVF_MIN_RXD);
 284        new_rx_count = min(new_rx_count, (u32)IGBVF_MAX_RXD);
 285        new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
 286
 287        new_tx_count = max(ring->tx_pending, (u32)IGBVF_MIN_TXD);
 288        new_tx_count = min(new_tx_count, (u32)IGBVF_MAX_TXD);
 289        new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
 290
 291        if ((new_tx_count == adapter->tx_ring->count) &&
 292            (new_rx_count == adapter->rx_ring->count)) {
 293                /* nothing to do */
 294                return 0;
 295        }
 296
 297        while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
 298                msleep(1);
 299
 300        if (!netif_running(adapter->netdev)) {
 301                adapter->tx_ring->count = new_tx_count;
 302                adapter->rx_ring->count = new_rx_count;
 303                goto clear_reset;
 304        }
 305
 306        temp_ring = vmalloc(sizeof(struct igbvf_ring));
 307        if (!temp_ring) {
 308                err = -ENOMEM;
 309                goto clear_reset;
 310        }
 311
 312        igbvf_down(adapter);
 313
 314        /*
 315         * We can't just free everything and then setup again,
 316         * because the ISRs in MSI-X mode get passed pointers
 317         * to the tx and rx ring structs.
 318         */
 319        if (new_tx_count != adapter->tx_ring->count) {
 320                memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
 321
 322                temp_ring->count = new_tx_count;
 323                err = igbvf_setup_tx_resources(adapter, temp_ring);
 324                if (err)
 325                        goto err_setup;
 326
 327                igbvf_free_tx_resources(adapter->tx_ring);
 328
 329                memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
 330        }
 331
 332        if (new_rx_count != adapter->rx_ring->count) {
 333                memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
 334
 335                temp_ring->count = new_rx_count;
 336                err = igbvf_setup_rx_resources(adapter, temp_ring);
 337                if (err)
 338                        goto err_setup;
 339
 340                igbvf_free_rx_resources(adapter->rx_ring);
 341
 342                memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
 343        }
 344err_setup:
 345        igbvf_up(adapter);
 346        vfree(temp_ring);
 347clear_reset:
 348        clear_bit(__IGBVF_RESETTING, &adapter->state);
 349        return err;
 350}
 351
 352static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
 353{
 354        struct e1000_hw *hw = &adapter->hw;
 355        *data = 0;
 356
 357        hw->mac.ops.check_for_link(hw);
 358
 359        if (!(er32(STATUS) & E1000_STATUS_LU))
 360                *data = 1;
 361
 362        return *data;
 363}
 364
 365static void igbvf_diag_test(struct net_device *netdev,
 366                            struct ethtool_test *eth_test, u64 *data)
 367{
 368        struct igbvf_adapter *adapter = netdev_priv(netdev);
 369
 370        set_bit(__IGBVF_TESTING, &adapter->state);
 371
 372        /*
 373         * Link test performed before hardware reset so autoneg doesn't
 374         * interfere with test result
 375         */
 376        if (igbvf_link_test(adapter, &data[0]))
 377                eth_test->flags |= ETH_TEST_FL_FAILED;
 378
 379        clear_bit(__IGBVF_TESTING, &adapter->state);
 380        msleep_interruptible(4 * 1000);
 381}
 382
 383static void igbvf_get_wol(struct net_device *netdev,
 384                          struct ethtool_wolinfo *wol)
 385{
 386        wol->supported = 0;
 387        wol->wolopts = 0;
 388}
 389
 390static int igbvf_set_wol(struct net_device *netdev,
 391                         struct ethtool_wolinfo *wol)
 392{
 393        return -EOPNOTSUPP;
 394}
 395
 396static int igbvf_phys_id(struct net_device *netdev, u32 data)
 397{
 398        return 0;
 399}
 400
 401static int igbvf_get_coalesce(struct net_device *netdev,
 402                              struct ethtool_coalesce *ec)
 403{
 404        struct igbvf_adapter *adapter = netdev_priv(netdev);
 405
 406        if (adapter->itr_setting <= 3)
 407                ec->rx_coalesce_usecs = adapter->itr_setting;
 408        else
 409                ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
 410
 411        return 0;
 412}
 413
 414static int igbvf_set_coalesce(struct net_device *netdev,
 415                              struct ethtool_coalesce *ec)
 416{
 417        struct igbvf_adapter *adapter = netdev_priv(netdev);
 418        struct e1000_hw *hw = &adapter->hw;
 419
 420        if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) ||
 421            ((ec->rx_coalesce_usecs > 3) &&
 422             (ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) ||
 423            (ec->rx_coalesce_usecs == 2))
 424                return -EINVAL;
 425
 426        /* convert to rate of irq's per second */
 427        if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
 428                adapter->itr = IGBVF_START_ITR;
 429                adapter->itr_setting = ec->rx_coalesce_usecs;
 430        } else {
 431                adapter->itr = ec->rx_coalesce_usecs << 2;
 432                adapter->itr_setting = adapter->itr;
 433        }
 434
 435        writel(adapter->itr,
 436               hw->hw_addr + adapter->rx_ring[0].itr_register);
 437
 438        return 0;
 439}
 440
 441static int igbvf_nway_reset(struct net_device *netdev)
 442{
 443        struct igbvf_adapter *adapter = netdev_priv(netdev);
 444        if (netif_running(netdev))
 445                igbvf_reinit_locked(adapter);
 446        return 0;
 447}
 448
 449
 450static void igbvf_get_ethtool_stats(struct net_device *netdev,
 451                                    struct ethtool_stats *stats,
 452                                    u64 *data)
 453{
 454        struct igbvf_adapter *adapter = netdev_priv(netdev);
 455        int i;
 456
 457        igbvf_update_stats(adapter);
 458        for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
 459                char *p = (char *)adapter +
 460                          igbvf_gstrings_stats[i].stat_offset;
 461                char *b = (char *)adapter +
 462                          igbvf_gstrings_stats[i].base_stat_offset;
 463                data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
 464                            sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
 465                            (*(u32 *)p - *(u32 *)b));
 466        }
 467
 468}
 469
 470static int igbvf_get_sset_count(struct net_device *dev, int stringset)
 471{
 472        switch(stringset) {
 473        case ETH_SS_TEST:
 474                return IGBVF_TEST_LEN;
 475        case ETH_SS_STATS:
 476                return IGBVF_GLOBAL_STATS_LEN;
 477        default:
 478                return -EINVAL;
 479        }
 480}
 481
 482static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
 483                              u8 *data)
 484{
 485        u8 *p = data;
 486        int i;
 487
 488        switch (stringset) {
 489        case ETH_SS_TEST:
 490                memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
 491                break;
 492        case ETH_SS_STATS:
 493                for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
 494                        memcpy(p, igbvf_gstrings_stats[i].stat_string,
 495                               ETH_GSTRING_LEN);
 496                        p += ETH_GSTRING_LEN;
 497                }
 498                break;
 499        }
 500}
 501
 502static const struct ethtool_ops igbvf_ethtool_ops = {
 503        .get_settings           = igbvf_get_settings,
 504        .set_settings           = igbvf_set_settings,
 505        .get_drvinfo            = igbvf_get_drvinfo,
 506        .get_regs_len           = igbvf_get_regs_len,
 507        .get_regs               = igbvf_get_regs,
 508        .get_wol                = igbvf_get_wol,
 509        .set_wol                = igbvf_set_wol,
 510        .get_msglevel           = igbvf_get_msglevel,
 511        .set_msglevel           = igbvf_set_msglevel,
 512        .nway_reset             = igbvf_nway_reset,
 513        .get_link               = ethtool_op_get_link,
 514        .get_eeprom_len         = igbvf_get_eeprom_len,
 515        .get_eeprom             = igbvf_get_eeprom,
 516        .set_eeprom             = igbvf_set_eeprom,
 517        .get_ringparam          = igbvf_get_ringparam,
 518        .set_ringparam          = igbvf_set_ringparam,
 519        .get_pauseparam         = igbvf_get_pauseparam,
 520        .set_pauseparam         = igbvf_set_pauseparam,
 521        .get_rx_csum            = igbvf_get_rx_csum,
 522        .set_rx_csum            = igbvf_set_rx_csum,
 523        .get_tx_csum            = igbvf_get_tx_csum,
 524        .set_tx_csum            = igbvf_set_tx_csum,
 525        .get_sg                 = ethtool_op_get_sg,
 526        .set_sg                 = ethtool_op_set_sg,
 527        .get_tso                = ethtool_op_get_tso,
 528        .set_tso                = igbvf_set_tso,
 529        .self_test              = igbvf_diag_test,
 530        .get_sset_count         = igbvf_get_sset_count,
 531        .get_strings            = igbvf_get_strings,
 532        .phys_id                = igbvf_phys_id,
 533        .get_ethtool_stats      = igbvf_get_ethtool_stats,
 534        .get_coalesce           = igbvf_get_coalesce,
 535        .set_coalesce           = igbvf_set_coalesce,
 536};
 537
 538void igbvf_set_ethtool_ops(struct net_device *netdev)
 539{
 540        /* have to "undeclare" const on this struct to remove warnings */
 541        SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
 542}
 543