linux/drivers/net/igbvf/ethtool.c
<<
>>
Prefs
   1/*******************************************************************************
   2
   3  Intel(R) 82576 Virtual Function Linux driver
   4  Copyright(c) 2009 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 u32 igbvf_get_link(struct net_device *netdev)
 114{
 115        return netif_carrier_ok(netdev);
 116}
 117
 118static int igbvf_set_settings(struct net_device *netdev,
 119                              struct ethtool_cmd *ecmd)
 120{
 121        return -EOPNOTSUPP;
 122}
 123
 124static void igbvf_get_pauseparam(struct net_device *netdev,
 125                                 struct ethtool_pauseparam *pause)
 126{
 127        return;
 128}
 129
 130static int igbvf_set_pauseparam(struct net_device *netdev,
 131                                struct ethtool_pauseparam *pause)
 132{
 133        return -EOPNOTSUPP;
 134}
 135
 136static u32 igbvf_get_rx_csum(struct net_device *netdev)
 137{
 138        struct igbvf_adapter *adapter = netdev_priv(netdev);
 139        return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
 140}
 141
 142static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
 143{
 144        struct igbvf_adapter *adapter = netdev_priv(netdev);
 145
 146        if (data)
 147                adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
 148        else
 149                adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
 150
 151        return 0;
 152}
 153
 154static u32 igbvf_get_tx_csum(struct net_device *netdev)
 155{
 156        return ((netdev->features & NETIF_F_IP_CSUM) != 0);
 157}
 158
 159static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
 160{
 161        if (data)
 162                netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 163        else
 164                netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 165        return 0;
 166}
 167
 168static int igbvf_set_tso(struct net_device *netdev, u32 data)
 169{
 170        struct igbvf_adapter *adapter = netdev_priv(netdev);
 171
 172        if (data) {
 173                netdev->features |= NETIF_F_TSO;
 174                netdev->features |= NETIF_F_TSO6;
 175        } else {
 176                netdev->features &= ~NETIF_F_TSO;
 177                netdev->features &= ~NETIF_F_TSO6;
 178        }
 179
 180        dev_info(&adapter->pdev->dev, "TSO is %s\n",
 181                 data ? "Enabled" : "Disabled");
 182        return 0;
 183}
 184
 185static u32 igbvf_get_msglevel(struct net_device *netdev)
 186{
 187        struct igbvf_adapter *adapter = netdev_priv(netdev);
 188        return adapter->msg_enable;
 189}
 190
 191static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
 192{
 193        struct igbvf_adapter *adapter = netdev_priv(netdev);
 194        adapter->msg_enable = data;
 195}
 196
 197static int igbvf_get_regs_len(struct net_device *netdev)
 198{
 199#define IGBVF_REGS_LEN 8
 200        return IGBVF_REGS_LEN * sizeof(u32);
 201}
 202
 203static void igbvf_get_regs(struct net_device *netdev,
 204                           struct ethtool_regs *regs, void *p)
 205{
 206        struct igbvf_adapter *adapter = netdev_priv(netdev);
 207        struct e1000_hw *hw = &adapter->hw;
 208        u32 *regs_buff = p;
 209        u8 revision_id;
 210
 211        memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
 212
 213        pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
 214
 215        regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
 216
 217        regs_buff[0] = er32(CTRL);
 218        regs_buff[1] = er32(STATUS);
 219
 220        regs_buff[2] = er32(RDLEN(0));
 221        regs_buff[3] = er32(RDH(0));
 222        regs_buff[4] = er32(RDT(0));
 223
 224        regs_buff[5] = er32(TDLEN(0));
 225        regs_buff[6] = er32(TDH(0));
 226        regs_buff[7] = er32(TDT(0));
 227}
 228
 229static int igbvf_get_eeprom_len(struct net_device *netdev)
 230{
 231        return 0;
 232}
 233
 234static int igbvf_get_eeprom(struct net_device *netdev,
 235                            struct ethtool_eeprom *eeprom, u8 *bytes)
 236{
 237        return -EOPNOTSUPP;
 238}
 239
 240static int igbvf_set_eeprom(struct net_device *netdev,
 241                            struct ethtool_eeprom *eeprom, u8 *bytes)
 242{
 243        return -EOPNOTSUPP;
 244}
 245
 246static void igbvf_get_drvinfo(struct net_device *netdev,
 247                              struct ethtool_drvinfo *drvinfo)
 248{
 249        struct igbvf_adapter *adapter = netdev_priv(netdev);
 250        char firmware_version[32] = "N/A";
 251
 252        strncpy(drvinfo->driver,  igbvf_driver_name, 32);
 253        strncpy(drvinfo->version, igbvf_driver_version, 32);
 254        strncpy(drvinfo->fw_version, firmware_version, 32);
 255        strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
 256        drvinfo->regdump_len = igbvf_get_regs_len(netdev);
 257        drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
 258}
 259
 260static void igbvf_get_ringparam(struct net_device *netdev,
 261                                struct ethtool_ringparam *ring)
 262{
 263        struct igbvf_adapter *adapter = netdev_priv(netdev);
 264        struct igbvf_ring *tx_ring = adapter->tx_ring;
 265        struct igbvf_ring *rx_ring = adapter->rx_ring;
 266
 267        ring->rx_max_pending = IGBVF_MAX_RXD;
 268        ring->tx_max_pending = IGBVF_MAX_TXD;
 269        ring->rx_mini_max_pending = 0;
 270        ring->rx_jumbo_max_pending = 0;
 271        ring->rx_pending = rx_ring->count;
 272        ring->tx_pending = tx_ring->count;
 273        ring->rx_mini_pending = 0;
 274        ring->rx_jumbo_pending = 0;
 275}
 276
 277static int igbvf_set_ringparam(struct net_device *netdev,
 278                               struct ethtool_ringparam *ring)
 279{
 280        struct igbvf_adapter *adapter = netdev_priv(netdev);
 281        struct igbvf_ring *temp_ring;
 282        int err = 0;
 283        u32 new_rx_count, new_tx_count;
 284
 285        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 286                return -EINVAL;
 287
 288        new_rx_count = max(ring->rx_pending, (u32)IGBVF_MIN_RXD);
 289        new_rx_count = min(new_rx_count, (u32)IGBVF_MAX_RXD);
 290        new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
 291
 292        new_tx_count = max(ring->tx_pending, (u32)IGBVF_MIN_TXD);
 293        new_tx_count = min(new_tx_count, (u32)IGBVF_MAX_TXD);
 294        new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
 295
 296        if ((new_tx_count == adapter->tx_ring->count) &&
 297            (new_rx_count == adapter->rx_ring->count)) {
 298                /* nothing to do */
 299                return 0;
 300        }
 301
 302        while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
 303                msleep(1);
 304
 305        if (!netif_running(adapter->netdev)) {
 306                adapter->tx_ring->count = new_tx_count;
 307                adapter->rx_ring->count = new_rx_count;
 308                goto clear_reset;
 309        }
 310
 311        temp_ring = vmalloc(sizeof(struct igbvf_ring));
 312        if (!temp_ring) {
 313                err = -ENOMEM;
 314                goto clear_reset;
 315        }
 316
 317        igbvf_down(adapter);
 318
 319        /*
 320         * We can't just free everything and then setup again,
 321         * because the ISRs in MSI-X mode get passed pointers
 322         * to the tx and rx ring structs.
 323         */
 324        if (new_tx_count != adapter->tx_ring->count) {
 325                memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
 326
 327                temp_ring->count = new_tx_count;
 328                err = igbvf_setup_tx_resources(adapter, temp_ring);
 329                if (err)
 330                        goto err_setup;
 331
 332                igbvf_free_tx_resources(adapter->tx_ring);
 333
 334                memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
 335        }
 336
 337        if (new_rx_count != adapter->rx_ring->count) {
 338                memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
 339
 340                temp_ring->count = new_rx_count;
 341                err = igbvf_setup_rx_resources(adapter, temp_ring);
 342                if (err)
 343                        goto err_setup;
 344
 345                igbvf_free_rx_resources(adapter->rx_ring);
 346
 347                memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
 348        }
 349err_setup:
 350        igbvf_up(adapter);
 351        vfree(temp_ring);
 352clear_reset:
 353        clear_bit(__IGBVF_RESETTING, &adapter->state);
 354        return err;
 355}
 356
 357static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
 358{
 359        struct e1000_hw *hw = &adapter->hw;
 360        *data = 0;
 361
 362        hw->mac.ops.check_for_link(hw);
 363
 364        if (!(er32(STATUS) & E1000_STATUS_LU))
 365                *data = 1;
 366
 367        return *data;
 368}
 369
 370static int igbvf_get_self_test_count(struct net_device *netdev)
 371{
 372        return IGBVF_TEST_LEN;
 373}
 374
 375static int igbvf_get_stats_count(struct net_device *netdev)
 376{
 377        return IGBVF_GLOBAL_STATS_LEN;
 378}
 379
 380static void igbvf_diag_test(struct net_device *netdev,
 381                            struct ethtool_test *eth_test, u64 *data)
 382{
 383        struct igbvf_adapter *adapter = netdev_priv(netdev);
 384
 385        set_bit(__IGBVF_TESTING, &adapter->state);
 386
 387        /*
 388         * Link test performed before hardware reset so autoneg doesn't
 389         * interfere with test result
 390         */
 391        if (igbvf_link_test(adapter, &data[0]))
 392                eth_test->flags |= ETH_TEST_FL_FAILED;
 393
 394        clear_bit(__IGBVF_TESTING, &adapter->state);
 395        msleep_interruptible(4 * 1000);
 396}
 397
 398static void igbvf_get_wol(struct net_device *netdev,
 399                          struct ethtool_wolinfo *wol)
 400{
 401        wol->supported = 0;
 402        wol->wolopts = 0;
 403
 404        return;
 405}
 406
 407static int igbvf_set_wol(struct net_device *netdev,
 408                         struct ethtool_wolinfo *wol)
 409{
 410        return -EOPNOTSUPP;
 411}
 412
 413static int igbvf_phys_id(struct net_device *netdev, u32 data)
 414{
 415        return 0;
 416}
 417
 418static int igbvf_get_coalesce(struct net_device *netdev,
 419                              struct ethtool_coalesce *ec)
 420{
 421        struct igbvf_adapter *adapter = netdev_priv(netdev);
 422
 423        if (adapter->itr_setting <= 3)
 424                ec->rx_coalesce_usecs = adapter->itr_setting;
 425        else
 426                ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
 427
 428        return 0;
 429}
 430
 431static int igbvf_set_coalesce(struct net_device *netdev,
 432                              struct ethtool_coalesce *ec)
 433{
 434        struct igbvf_adapter *adapter = netdev_priv(netdev);
 435        struct e1000_hw *hw = &adapter->hw;
 436
 437        if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) ||
 438            ((ec->rx_coalesce_usecs > 3) &&
 439             (ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) ||
 440            (ec->rx_coalesce_usecs == 2))
 441                return -EINVAL;
 442
 443        /* convert to rate of irq's per second */
 444        if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
 445                adapter->itr = IGBVF_START_ITR;
 446                adapter->itr_setting = ec->rx_coalesce_usecs;
 447        } else {
 448                adapter->itr = ec->rx_coalesce_usecs << 2;
 449                adapter->itr_setting = adapter->itr;
 450        }
 451
 452        writel(adapter->itr,
 453               hw->hw_addr + adapter->rx_ring[0].itr_register);
 454
 455        return 0;
 456}
 457
 458static int igbvf_nway_reset(struct net_device *netdev)
 459{
 460        struct igbvf_adapter *adapter = netdev_priv(netdev);
 461        if (netif_running(netdev))
 462                igbvf_reinit_locked(adapter);
 463        return 0;
 464}
 465
 466
 467static void igbvf_get_ethtool_stats(struct net_device *netdev,
 468                                    struct ethtool_stats *stats,
 469                                    u64 *data)
 470{
 471        struct igbvf_adapter *adapter = netdev_priv(netdev);
 472        int i;
 473
 474        igbvf_update_stats(adapter);
 475        for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
 476                char *p = (char *)adapter +
 477                          igbvf_gstrings_stats[i].stat_offset;
 478                char *b = (char *)adapter +
 479                          igbvf_gstrings_stats[i].base_stat_offset;
 480                data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
 481                            sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
 482                            (*(u32 *)p - *(u32 *)b));
 483        }
 484
 485}
 486
 487static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
 488                              u8 *data)
 489{
 490        u8 *p = data;
 491        int i;
 492
 493        switch (stringset) {
 494        case ETH_SS_TEST:
 495                memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
 496                break;
 497        case ETH_SS_STATS:
 498                for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
 499                        memcpy(p, igbvf_gstrings_stats[i].stat_string,
 500                               ETH_GSTRING_LEN);
 501                        p += ETH_GSTRING_LEN;
 502                }
 503                break;
 504        }
 505}
 506
 507static const struct ethtool_ops igbvf_ethtool_ops = {
 508        .get_settings           = igbvf_get_settings,
 509        .set_settings           = igbvf_set_settings,
 510        .get_drvinfo            = igbvf_get_drvinfo,
 511        .get_regs_len           = igbvf_get_regs_len,
 512        .get_regs               = igbvf_get_regs,
 513        .get_wol                = igbvf_get_wol,
 514        .set_wol                = igbvf_set_wol,
 515        .get_msglevel           = igbvf_get_msglevel,
 516        .set_msglevel           = igbvf_set_msglevel,
 517        .nway_reset             = igbvf_nway_reset,
 518        .get_link               = igbvf_get_link,
 519        .get_eeprom_len         = igbvf_get_eeprom_len,
 520        .get_eeprom             = igbvf_get_eeprom,
 521        .set_eeprom             = igbvf_set_eeprom,
 522        .get_ringparam          = igbvf_get_ringparam,
 523        .set_ringparam          = igbvf_set_ringparam,
 524        .get_pauseparam         = igbvf_get_pauseparam,
 525        .set_pauseparam         = igbvf_set_pauseparam,
 526        .get_rx_csum            = igbvf_get_rx_csum,
 527        .set_rx_csum            = igbvf_set_rx_csum,
 528        .get_tx_csum            = igbvf_get_tx_csum,
 529        .set_tx_csum            = igbvf_set_tx_csum,
 530        .get_sg                 = ethtool_op_get_sg,
 531        .set_sg                 = ethtool_op_set_sg,
 532        .get_tso                = ethtool_op_get_tso,
 533        .set_tso                = igbvf_set_tso,
 534        .self_test              = igbvf_diag_test,
 535        .get_strings            = igbvf_get_strings,
 536        .phys_id                = igbvf_phys_id,
 537        .get_ethtool_stats      = igbvf_get_ethtool_stats,
 538        .self_test_count        = igbvf_get_self_test_count,
 539        .get_stats_count        = igbvf_get_stats_count,
 540        .get_coalesce           = igbvf_get_coalesce,
 541        .set_coalesce           = igbvf_set_coalesce,
 542};
 543
 544void igbvf_set_ethtool_ops(struct net_device *netdev)
 545{
 546        /* have to "undeclare" const on this struct to remove warnings */
 547        SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
 548}
 549