linux/drivers/net/netxen/netxen_nic_ethtool.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2003 - 2009 NetXen, Inc.
   3 * Copyright (C) 2009 - QLogic Corporation.
   4 * All rights reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version 2
   9 * of the License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  19 * MA  02111-1307, USA.
  20 *
  21 * The full GNU General Public License is included in this distribution
  22 * in the file called LICENSE.
  23 *
  24 */
  25
  26#include <linux/types.h>
  27#include <linux/delay.h>
  28#include <linux/pci.h>
  29#include <asm/io.h>
  30#include <linux/netdevice.h>
  31#include <linux/ethtool.h>
  32
  33#include "netxen_nic.h"
  34#include "netxen_nic_hw.h"
  35
  36struct netxen_nic_stats {
  37        char stat_string[ETH_GSTRING_LEN];
  38        int sizeof_stat;
  39        int stat_offset;
  40};
  41
  42#define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \
  43                        offsetof(struct netxen_adapter, m)
  44
  45#define NETXEN_NIC_PORT_WINDOW 0x10000
  46#define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
  47
  48static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
  49        {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
  50        {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
  51        {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
  52        {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
  53        {"csummed", NETXEN_NIC_STAT(stats.csummed)},
  54        {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)},
  55        {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)},
  56        {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
  57        {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
  58};
  59
  60#define NETXEN_NIC_STATS_LEN    ARRAY_SIZE(netxen_nic_gstrings_stats)
  61
  62static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
  63        "Register_Test_on_offline",
  64        "Link_Test_on_offline"
  65};
  66
  67#define NETXEN_NIC_TEST_LEN     ARRAY_SIZE(netxen_nic_gstrings_test)
  68
  69#define NETXEN_NIC_REGS_COUNT 42
  70#define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
  71#define NETXEN_MAX_EEPROM_LEN   1024
  72
  73static int netxen_nic_get_eeprom_len(struct net_device *dev)
  74{
  75        return NETXEN_FLASH_TOTAL_SIZE;
  76}
  77
  78static void
  79netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
  80{
  81        struct netxen_adapter *adapter = netdev_priv(dev);
  82        u32 fw_major = 0;
  83        u32 fw_minor = 0;
  84        u32 fw_build = 0;
  85
  86        strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
  87        strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
  88        read_lock(&adapter->adapter_lock);
  89        fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
  90        fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
  91        fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
  92        read_unlock(&adapter->adapter_lock);
  93        sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
  94
  95        strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
  96        drvinfo->regdump_len = NETXEN_NIC_REGS_LEN;
  97        drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev);
  98}
  99
 100static int
 101netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 102{
 103        struct netxen_adapter *adapter = netdev_priv(dev);
 104        int check_sfp_module = 0;
 105
 106        /* read which mode */
 107        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 108                ecmd->supported = (SUPPORTED_10baseT_Half |
 109                                   SUPPORTED_10baseT_Full |
 110                                   SUPPORTED_100baseT_Half |
 111                                   SUPPORTED_100baseT_Full |
 112                                   SUPPORTED_1000baseT_Half |
 113                                   SUPPORTED_1000baseT_Full);
 114
 115                ecmd->advertising = (ADVERTISED_100baseT_Half |
 116                                     ADVERTISED_100baseT_Full |
 117                                     ADVERTISED_1000baseT_Half |
 118                                     ADVERTISED_1000baseT_Full);
 119
 120                ecmd->port = PORT_TP;
 121
 122                ecmd->speed = adapter->link_speed;
 123                ecmd->duplex = adapter->link_duplex;
 124                ecmd->autoneg = adapter->link_autoneg;
 125
 126        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 127                u32 val;
 128
 129                val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
 130                if (val == NETXEN_PORT_MODE_802_3_AP) {
 131                        ecmd->supported = SUPPORTED_1000baseT_Full;
 132                        ecmd->advertising = ADVERTISED_1000baseT_Full;
 133                } else {
 134                        ecmd->supported = SUPPORTED_10000baseT_Full;
 135                        ecmd->advertising = ADVERTISED_10000baseT_Full;
 136                }
 137
 138                if (netif_running(dev) && adapter->has_link_events) {
 139                        ecmd->speed = adapter->link_speed;
 140                        ecmd->autoneg = adapter->link_autoneg;
 141                        ecmd->duplex = adapter->link_duplex;
 142                        goto skip;
 143                }
 144
 145                ecmd->port = PORT_TP;
 146
 147                if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 148                        u16 pcifn = adapter->ahw.pci_func;
 149
 150                        val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));
 151                        ecmd->speed = P3_LINK_SPEED_MHZ *
 152                                        P3_LINK_SPEED_VAL(pcifn, val);
 153                } else
 154                        ecmd->speed = SPEED_10000;
 155
 156                ecmd->duplex = DUPLEX_FULL;
 157                ecmd->autoneg = AUTONEG_DISABLE;
 158        } else
 159                return -EIO;
 160
 161skip:
 162        ecmd->phy_address = adapter->physical_port;
 163        ecmd->transceiver = XCVR_EXTERNAL;
 164
 165        switch (adapter->ahw.board_type) {
 166        case NETXEN_BRDTYPE_P2_SB35_4G:
 167        case NETXEN_BRDTYPE_P2_SB31_2G:
 168        case NETXEN_BRDTYPE_P3_REF_QG:
 169        case NETXEN_BRDTYPE_P3_4_GB:
 170        case NETXEN_BRDTYPE_P3_4_GB_MM:
 171
 172                ecmd->supported |= SUPPORTED_Autoneg;
 173                ecmd->advertising |= ADVERTISED_Autoneg;
 174        case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
 175        case NETXEN_BRDTYPE_P3_10G_CX4:
 176        case NETXEN_BRDTYPE_P3_10G_CX4_LP:
 177        case NETXEN_BRDTYPE_P3_10000_BASE_T:
 178                ecmd->supported |= SUPPORTED_TP;
 179                ecmd->advertising |= ADVERTISED_TP;
 180                ecmd->port = PORT_TP;
 181                ecmd->autoneg = (adapter->ahw.board_type ==
 182                                 NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
 183                    (AUTONEG_DISABLE) : (adapter->link_autoneg);
 184                break;
 185        case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
 186        case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
 187        case NETXEN_BRDTYPE_P3_IMEZ:
 188        case NETXEN_BRDTYPE_P3_XG_LOM:
 189        case NETXEN_BRDTYPE_P3_HMEZ:
 190                ecmd->supported |= SUPPORTED_MII;
 191                ecmd->advertising |= ADVERTISED_MII;
 192                ecmd->port = PORT_MII;
 193                ecmd->autoneg = AUTONEG_DISABLE;
 194                break;
 195        case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
 196        case NETXEN_BRDTYPE_P3_10G_SFP_CT:
 197        case NETXEN_BRDTYPE_P3_10G_SFP_QT:
 198                ecmd->advertising |= ADVERTISED_TP;
 199                ecmd->supported |= SUPPORTED_TP;
 200                check_sfp_module = netif_running(dev) &&
 201                        adapter->has_link_events;
 202        case NETXEN_BRDTYPE_P2_SB31_10G:
 203        case NETXEN_BRDTYPE_P3_10G_XFP:
 204                ecmd->supported |= SUPPORTED_FIBRE;
 205                ecmd->advertising |= ADVERTISED_FIBRE;
 206                ecmd->port = PORT_FIBRE;
 207                ecmd->autoneg = AUTONEG_DISABLE;
 208                break;
 209        case NETXEN_BRDTYPE_P3_10G_TP:
 210                if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 211                        ecmd->autoneg = AUTONEG_DISABLE;
 212                        ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
 213                        ecmd->advertising |=
 214                                (ADVERTISED_FIBRE | ADVERTISED_TP);
 215                        ecmd->port = PORT_FIBRE;
 216                        check_sfp_module = netif_running(dev) &&
 217                                adapter->has_link_events;
 218                } else {
 219                        ecmd->autoneg = AUTONEG_ENABLE;
 220                        ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
 221                        ecmd->advertising |=
 222                                (ADVERTISED_TP | ADVERTISED_Autoneg);
 223                        ecmd->port = PORT_TP;
 224                }
 225                break;
 226        default:
 227                printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
 228                                adapter->ahw.board_type);
 229                return -EIO;
 230        }
 231
 232        if (check_sfp_module) {
 233                switch (adapter->module_type) {
 234                case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
 235                case LINKEVENT_MODULE_OPTICAL_SRLR:
 236                case LINKEVENT_MODULE_OPTICAL_LRM:
 237                case LINKEVENT_MODULE_OPTICAL_SFP_1G:
 238                        ecmd->port = PORT_FIBRE;
 239                        break;
 240                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
 241                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
 242                case LINKEVENT_MODULE_TWINAX:
 243                        ecmd->port = PORT_TP;
 244                        break;
 245                default:
 246                        ecmd->port = -1;
 247                }
 248        }
 249
 250        return 0;
 251}
 252
 253static int
 254netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 255{
 256        struct netxen_adapter *adapter = netdev_priv(dev);
 257        __u32 status;
 258
 259        /* read which mode */
 260        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 261                /* autonegotiation */
 262                if (adapter->phy_write
 263                    && adapter->phy_write(adapter,
 264                                          NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
 265                                          ecmd->autoneg) != 0)
 266                        return -EIO;
 267                else
 268                        adapter->link_autoneg = ecmd->autoneg;
 269
 270                if (adapter->phy_read
 271                    && adapter->phy_read(adapter,
 272                                         NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
 273                                         &status) != 0)
 274                        return -EIO;
 275
 276                /* speed */
 277                switch (ecmd->speed) {
 278                case SPEED_10:
 279                        netxen_set_phy_speed(status, 0);
 280                        break;
 281                case SPEED_100:
 282                        netxen_set_phy_speed(status, 1);
 283                        break;
 284                case SPEED_1000:
 285                        netxen_set_phy_speed(status, 2);
 286                        break;
 287                }
 288                /* set duplex mode */
 289                if (ecmd->duplex == DUPLEX_HALF)
 290                        netxen_clear_phy_duplex(status);
 291                if (ecmd->duplex == DUPLEX_FULL)
 292                        netxen_set_phy_duplex(status);
 293                if (adapter->phy_write
 294                    && adapter->phy_write(adapter,
 295                                          NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
 296                                          *((int *)&status)) != 0)
 297                        return -EIO;
 298                else {
 299                        adapter->link_speed = ecmd->speed;
 300                        adapter->link_duplex = ecmd->duplex;
 301                }
 302        } else
 303                return -EOPNOTSUPP;
 304
 305        if (!netif_running(dev))
 306                return 0;
 307
 308        dev->netdev_ops->ndo_stop(dev);
 309        return dev->netdev_ops->ndo_open(dev);
 310}
 311
 312static int netxen_nic_get_regs_len(struct net_device *dev)
 313{
 314        return NETXEN_NIC_REGS_LEN;
 315}
 316
 317struct netxen_niu_regs {
 318        __u32 reg[NETXEN_NIC_REGS_COUNT];
 319};
 320
 321static struct netxen_niu_regs niu_registers[] = {
 322        {
 323         /* GB Mode */
 324         {
 325          NETXEN_NIU_GB_SERDES_RESET,
 326          NETXEN_NIU_GB0_MII_MODE,
 327          NETXEN_NIU_GB1_MII_MODE,
 328          NETXEN_NIU_GB2_MII_MODE,
 329          NETXEN_NIU_GB3_MII_MODE,
 330          NETXEN_NIU_GB0_GMII_MODE,
 331          NETXEN_NIU_GB1_GMII_MODE,
 332          NETXEN_NIU_GB2_GMII_MODE,
 333          NETXEN_NIU_GB3_GMII_MODE,
 334          NETXEN_NIU_REMOTE_LOOPBACK,
 335          NETXEN_NIU_GB0_HALF_DUPLEX,
 336          NETXEN_NIU_GB1_HALF_DUPLEX,
 337          NETXEN_NIU_RESET_SYS_FIFOS,
 338          NETXEN_NIU_GB_CRC_DROP,
 339          NETXEN_NIU_GB_DROP_WRONGADDR,
 340          NETXEN_NIU_TEST_MUX_CTL,
 341
 342          NETXEN_NIU_GB_MAC_CONFIG_0(0),
 343          NETXEN_NIU_GB_MAC_CONFIG_1(0),
 344          NETXEN_NIU_GB_HALF_DUPLEX_CTRL(0),
 345          NETXEN_NIU_GB_MAX_FRAME_SIZE(0),
 346          NETXEN_NIU_GB_TEST_REG(0),
 347          NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
 348          NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
 349          NETXEN_NIU_GB_MII_MGMT_ADDR(0),
 350          NETXEN_NIU_GB_MII_MGMT_CTRL(0),
 351          NETXEN_NIU_GB_MII_MGMT_STATUS(0),
 352          NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
 353          NETXEN_NIU_GB_INTERFACE_CTRL(0),
 354          NETXEN_NIU_GB_INTERFACE_STATUS(0),
 355          NETXEN_NIU_GB_STATION_ADDR_0(0),
 356          NETXEN_NIU_GB_STATION_ADDR_1(0),
 357          -1,
 358          }
 359         },
 360        {
 361         /* XG Mode */
 362         {
 363          NETXEN_NIU_XG_SINGLE_TERM,
 364          NETXEN_NIU_XG_DRIVE_HI,
 365          NETXEN_NIU_XG_DRIVE_LO,
 366          NETXEN_NIU_XG_DTX,
 367          NETXEN_NIU_XG_DEQ,
 368          NETXEN_NIU_XG_WORD_ALIGN,
 369          NETXEN_NIU_XG_RESET,
 370          NETXEN_NIU_XG_POWER_DOWN,
 371          NETXEN_NIU_XG_RESET_PLL,
 372          NETXEN_NIU_XG_SERDES_LOOPBACK,
 373          NETXEN_NIU_XG_DO_BYTE_ALIGN,
 374          NETXEN_NIU_XG_TX_ENABLE,
 375          NETXEN_NIU_XG_RX_ENABLE,
 376          NETXEN_NIU_XG_STATUS,
 377          NETXEN_NIU_XG_PAUSE_THRESHOLD,
 378          NETXEN_NIU_XGE_CONFIG_0,
 379          NETXEN_NIU_XGE_CONFIG_1,
 380          NETXEN_NIU_XGE_IPG,
 381          NETXEN_NIU_XGE_STATION_ADDR_0_HI,
 382          NETXEN_NIU_XGE_STATION_ADDR_0_1,
 383          NETXEN_NIU_XGE_STATION_ADDR_1_LO,
 384          NETXEN_NIU_XGE_STATUS,
 385          NETXEN_NIU_XGE_MAX_FRAME_SIZE,
 386          NETXEN_NIU_XGE_PAUSE_FRAME_VALUE,
 387          NETXEN_NIU_XGE_TX_BYTE_CNT,
 388          NETXEN_NIU_XGE_TX_FRAME_CNT,
 389          NETXEN_NIU_XGE_RX_BYTE_CNT,
 390          NETXEN_NIU_XGE_RX_FRAME_CNT,
 391          NETXEN_NIU_XGE_AGGR_ERROR_CNT,
 392          NETXEN_NIU_XGE_MULTICAST_FRAME_CNT,
 393          NETXEN_NIU_XGE_UNICAST_FRAME_CNT,
 394          NETXEN_NIU_XGE_CRC_ERROR_CNT,
 395          NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
 396          NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
 397          NETXEN_NIU_XGE_LOCAL_ERROR_CNT,
 398          NETXEN_NIU_XGE_REMOTE_ERROR_CNT,
 399          NETXEN_NIU_XGE_CONTROL_CHAR_CNT,
 400          NETXEN_NIU_XGE_PAUSE_FRAME_CNT,
 401          -1,
 402          }
 403         }
 404};
 405
 406static void
 407netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 408{
 409        struct netxen_adapter *adapter = netdev_priv(dev);
 410        __u32 mode, *regs_buff = p;
 411        int i, window;
 412
 413        memset(p, 0, NETXEN_NIC_REGS_LEN);
 414        regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 415            (adapter->pdev)->device;
 416        /* which mode */
 417        regs_buff[0] = NXRD32(adapter, NETXEN_NIU_MODE);
 418        mode = regs_buff[0];
 419
 420        /* Common registers to all the modes */
 421        regs_buff[2] = NXRD32(adapter, NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER);
 422        /* GB/XGB Mode */
 423        mode = (mode / 2) - 1;
 424        window = 0;
 425        if (mode <= 1) {
 426                for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) {
 427                        /* GB: port specific registers */
 428                        if (mode == 0 && i >= 19)
 429                                window = adapter->physical_port *
 430                                        NETXEN_NIC_PORT_WINDOW;
 431
 432                        regs_buff[i] = NXRD32(adapter,
 433                                niu_registers[mode].reg[i - 3] + window);
 434                }
 435
 436        }
 437}
 438
 439static u32 netxen_nic_test_link(struct net_device *dev)
 440{
 441        struct netxen_adapter *adapter = netdev_priv(dev);
 442        __u32 status;
 443        int val;
 444
 445        /* read which mode */
 446        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 447                if (adapter->phy_read
 448                    && adapter->phy_read(adapter,
 449                                         NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
 450                                         &status) != 0)
 451                        return -EIO;
 452                else {
 453                        val = netxen_get_phy_link(status);
 454                        return !val;
 455                }
 456        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 457                val = NXRD32(adapter, CRB_XG_STATE);
 458                return (val == XG_LINK_UP) ? 0 : 1;
 459        }
 460        return -EIO;
 461}
 462
 463static int
 464netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 465                      u8 * bytes)
 466{
 467        struct netxen_adapter *adapter = netdev_priv(dev);
 468        int offset;
 469        int ret;
 470
 471        if (eeprom->len == 0)
 472                return -EINVAL;
 473
 474        eeprom->magic = (adapter->pdev)->vendor |
 475                        ((adapter->pdev)->device << 16);
 476        offset = eeprom->offset;
 477
 478        ret = netxen_rom_fast_read_words(adapter, offset, bytes,
 479                                                eeprom->len);
 480        if (ret < 0)
 481                return ret;
 482
 483        return 0;
 484}
 485
 486static void
 487netxen_nic_get_ringparam(struct net_device *dev,
 488                struct ethtool_ringparam *ring)
 489{
 490        struct netxen_adapter *adapter = netdev_priv(dev);
 491
 492        ring->rx_pending = adapter->num_rxd;
 493        ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
 494        ring->rx_jumbo_pending += adapter->num_lro_rxd;
 495        ring->tx_pending = adapter->num_txd;
 496
 497        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 498                ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
 499                ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
 500        } else {
 501                ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
 502                ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 503        }
 504
 505        ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
 506
 507        ring->rx_mini_max_pending = 0;
 508        ring->rx_mini_pending = 0;
 509}
 510
 511static u32
 512netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
 513{
 514        u32 num_desc;
 515        num_desc = max(val, min);
 516        num_desc = min(num_desc, max);
 517        num_desc = roundup_pow_of_two(num_desc);
 518
 519        if (val != num_desc) {
 520                printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
 521                       netxen_nic_driver_name, r_name, num_desc, val);
 522        }
 523
 524        return num_desc;
 525}
 526
 527static int
 528netxen_nic_set_ringparam(struct net_device *dev,
 529                struct ethtool_ringparam *ring)
 530{
 531        struct netxen_adapter *adapter = netdev_priv(dev);
 532        u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
 533        u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 534        u16 num_rxd, num_jumbo_rxd, num_txd;
 535
 536        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 537                return -EOPNOTSUPP;
 538
 539        if (ring->rx_mini_pending)
 540                return -EOPNOTSUPP;
 541
 542        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 543                max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
 544                max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 545        }
 546
 547        num_rxd = netxen_validate_ringparam(ring->rx_pending,
 548                        MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
 549
 550        num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
 551                        MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
 552
 553        num_txd = netxen_validate_ringparam(ring->tx_pending,
 554                        MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
 555
 556        if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
 557                        num_jumbo_rxd == adapter->num_jumbo_rxd)
 558                return 0;
 559
 560        adapter->num_rxd = num_rxd;
 561        adapter->num_jumbo_rxd = num_jumbo_rxd;
 562        adapter->num_txd = num_txd;
 563
 564        return netxen_nic_reset_context(adapter);
 565}
 566
 567static void
 568netxen_nic_get_pauseparam(struct net_device *dev,
 569                          struct ethtool_pauseparam *pause)
 570{
 571        struct netxen_adapter *adapter = netdev_priv(dev);
 572        __u32 val;
 573        int port = adapter->physical_port;
 574
 575        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 576                if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 577                        return;
 578                /* get flow control settings */
 579                val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 580                pause->rx_pause = netxen_gb_get_rx_flowctl(val);
 581                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 582                switch (port) {
 583                        case 0:
 584                                pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
 585                                break;
 586                        case 1:
 587                                pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
 588                                break;
 589                        case 2:
 590                                pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
 591                                break;
 592                        case 3:
 593                        default:
 594                                pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
 595                                break;
 596                }
 597        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 598                if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
 599                        return;
 600                pause->rx_pause = 1;
 601                val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 602                if (port == 0)
 603                        pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
 604                else
 605                        pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
 606        } else {
 607                printk(KERN_ERR"%s: Unknown board type: %x\n",
 608                                netxen_nic_driver_name, adapter->ahw.port_type);
 609        }
 610}
 611
 612static int
 613netxen_nic_set_pauseparam(struct net_device *dev,
 614                          struct ethtool_pauseparam *pause)
 615{
 616        struct netxen_adapter *adapter = netdev_priv(dev);
 617        __u32 val;
 618        int port = adapter->physical_port;
 619        /* read mode */
 620        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 621                if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 622                        return -EIO;
 623                /* set flow control */
 624                val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 625
 626                if (pause->rx_pause)
 627                        netxen_gb_rx_flowctl(val);
 628                else
 629                        netxen_gb_unset_rx_flowctl(val);
 630
 631                NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 632                                val);
 633                /* set autoneg */
 634                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 635                switch (port) {
 636                        case 0:
 637                                if (pause->tx_pause)
 638                                        netxen_gb_unset_gb0_mask(val);
 639                                else
 640                                        netxen_gb_set_gb0_mask(val);
 641                                break;
 642                        case 1:
 643                                if (pause->tx_pause)
 644                                        netxen_gb_unset_gb1_mask(val);
 645                                else
 646                                        netxen_gb_set_gb1_mask(val);
 647                                break;
 648                        case 2:
 649                                if (pause->tx_pause)
 650                                        netxen_gb_unset_gb2_mask(val);
 651                                else
 652                                        netxen_gb_set_gb2_mask(val);
 653                                break;
 654                        case 3:
 655                        default:
 656                                if (pause->tx_pause)
 657                                        netxen_gb_unset_gb3_mask(val);
 658                                else
 659                                        netxen_gb_set_gb3_mask(val);
 660                                break;
 661                }
 662                NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
 663        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 664                if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
 665                        return -EIO;
 666                val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 667                if (port == 0) {
 668                        if (pause->tx_pause)
 669                                netxen_xg_unset_xg0_mask(val);
 670                        else
 671                                netxen_xg_set_xg0_mask(val);
 672                } else {
 673                        if (pause->tx_pause)
 674                                netxen_xg_unset_xg1_mask(val);
 675                        else
 676                                netxen_xg_set_xg1_mask(val);
 677                }
 678                NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
 679        } else {
 680                printk(KERN_ERR "%s: Unknown board type: %x\n",
 681                                netxen_nic_driver_name,
 682                                adapter->ahw.port_type);
 683        }
 684        return 0;
 685}
 686
 687static int netxen_nic_reg_test(struct net_device *dev)
 688{
 689        struct netxen_adapter *adapter = netdev_priv(dev);
 690        u32 data_read, data_written;
 691
 692        data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
 693        if ((data_read & 0xffff) != PHAN_VENDOR_ID)
 694        return 1;
 695
 696        data_written = (u32)0xa5a5a5a5;
 697
 698        NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
 699        data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
 700        if (data_written != data_read)
 701                return 1;
 702
 703        return 0;
 704}
 705
 706static int netxen_get_sset_count(struct net_device *dev, int sset)
 707{
 708        switch (sset) {
 709        case ETH_SS_TEST:
 710                return NETXEN_NIC_TEST_LEN;
 711        case ETH_SS_STATS:
 712                return NETXEN_NIC_STATS_LEN;
 713        default:
 714                return -EOPNOTSUPP;
 715        }
 716}
 717
 718static void
 719netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 720                     u64 * data)
 721{
 722        memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
 723        if ((data[0] = netxen_nic_reg_test(dev)))
 724                eth_test->flags |= ETH_TEST_FL_FAILED;
 725        /* link test */
 726        if ((data[1] = (u64) netxen_nic_test_link(dev)))
 727                eth_test->flags |= ETH_TEST_FL_FAILED;
 728}
 729
 730static void
 731netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 732{
 733        int index;
 734
 735        switch (stringset) {
 736        case ETH_SS_TEST:
 737                memcpy(data, *netxen_nic_gstrings_test,
 738                       NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
 739                break;
 740        case ETH_SS_STATS:
 741                for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
 742                        memcpy(data + index * ETH_GSTRING_LEN,
 743                               netxen_nic_gstrings_stats[index].stat_string,
 744                               ETH_GSTRING_LEN);
 745                }
 746                break;
 747        }
 748}
 749
 750static void
 751netxen_nic_get_ethtool_stats(struct net_device *dev,
 752                             struct ethtool_stats *stats, u64 * data)
 753{
 754        struct netxen_adapter *adapter = netdev_priv(dev);
 755        int index;
 756
 757        for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
 758                char *p =
 759                    (char *)adapter +
 760                    netxen_nic_gstrings_stats[index].stat_offset;
 761                data[index] =
 762                    (netxen_nic_gstrings_stats[index].sizeof_stat ==
 763                     sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
 764        }
 765}
 766
 767static u32 netxen_nic_get_rx_csum(struct net_device *dev)
 768{
 769        struct netxen_adapter *adapter = netdev_priv(dev);
 770        return adapter->rx_csum;
 771}
 772
 773static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
 774{
 775        struct netxen_adapter *adapter = netdev_priv(dev);
 776        adapter->rx_csum = !!data;
 777        return 0;
 778}
 779
 780static u32 netxen_nic_get_tso(struct net_device *dev)
 781{
 782        struct netxen_adapter *adapter = netdev_priv(dev);
 783
 784        if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 785                return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
 786
 787        return (dev->features & NETIF_F_TSO) != 0;
 788}
 789
 790static int netxen_nic_set_tso(struct net_device *dev, u32 data)
 791{
 792        if (data) {
 793                struct netxen_adapter *adapter = netdev_priv(dev);
 794
 795                dev->features |= NETIF_F_TSO;
 796                if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 797                        dev->features |= NETIF_F_TSO6;
 798        } else
 799                dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
 800
 801        return 0;
 802}
 803
 804static void
 805netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 806{
 807        struct netxen_adapter *adapter = netdev_priv(dev);
 808        u32 wol_cfg = 0;
 809
 810        wol->supported = 0;
 811        wol->wolopts = 0;
 812
 813        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 814                return;
 815
 816        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 817        if (wol_cfg & (1UL << adapter->portnum))
 818                wol->supported |= WAKE_MAGIC;
 819
 820        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 821        if (wol_cfg & (1UL << adapter->portnum))
 822                wol->wolopts |= WAKE_MAGIC;
 823}
 824
 825static int
 826netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 827{
 828        struct netxen_adapter *adapter = netdev_priv(dev);
 829        u32 wol_cfg = 0;
 830
 831        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 832                return -EOPNOTSUPP;
 833
 834        if (wol->wolopts & ~WAKE_MAGIC)
 835                return -EOPNOTSUPP;
 836
 837        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 838        if (!(wol_cfg & (1 << adapter->portnum)))
 839                return -EOPNOTSUPP;
 840
 841        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 842        if (wol->wolopts & WAKE_MAGIC)
 843                wol_cfg |= 1UL << adapter->portnum;
 844        else
 845                wol_cfg &= ~(1UL << adapter->portnum);
 846        NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
 847
 848        return 0;
 849}
 850
 851/*
 852 * Set the coalescing parameters. Currently only normal is supported.
 853 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
 854 * firmware coalescing to default.
 855 */
 856static int netxen_set_intr_coalesce(struct net_device *netdev,
 857                        struct ethtool_coalesce *ethcoal)
 858{
 859        struct netxen_adapter *adapter = netdev_priv(netdev);
 860
 861        if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
 862                return -EINVAL;
 863
 864        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 865                return -EINVAL;
 866
 867        /*
 868        * Return Error if unsupported values or
 869        * unsupported parameters are set.
 870        */
 871        if (ethcoal->rx_coalesce_usecs > 0xffff ||
 872                ethcoal->rx_max_coalesced_frames > 0xffff ||
 873                ethcoal->tx_coalesce_usecs > 0xffff ||
 874                ethcoal->tx_max_coalesced_frames > 0xffff ||
 875                ethcoal->rx_coalesce_usecs_irq ||
 876                ethcoal->rx_max_coalesced_frames_irq ||
 877                ethcoal->tx_coalesce_usecs_irq ||
 878                ethcoal->tx_max_coalesced_frames_irq ||
 879                ethcoal->stats_block_coalesce_usecs ||
 880                ethcoal->use_adaptive_rx_coalesce ||
 881                ethcoal->use_adaptive_tx_coalesce ||
 882                ethcoal->pkt_rate_low ||
 883                ethcoal->rx_coalesce_usecs_low ||
 884                ethcoal->rx_max_coalesced_frames_low ||
 885                ethcoal->tx_coalesce_usecs_low ||
 886                ethcoal->tx_max_coalesced_frames_low ||
 887                ethcoal->pkt_rate_high ||
 888                ethcoal->rx_coalesce_usecs_high ||
 889                ethcoal->rx_max_coalesced_frames_high ||
 890                ethcoal->tx_coalesce_usecs_high ||
 891                ethcoal->tx_max_coalesced_frames_high)
 892                return -EINVAL;
 893
 894        if (!ethcoal->rx_coalesce_usecs ||
 895                !ethcoal->rx_max_coalesced_frames) {
 896                adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
 897                adapter->coal.normal.data.rx_time_us =
 898                        NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
 899                adapter->coal.normal.data.rx_packets =
 900                        NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
 901        } else {
 902                adapter->coal.flags = 0;
 903                adapter->coal.normal.data.rx_time_us =
 904                ethcoal->rx_coalesce_usecs;
 905                adapter->coal.normal.data.rx_packets =
 906                ethcoal->rx_max_coalesced_frames;
 907        }
 908        adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
 909        adapter->coal.normal.data.tx_packets =
 910        ethcoal->tx_max_coalesced_frames;
 911
 912        netxen_config_intr_coalesce(adapter);
 913
 914        return 0;
 915}
 916
 917static int netxen_get_intr_coalesce(struct net_device *netdev,
 918                        struct ethtool_coalesce *ethcoal)
 919{
 920        struct netxen_adapter *adapter = netdev_priv(netdev);
 921
 922        if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
 923                return -EINVAL;
 924
 925        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 926                return -EINVAL;
 927
 928        ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
 929        ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
 930        ethcoal->rx_max_coalesced_frames =
 931                adapter->coal.normal.data.rx_packets;
 932        ethcoal->tx_max_coalesced_frames =
 933                adapter->coal.normal.data.tx_packets;
 934
 935        return 0;
 936}
 937
 938static int netxen_nic_set_flags(struct net_device *netdev, u32 data)
 939{
 940        struct netxen_adapter *adapter = netdev_priv(netdev);
 941        int hw_lro;
 942
 943        if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
 944                return -EINVAL;
 945
 946        ethtool_op_set_flags(netdev, data);
 947
 948        hw_lro = (data & ETH_FLAG_LRO) ? NETXEN_NIC_LRO_ENABLED : 0;
 949
 950        if (netxen_config_hw_lro(adapter, hw_lro))
 951                return -EIO;
 952
 953        if ((hw_lro == 0) && netxen_send_lro_cleanup(adapter))
 954                return -EIO;
 955
 956
 957        return 0;
 958}
 959
 960const struct ethtool_ops netxen_nic_ethtool_ops = {
 961        .get_settings = netxen_nic_get_settings,
 962        .set_settings = netxen_nic_set_settings,
 963        .get_drvinfo = netxen_nic_get_drvinfo,
 964        .get_regs_len = netxen_nic_get_regs_len,
 965        .get_regs = netxen_nic_get_regs,
 966        .get_link = ethtool_op_get_link,
 967        .get_eeprom_len = netxen_nic_get_eeprom_len,
 968        .get_eeprom = netxen_nic_get_eeprom,
 969        .get_ringparam = netxen_nic_get_ringparam,
 970        .set_ringparam = netxen_nic_set_ringparam,
 971        .get_pauseparam = netxen_nic_get_pauseparam,
 972        .set_pauseparam = netxen_nic_set_pauseparam,
 973        .set_tx_csum = ethtool_op_set_tx_csum,
 974        .set_sg = ethtool_op_set_sg,
 975        .get_tso = netxen_nic_get_tso,
 976        .set_tso = netxen_nic_set_tso,
 977        .get_wol = netxen_nic_get_wol,
 978        .set_wol = netxen_nic_set_wol,
 979        .self_test = netxen_nic_diag_test,
 980        .get_strings = netxen_nic_get_strings,
 981        .get_ethtool_stats = netxen_nic_get_ethtool_stats,
 982        .get_sset_count = netxen_get_sset_count,
 983        .get_rx_csum = netxen_nic_get_rx_csum,
 984        .set_rx_csum = netxen_nic_set_rx_csum,
 985        .get_coalesce = netxen_get_intr_coalesce,
 986        .set_coalesce = netxen_set_intr_coalesce,
 987        .get_flags = ethtool_op_get_flags,
 988        .set_flags = netxen_nic_set_flags,
 989};
 990