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