linux/drivers/net/ixgb/ixgb_ethtool.c
<<
>>
Prefs
   1/*******************************************************************************
   2
   3  Intel PRO/10GbE Linux driver
   4  Copyright(c) 1999 - 2008 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  Linux NICS <linux.nics@intel.com>
  24  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  25  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  26
  27*******************************************************************************/
  28
  29/* ethtool support for ixgb */
  30
  31#include "ixgb.h"
  32
  33#include <asm/uaccess.h>
  34
  35#define IXGB_ALL_RAR_ENTRIES 16
  36
  37struct ixgb_stats {
  38        char stat_string[ETH_GSTRING_LEN];
  39        int sizeof_stat;
  40        int stat_offset;
  41};
  42
  43#define IXGB_STAT(m) FIELD_SIZEOF(struct ixgb_adapter, m), \
  44                      offsetof(struct ixgb_adapter, m)
  45static struct ixgb_stats ixgb_gstrings_stats[] = {
  46        {"rx_packets", IXGB_STAT(net_stats.rx_packets)},
  47        {"tx_packets", IXGB_STAT(net_stats.tx_packets)},
  48        {"rx_bytes", IXGB_STAT(net_stats.rx_bytes)},
  49        {"tx_bytes", IXGB_STAT(net_stats.tx_bytes)},
  50        {"rx_errors", IXGB_STAT(net_stats.rx_errors)},
  51        {"tx_errors", IXGB_STAT(net_stats.tx_errors)},
  52        {"rx_dropped", IXGB_STAT(net_stats.rx_dropped)},
  53        {"tx_dropped", IXGB_STAT(net_stats.tx_dropped)},
  54        {"multicast", IXGB_STAT(net_stats.multicast)},
  55        {"collisions", IXGB_STAT(net_stats.collisions)},
  56
  57/*      { "rx_length_errors", IXGB_STAT(net_stats.rx_length_errors) },  */
  58        {"rx_over_errors", IXGB_STAT(net_stats.rx_over_errors)},
  59        {"rx_crc_errors", IXGB_STAT(net_stats.rx_crc_errors)},
  60        {"rx_frame_errors", IXGB_STAT(net_stats.rx_frame_errors)},
  61        {"rx_no_buffer_count", IXGB_STAT(stats.rnbc)},
  62        {"rx_fifo_errors", IXGB_STAT(net_stats.rx_fifo_errors)},
  63        {"rx_missed_errors", IXGB_STAT(net_stats.rx_missed_errors)},
  64        {"tx_aborted_errors", IXGB_STAT(net_stats.tx_aborted_errors)},
  65        {"tx_carrier_errors", IXGB_STAT(net_stats.tx_carrier_errors)},
  66        {"tx_fifo_errors", IXGB_STAT(net_stats.tx_fifo_errors)},
  67        {"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)},
  68        {"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
  69        {"tx_deferred_ok", IXGB_STAT(stats.dc)},
  70        {"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
  71        {"tx_restart_queue", IXGB_STAT(restart_queue) },
  72        {"rx_long_length_errors", IXGB_STAT(stats.roc)},
  73        {"rx_short_length_errors", IXGB_STAT(stats.ruc)},
  74        {"tx_tcp_seg_good", IXGB_STAT(stats.tsctc)},
  75        {"tx_tcp_seg_failed", IXGB_STAT(stats.tsctfc)},
  76        {"rx_flow_control_xon", IXGB_STAT(stats.xonrxc)},
  77        {"rx_flow_control_xoff", IXGB_STAT(stats.xoffrxc)},
  78        {"tx_flow_control_xon", IXGB_STAT(stats.xontxc)},
  79        {"tx_flow_control_xoff", IXGB_STAT(stats.xofftxc)},
  80        {"rx_csum_offload_good", IXGB_STAT(hw_csum_rx_good)},
  81        {"rx_csum_offload_errors", IXGB_STAT(hw_csum_rx_error)},
  82        {"tx_csum_offload_good", IXGB_STAT(hw_csum_tx_good)},
  83        {"tx_csum_offload_errors", IXGB_STAT(hw_csum_tx_error)}
  84};
  85
  86#define IXGB_STATS_LEN  ARRAY_SIZE(ixgb_gstrings_stats)
  87
  88static int
  89ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
  90{
  91        struct ixgb_adapter *adapter = netdev_priv(netdev);
  92
  93        ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
  94        ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
  95        ecmd->port = PORT_FIBRE;
  96        ecmd->transceiver = XCVR_EXTERNAL;
  97
  98        if (netif_carrier_ok(adapter->netdev)) {
  99                ecmd->speed = SPEED_10000;
 100                ecmd->duplex = DUPLEX_FULL;
 101        } else {
 102                ecmd->speed = -1;
 103                ecmd->duplex = -1;
 104        }
 105
 106        ecmd->autoneg = AUTONEG_DISABLE;
 107        return 0;
 108}
 109
 110static void ixgb_set_speed_duplex(struct net_device *netdev)
 111{
 112        struct ixgb_adapter *adapter = netdev_priv(netdev);
 113        /* be optimistic about our link, since we were up before */
 114        adapter->link_speed = 10000;
 115        adapter->link_duplex = FULL_DUPLEX;
 116        netif_carrier_on(netdev);
 117        netif_wake_queue(netdev);
 118}
 119
 120static int
 121ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 122{
 123        struct ixgb_adapter *adapter = netdev_priv(netdev);
 124
 125        if (ecmd->autoneg == AUTONEG_ENABLE ||
 126           ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
 127                return -EINVAL;
 128
 129        if (netif_running(adapter->netdev)) {
 130                ixgb_down(adapter, true);
 131                ixgb_reset(adapter);
 132                ixgb_up(adapter);
 133                ixgb_set_speed_duplex(netdev);
 134        } else
 135                ixgb_reset(adapter);
 136
 137        return 0;
 138}
 139
 140static void
 141ixgb_get_pauseparam(struct net_device *netdev,
 142                         struct ethtool_pauseparam *pause)
 143{
 144        struct ixgb_adapter *adapter = netdev_priv(netdev);
 145        struct ixgb_hw *hw = &adapter->hw;
 146
 147        pause->autoneg = AUTONEG_DISABLE;
 148
 149        if (hw->fc.type == ixgb_fc_rx_pause)
 150                pause->rx_pause = 1;
 151        else if (hw->fc.type == ixgb_fc_tx_pause)
 152                pause->tx_pause = 1;
 153        else if (hw->fc.type == ixgb_fc_full) {
 154                pause->rx_pause = 1;
 155                pause->tx_pause = 1;
 156        }
 157}
 158
 159static int
 160ixgb_set_pauseparam(struct net_device *netdev,
 161                         struct ethtool_pauseparam *pause)
 162{
 163        struct ixgb_adapter *adapter = netdev_priv(netdev);
 164        struct ixgb_hw *hw = &adapter->hw;
 165
 166        if (pause->autoneg == AUTONEG_ENABLE)
 167                return -EINVAL;
 168
 169        if (pause->rx_pause && pause->tx_pause)
 170                hw->fc.type = ixgb_fc_full;
 171        else if (pause->rx_pause && !pause->tx_pause)
 172                hw->fc.type = ixgb_fc_rx_pause;
 173        else if (!pause->rx_pause && pause->tx_pause)
 174                hw->fc.type = ixgb_fc_tx_pause;
 175        else if (!pause->rx_pause && !pause->tx_pause)
 176                hw->fc.type = ixgb_fc_none;
 177
 178        if (netif_running(adapter->netdev)) {
 179                ixgb_down(adapter, true);
 180                ixgb_up(adapter);
 181                ixgb_set_speed_duplex(netdev);
 182        } else
 183                ixgb_reset(adapter);
 184
 185        return 0;
 186}
 187
 188static u32
 189ixgb_get_rx_csum(struct net_device *netdev)
 190{
 191        struct ixgb_adapter *adapter = netdev_priv(netdev);
 192
 193        return adapter->rx_csum;
 194}
 195
 196static int
 197ixgb_set_rx_csum(struct net_device *netdev, u32 data)
 198{
 199        struct ixgb_adapter *adapter = netdev_priv(netdev);
 200
 201        adapter->rx_csum = data;
 202
 203        if (netif_running(netdev)) {
 204                ixgb_down(adapter, true);
 205                ixgb_up(adapter);
 206                ixgb_set_speed_duplex(netdev);
 207        } else
 208                ixgb_reset(adapter);
 209        return 0;
 210}
 211
 212static u32
 213ixgb_get_tx_csum(struct net_device *netdev)
 214{
 215        return (netdev->features & NETIF_F_HW_CSUM) != 0;
 216}
 217
 218static int
 219ixgb_set_tx_csum(struct net_device *netdev, u32 data)
 220{
 221        if (data)
 222                netdev->features |= NETIF_F_HW_CSUM;
 223        else
 224                netdev->features &= ~NETIF_F_HW_CSUM;
 225
 226        return 0;
 227}
 228
 229static int
 230ixgb_set_tso(struct net_device *netdev, u32 data)
 231{
 232        if (data)
 233                netdev->features |= NETIF_F_TSO;
 234        else
 235                netdev->features &= ~NETIF_F_TSO;
 236        return 0;
 237}
 238
 239static u32
 240ixgb_get_msglevel(struct net_device *netdev)
 241{
 242        struct ixgb_adapter *adapter = netdev_priv(netdev);
 243        return adapter->msg_enable;
 244}
 245
 246static void
 247ixgb_set_msglevel(struct net_device *netdev, u32 data)
 248{
 249        struct ixgb_adapter *adapter = netdev_priv(netdev);
 250        adapter->msg_enable = data;
 251}
 252#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
 253
 254static int
 255ixgb_get_regs_len(struct net_device *netdev)
 256{
 257#define IXGB_REG_DUMP_LEN  136*sizeof(u32)
 258        return IXGB_REG_DUMP_LEN;
 259}
 260
 261static void
 262ixgb_get_regs(struct net_device *netdev,
 263                   struct ethtool_regs *regs, void *p)
 264{
 265        struct ixgb_adapter *adapter = netdev_priv(netdev);
 266        struct ixgb_hw *hw = &adapter->hw;
 267        u32 *reg = p;
 268        u32 *reg_start = reg;
 269        u8 i;
 270
 271        /* the 1 (one) below indicates an attempt at versioning, if the
 272         * interface in ethtool or the driver changes, this 1 should be
 273         * incremented */
 274        regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
 275
 276        /* General Registers */
 277        *reg++ = IXGB_READ_REG(hw, CTRL0);      /*   0 */
 278        *reg++ = IXGB_READ_REG(hw, CTRL1);      /*   1 */
 279        *reg++ = IXGB_READ_REG(hw, STATUS);     /*   2 */
 280        *reg++ = IXGB_READ_REG(hw, EECD);       /*   3 */
 281        *reg++ = IXGB_READ_REG(hw, MFS);        /*   4 */
 282
 283        /* Interrupt */
 284        *reg++ = IXGB_READ_REG(hw, ICR);        /*   5 */
 285        *reg++ = IXGB_READ_REG(hw, ICS);        /*   6 */
 286        *reg++ = IXGB_READ_REG(hw, IMS);        /*   7 */
 287        *reg++ = IXGB_READ_REG(hw, IMC);        /*   8 */
 288
 289        /* Receive */
 290        *reg++ = IXGB_READ_REG(hw, RCTL);       /*   9 */
 291        *reg++ = IXGB_READ_REG(hw, FCRTL);      /*  10 */
 292        *reg++ = IXGB_READ_REG(hw, FCRTH);      /*  11 */
 293        *reg++ = IXGB_READ_REG(hw, RDBAL);      /*  12 */
 294        *reg++ = IXGB_READ_REG(hw, RDBAH);      /*  13 */
 295        *reg++ = IXGB_READ_REG(hw, RDLEN);      /*  14 */
 296        *reg++ = IXGB_READ_REG(hw, RDH);        /*  15 */
 297        *reg++ = IXGB_READ_REG(hw, RDT);        /*  16 */
 298        *reg++ = IXGB_READ_REG(hw, RDTR);       /*  17 */
 299        *reg++ = IXGB_READ_REG(hw, RXDCTL);     /*  18 */
 300        *reg++ = IXGB_READ_REG(hw, RAIDC);      /*  19 */
 301        *reg++ = IXGB_READ_REG(hw, RXCSUM);     /*  20 */
 302
 303        /* there are 16 RAR entries in hardware, we only use 3 */
 304        for (i = 0; i < IXGB_ALL_RAR_ENTRIES; i++) {
 305                *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
 306                *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
 307        }
 308
 309        /* Transmit */
 310        *reg++ = IXGB_READ_REG(hw, TCTL);       /*  53 */
 311        *reg++ = IXGB_READ_REG(hw, TDBAL);      /*  54 */
 312        *reg++ = IXGB_READ_REG(hw, TDBAH);      /*  55 */
 313        *reg++ = IXGB_READ_REG(hw, TDLEN);      /*  56 */
 314        *reg++ = IXGB_READ_REG(hw, TDH);        /*  57 */
 315        *reg++ = IXGB_READ_REG(hw, TDT);        /*  58 */
 316        *reg++ = IXGB_READ_REG(hw, TIDV);       /*  59 */
 317        *reg++ = IXGB_READ_REG(hw, TXDCTL);     /*  60 */
 318        *reg++ = IXGB_READ_REG(hw, TSPMT);      /*  61 */
 319        *reg++ = IXGB_READ_REG(hw, PAP);        /*  62 */
 320
 321        /* Physical */
 322        *reg++ = IXGB_READ_REG(hw, PCSC1);      /*  63 */
 323        *reg++ = IXGB_READ_REG(hw, PCSC2);      /*  64 */
 324        *reg++ = IXGB_READ_REG(hw, PCSS1);      /*  65 */
 325        *reg++ = IXGB_READ_REG(hw, PCSS2);      /*  66 */
 326        *reg++ = IXGB_READ_REG(hw, XPCSS);      /*  67 */
 327        *reg++ = IXGB_READ_REG(hw, UCCR);       /*  68 */
 328        *reg++ = IXGB_READ_REG(hw, XPCSTC);     /*  69 */
 329        *reg++ = IXGB_READ_REG(hw, MACA);       /*  70 */
 330        *reg++ = IXGB_READ_REG(hw, APAE);       /*  71 */
 331        *reg++ = IXGB_READ_REG(hw, ARD);        /*  72 */
 332        *reg++ = IXGB_READ_REG(hw, AIS);        /*  73 */
 333        *reg++ = IXGB_READ_REG(hw, MSCA);       /*  74 */
 334        *reg++ = IXGB_READ_REG(hw, MSRWD);      /*  75 */
 335
 336        /* Statistics */
 337        *reg++ = IXGB_GET_STAT(adapter, tprl);  /*  76 */
 338        *reg++ = IXGB_GET_STAT(adapter, tprh);  /*  77 */
 339        *reg++ = IXGB_GET_STAT(adapter, gprcl); /*  78 */
 340        *reg++ = IXGB_GET_STAT(adapter, gprch); /*  79 */
 341        *reg++ = IXGB_GET_STAT(adapter, bprcl); /*  80 */
 342        *reg++ = IXGB_GET_STAT(adapter, bprch); /*  81 */
 343        *reg++ = IXGB_GET_STAT(adapter, mprcl); /*  82 */
 344        *reg++ = IXGB_GET_STAT(adapter, mprch); /*  83 */
 345        *reg++ = IXGB_GET_STAT(adapter, uprcl); /*  84 */
 346        *reg++ = IXGB_GET_STAT(adapter, uprch); /*  85 */
 347        *reg++ = IXGB_GET_STAT(adapter, vprcl); /*  86 */
 348        *reg++ = IXGB_GET_STAT(adapter, vprch); /*  87 */
 349        *reg++ = IXGB_GET_STAT(adapter, jprcl); /*  88 */
 350        *reg++ = IXGB_GET_STAT(adapter, jprch); /*  89 */
 351        *reg++ = IXGB_GET_STAT(adapter, gorcl); /*  90 */
 352        *reg++ = IXGB_GET_STAT(adapter, gorch); /*  91 */
 353        *reg++ = IXGB_GET_STAT(adapter, torl);  /*  92 */
 354        *reg++ = IXGB_GET_STAT(adapter, torh);  /*  93 */
 355        *reg++ = IXGB_GET_STAT(adapter, rnbc);  /*  94 */
 356        *reg++ = IXGB_GET_STAT(adapter, ruc);   /*  95 */
 357        *reg++ = IXGB_GET_STAT(adapter, roc);   /*  96 */
 358        *reg++ = IXGB_GET_STAT(adapter, rlec);  /*  97 */
 359        *reg++ = IXGB_GET_STAT(adapter, crcerrs);       /*  98 */
 360        *reg++ = IXGB_GET_STAT(adapter, icbc);  /*  99 */
 361        *reg++ = IXGB_GET_STAT(adapter, ecbc);  /* 100 */
 362        *reg++ = IXGB_GET_STAT(adapter, mpc);   /* 101 */
 363        *reg++ = IXGB_GET_STAT(adapter, tptl);  /* 102 */
 364        *reg++ = IXGB_GET_STAT(adapter, tpth);  /* 103 */
 365        *reg++ = IXGB_GET_STAT(adapter, gptcl); /* 104 */
 366        *reg++ = IXGB_GET_STAT(adapter, gptch); /* 105 */
 367        *reg++ = IXGB_GET_STAT(adapter, bptcl); /* 106 */
 368        *reg++ = IXGB_GET_STAT(adapter, bptch); /* 107 */
 369        *reg++ = IXGB_GET_STAT(adapter, mptcl); /* 108 */
 370        *reg++ = IXGB_GET_STAT(adapter, mptch); /* 109 */
 371        *reg++ = IXGB_GET_STAT(adapter, uptcl); /* 110 */
 372        *reg++ = IXGB_GET_STAT(adapter, uptch); /* 111 */
 373        *reg++ = IXGB_GET_STAT(adapter, vptcl); /* 112 */
 374        *reg++ = IXGB_GET_STAT(adapter, vptch); /* 113 */
 375        *reg++ = IXGB_GET_STAT(adapter, jptcl); /* 114 */
 376        *reg++ = IXGB_GET_STAT(adapter, jptch); /* 115 */
 377        *reg++ = IXGB_GET_STAT(adapter, gotcl); /* 116 */
 378        *reg++ = IXGB_GET_STAT(adapter, gotch); /* 117 */
 379        *reg++ = IXGB_GET_STAT(adapter, totl);  /* 118 */
 380        *reg++ = IXGB_GET_STAT(adapter, toth);  /* 119 */
 381        *reg++ = IXGB_GET_STAT(adapter, dc);    /* 120 */
 382        *reg++ = IXGB_GET_STAT(adapter, plt64c);        /* 121 */
 383        *reg++ = IXGB_GET_STAT(adapter, tsctc); /* 122 */
 384        *reg++ = IXGB_GET_STAT(adapter, tsctfc);        /* 123 */
 385        *reg++ = IXGB_GET_STAT(adapter, ibic);  /* 124 */
 386        *reg++ = IXGB_GET_STAT(adapter, rfc);   /* 125 */
 387        *reg++ = IXGB_GET_STAT(adapter, lfc);   /* 126 */
 388        *reg++ = IXGB_GET_STAT(adapter, pfrc);  /* 127 */
 389        *reg++ = IXGB_GET_STAT(adapter, pftc);  /* 128 */
 390        *reg++ = IXGB_GET_STAT(adapter, mcfrc); /* 129 */
 391        *reg++ = IXGB_GET_STAT(adapter, mcftc); /* 130 */
 392        *reg++ = IXGB_GET_STAT(adapter, xonrxc);        /* 131 */
 393        *reg++ = IXGB_GET_STAT(adapter, xontxc);        /* 132 */
 394        *reg++ = IXGB_GET_STAT(adapter, xoffrxc);       /* 133 */
 395        *reg++ = IXGB_GET_STAT(adapter, xofftxc);       /* 134 */
 396        *reg++ = IXGB_GET_STAT(adapter, rjc);   /* 135 */
 397
 398        regs->len = (reg - reg_start) * sizeof(u32);
 399}
 400
 401static int
 402ixgb_get_eeprom_len(struct net_device *netdev)
 403{
 404        /* return size in bytes */
 405        return (IXGB_EEPROM_SIZE << 1);
 406}
 407
 408static int
 409ixgb_get_eeprom(struct net_device *netdev,
 410                  struct ethtool_eeprom *eeprom, u8 *bytes)
 411{
 412        struct ixgb_adapter *adapter = netdev_priv(netdev);
 413        struct ixgb_hw *hw = &adapter->hw;
 414        __le16 *eeprom_buff;
 415        int i, max_len, first_word, last_word;
 416        int ret_val = 0;
 417
 418        if (eeprom->len == 0) {
 419                ret_val = -EINVAL;
 420                goto geeprom_error;
 421        }
 422
 423        eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 424
 425        max_len = ixgb_get_eeprom_len(netdev);
 426
 427        if (eeprom->offset > eeprom->offset + eeprom->len) {
 428                ret_val = -EINVAL;
 429                goto geeprom_error;
 430        }
 431
 432        if ((eeprom->offset + eeprom->len) > max_len)
 433                eeprom->len = (max_len - eeprom->offset);
 434
 435        first_word = eeprom->offset >> 1;
 436        last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 437
 438        eeprom_buff = kmalloc(sizeof(__le16) *
 439                        (last_word - first_word + 1), GFP_KERNEL);
 440        if (!eeprom_buff)
 441                return -ENOMEM;
 442
 443        /* note the eeprom was good because the driver loaded */
 444        for (i = 0; i <= (last_word - first_word); i++)
 445                eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
 446
 447        memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
 448        kfree(eeprom_buff);
 449
 450geeprom_error:
 451        return ret_val;
 452}
 453
 454static int
 455ixgb_set_eeprom(struct net_device *netdev,
 456                  struct ethtool_eeprom *eeprom, u8 *bytes)
 457{
 458        struct ixgb_adapter *adapter = netdev_priv(netdev);
 459        struct ixgb_hw *hw = &adapter->hw;
 460        u16 *eeprom_buff;
 461        void *ptr;
 462        int max_len, first_word, last_word;
 463        u16 i;
 464
 465        if (eeprom->len == 0)
 466                return -EINVAL;
 467
 468        if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
 469                return -EFAULT;
 470
 471        max_len = ixgb_get_eeprom_len(netdev);
 472
 473        if (eeprom->offset > eeprom->offset + eeprom->len)
 474                return -EINVAL;
 475
 476        if ((eeprom->offset + eeprom->len) > max_len)
 477                eeprom->len = (max_len - eeprom->offset);
 478
 479        first_word = eeprom->offset >> 1;
 480        last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 481        eeprom_buff = kmalloc(max_len, GFP_KERNEL);
 482        if (!eeprom_buff)
 483                return -ENOMEM;
 484
 485        ptr = (void *)eeprom_buff;
 486
 487        if (eeprom->offset & 1) {
 488                /* need read/modify/write of first changed EEPROM word */
 489                /* only the second byte of the word is being modified */
 490                eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
 491                ptr++;
 492        }
 493        if ((eeprom->offset + eeprom->len) & 1) {
 494                /* need read/modify/write of last changed EEPROM word */
 495                /* only the first byte of the word is being modified */
 496                eeprom_buff[last_word - first_word]
 497                        = ixgb_read_eeprom(hw, last_word);
 498        }
 499
 500        memcpy(ptr, bytes, eeprom->len);
 501        for (i = 0; i <= (last_word - first_word); i++)
 502                ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
 503
 504        /* Update the checksum over the first part of the EEPROM if needed */
 505        if (first_word <= EEPROM_CHECKSUM_REG)
 506                ixgb_update_eeprom_checksum(hw);
 507
 508        kfree(eeprom_buff);
 509        return 0;
 510}
 511
 512static void
 513ixgb_get_drvinfo(struct net_device *netdev,
 514                   struct ethtool_drvinfo *drvinfo)
 515{
 516        struct ixgb_adapter *adapter = netdev_priv(netdev);
 517
 518        strncpy(drvinfo->driver,  ixgb_driver_name, 32);
 519        strncpy(drvinfo->version, ixgb_driver_version, 32);
 520        strncpy(drvinfo->fw_version, "N/A", 32);
 521        strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
 522        drvinfo->n_stats = IXGB_STATS_LEN;
 523        drvinfo->regdump_len = ixgb_get_regs_len(netdev);
 524        drvinfo->eedump_len = ixgb_get_eeprom_len(netdev);
 525}
 526
 527static void
 528ixgb_get_ringparam(struct net_device *netdev,
 529                struct ethtool_ringparam *ring)
 530{
 531        struct ixgb_adapter *adapter = netdev_priv(netdev);
 532        struct ixgb_desc_ring *txdr = &adapter->tx_ring;
 533        struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
 534
 535        ring->rx_max_pending = MAX_RXD;
 536        ring->tx_max_pending = MAX_TXD;
 537        ring->rx_mini_max_pending = 0;
 538        ring->rx_jumbo_max_pending = 0;
 539        ring->rx_pending = rxdr->count;
 540        ring->tx_pending = txdr->count;
 541        ring->rx_mini_pending = 0;
 542        ring->rx_jumbo_pending = 0;
 543}
 544
 545static int
 546ixgb_set_ringparam(struct net_device *netdev,
 547                struct ethtool_ringparam *ring)
 548{
 549        struct ixgb_adapter *adapter = netdev_priv(netdev);
 550        struct ixgb_desc_ring *txdr = &adapter->tx_ring;
 551        struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
 552        struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
 553        int err;
 554
 555        tx_old = adapter->tx_ring;
 556        rx_old = adapter->rx_ring;
 557
 558        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 559                return -EINVAL;
 560
 561        if (netif_running(adapter->netdev))
 562                ixgb_down(adapter, true);
 563
 564        rxdr->count = max(ring->rx_pending,(u32)MIN_RXD);
 565        rxdr->count = min(rxdr->count,(u32)MAX_RXD);
 566        rxdr->count = ALIGN(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
 567
 568        txdr->count = max(ring->tx_pending,(u32)MIN_TXD);
 569        txdr->count = min(txdr->count,(u32)MAX_TXD);
 570        txdr->count = ALIGN(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
 571
 572        if (netif_running(adapter->netdev)) {
 573                /* Try to get new resources before deleting old */
 574                if ((err = ixgb_setup_rx_resources(adapter)))
 575                        goto err_setup_rx;
 576                if ((err = ixgb_setup_tx_resources(adapter)))
 577                        goto err_setup_tx;
 578
 579                /* save the new, restore the old in order to free it,
 580                 * then restore the new back again */
 581
 582                rx_new = adapter->rx_ring;
 583                tx_new = adapter->tx_ring;
 584                adapter->rx_ring = rx_old;
 585                adapter->tx_ring = tx_old;
 586                ixgb_free_rx_resources(adapter);
 587                ixgb_free_tx_resources(adapter);
 588                adapter->rx_ring = rx_new;
 589                adapter->tx_ring = tx_new;
 590                if ((err = ixgb_up(adapter)))
 591                        return err;
 592                ixgb_set_speed_duplex(netdev);
 593        }
 594
 595        return 0;
 596err_setup_tx:
 597        ixgb_free_rx_resources(adapter);
 598err_setup_rx:
 599        adapter->rx_ring = rx_old;
 600        adapter->tx_ring = tx_old;
 601        ixgb_up(adapter);
 602        return err;
 603}
 604
 605/* toggle LED 4 times per second = 2 "blinks" per second */
 606#define IXGB_ID_INTERVAL        (HZ/4)
 607
 608/* bit defines for adapter->led_status */
 609#define IXGB_LED_ON             0
 610
 611static void
 612ixgb_led_blink_callback(unsigned long data)
 613{
 614        struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
 615
 616        if (test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
 617                ixgb_led_off(&adapter->hw);
 618        else
 619                ixgb_led_on(&adapter->hw);
 620
 621        mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL);
 622}
 623
 624static int
 625ixgb_phys_id(struct net_device *netdev, u32 data)
 626{
 627        struct ixgb_adapter *adapter = netdev_priv(netdev);
 628
 629        if (!data)
 630                data = INT_MAX;
 631
 632        if (!adapter->blink_timer.function) {
 633                init_timer(&adapter->blink_timer);
 634                adapter->blink_timer.function = ixgb_led_blink_callback;
 635                adapter->blink_timer.data = (unsigned long)adapter;
 636        }
 637
 638        mod_timer(&adapter->blink_timer, jiffies);
 639
 640        msleep_interruptible(data * 1000);
 641        del_timer_sync(&adapter->blink_timer);
 642        ixgb_led_off(&adapter->hw);
 643        clear_bit(IXGB_LED_ON, &adapter->led_status);
 644
 645        return 0;
 646}
 647
 648static int
 649ixgb_get_sset_count(struct net_device *netdev, int sset)
 650{
 651        switch (sset) {
 652        case ETH_SS_STATS:
 653                return IXGB_STATS_LEN;
 654        default:
 655                return -EOPNOTSUPP;
 656        }
 657}
 658
 659static void
 660ixgb_get_ethtool_stats(struct net_device *netdev,
 661                struct ethtool_stats *stats, u64 *data)
 662{
 663        struct ixgb_adapter *adapter = netdev_priv(netdev);
 664        int i;
 665
 666        ixgb_update_stats(adapter);
 667        for (i = 0; i < IXGB_STATS_LEN; i++) {
 668                char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;
 669                data[i] = (ixgb_gstrings_stats[i].sizeof_stat ==
 670                        sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 671        }
 672}
 673
 674static void
 675ixgb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 676{
 677        int i;
 678
 679        switch(stringset) {
 680        case ETH_SS_STATS:
 681                for (i = 0; i < IXGB_STATS_LEN; i++) {
 682                        memcpy(data + i * ETH_GSTRING_LEN,
 683                        ixgb_gstrings_stats[i].stat_string,
 684                        ETH_GSTRING_LEN);
 685                }
 686                break;
 687        }
 688}
 689
 690static const struct ethtool_ops ixgb_ethtool_ops = {
 691        .get_settings = ixgb_get_settings,
 692        .set_settings = ixgb_set_settings,
 693        .get_drvinfo = ixgb_get_drvinfo,
 694        .get_regs_len = ixgb_get_regs_len,
 695        .get_regs = ixgb_get_regs,
 696        .get_link = ethtool_op_get_link,
 697        .get_eeprom_len = ixgb_get_eeprom_len,
 698        .get_eeprom = ixgb_get_eeprom,
 699        .set_eeprom = ixgb_set_eeprom,
 700        .get_ringparam = ixgb_get_ringparam,
 701        .set_ringparam = ixgb_set_ringparam,
 702        .get_pauseparam = ixgb_get_pauseparam,
 703        .set_pauseparam = ixgb_set_pauseparam,
 704        .get_rx_csum = ixgb_get_rx_csum,
 705        .set_rx_csum = ixgb_set_rx_csum,
 706        .get_tx_csum = ixgb_get_tx_csum,
 707        .set_tx_csum = ixgb_set_tx_csum,
 708        .set_sg = ethtool_op_set_sg,
 709        .get_msglevel = ixgb_get_msglevel,
 710        .set_msglevel = ixgb_set_msglevel,
 711        .set_tso = ixgb_set_tso,
 712        .get_strings = ixgb_get_strings,
 713        .phys_id = ixgb_phys_id,
 714        .get_sset_count = ixgb_get_sset_count,
 715        .get_ethtool_stats = ixgb_get_ethtool_stats,
 716};
 717
 718void ixgb_set_ethtool_ops(struct net_device *netdev)
 719{
 720        SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
 721}
 722