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