linux/drivers/net/ethernet/qlogic/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, see <http://www.gnu.org/licenses/>.
  18 *
  19 * The full GNU General Public License is included in this distribution
  20 * in the file called "COPYING".
  21 *
  22 */
  23
  24#include <linux/types.h>
  25#include <linux/delay.h>
  26#include <linux/pci.h>
  27#include <asm/io.h>
  28#include <linux/netdevice.h>
  29#include <linux/ethtool.h>
  30
  31#include "netxen_nic.h"
  32#include "netxen_nic_hw.h"
  33
  34struct netxen_nic_stats {
  35        char stat_string[ETH_GSTRING_LEN];
  36        int sizeof_stat;
  37        int stat_offset;
  38};
  39
  40#define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \
  41                        offsetof(struct netxen_adapter, m)
  42
  43#define NETXEN_NIC_PORT_WINDOW 0x10000
  44#define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
  45
  46static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
  47        {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
  48        {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
  49        {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
  50        {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
  51        {"csummed", NETXEN_NIC_STAT(stats.csummed)},
  52        {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)},
  53        {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)},
  54        {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
  55        {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
  56};
  57
  58#define NETXEN_NIC_STATS_LEN    ARRAY_SIZE(netxen_nic_gstrings_stats)
  59
  60static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
  61        "Register_Test_on_offline",
  62        "Link_Test_on_offline"
  63};
  64
  65#define NETXEN_NIC_TEST_LEN     ARRAY_SIZE(netxen_nic_gstrings_test)
  66
  67#define NETXEN_NIC_REGS_COUNT 30
  68#define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
  69#define NETXEN_MAX_EEPROM_LEN   1024
  70
  71static int netxen_nic_get_eeprom_len(struct net_device *dev)
  72{
  73        return NETXEN_FLASH_TOTAL_SIZE;
  74}
  75
  76static void
  77netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
  78{
  79        struct netxen_adapter *adapter = netdev_priv(dev);
  80        u32 fw_major = 0;
  81        u32 fw_minor = 0;
  82        u32 fw_build = 0;
  83
  84        strlcpy(drvinfo->driver, netxen_nic_driver_name,
  85                sizeof(drvinfo->driver));
  86        strlcpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID,
  87                sizeof(drvinfo->version));
  88        fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
  89        fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
  90        fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
  91        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  92                "%d.%d.%d", fw_major, fw_minor, fw_build);
  93
  94        strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
  95                sizeof(drvinfo->bus_info));
  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                ethtool_cmd_speed_set(ecmd, 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                        ethtool_cmd_speed_set(ecmd, 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                        ethtool_cmd_speed_set(ecmd, P3_LINK_SPEED_MHZ *
 152                                              P3_LINK_SPEED_VAL(pcifn, val));
 153                } else
 154                        ethtool_cmd_speed_set(ecmd, 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->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
 220                        ecmd->advertising |=
 221                                (ADVERTISED_TP | ADVERTISED_Autoneg);
 222                        ecmd->port = PORT_TP;
 223                }
 224                break;
 225        default:
 226                printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
 227                                adapter->ahw.board_type);
 228                return -EIO;
 229        }
 230
 231        if (check_sfp_module) {
 232                switch (adapter->module_type) {
 233                case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
 234                case LINKEVENT_MODULE_OPTICAL_SRLR:
 235                case LINKEVENT_MODULE_OPTICAL_LRM:
 236                case LINKEVENT_MODULE_OPTICAL_SFP_1G:
 237                        ecmd->port = PORT_FIBRE;
 238                        break;
 239                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
 240                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
 241                case LINKEVENT_MODULE_TWINAX:
 242                        ecmd->port = PORT_TP;
 243                        break;
 244                default:
 245                        ecmd->port = -1;
 246                }
 247        }
 248
 249        if (!netif_running(dev) || !adapter->ahw.linkup) {
 250                ecmd->duplex = DUPLEX_UNKNOWN;
 251                ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
 252        }
 253
 254        return 0;
 255}
 256
 257static int
 258netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 259{
 260        struct netxen_adapter *adapter = netdev_priv(dev);
 261        u32 speed = ethtool_cmd_speed(ecmd);
 262        int ret;
 263
 264        if (adapter->ahw.port_type != NETXEN_NIC_GBE)
 265                return -EOPNOTSUPP;
 266
 267        if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
 268                return -EOPNOTSUPP;
 269
 270        ret = nx_fw_cmd_set_gbe_port(adapter, speed, ecmd->duplex,
 271                                     ecmd->autoneg);
 272        if (ret == NX_RCODE_NOT_SUPPORTED)
 273                return -EOPNOTSUPP;
 274        else if (ret)
 275                return -EIO;
 276
 277        adapter->link_speed = speed;
 278        adapter->link_duplex = ecmd->duplex;
 279        adapter->link_autoneg = ecmd->autoneg;
 280
 281        if (!netif_running(dev))
 282                return 0;
 283
 284        dev->netdev_ops->ndo_stop(dev);
 285        return dev->netdev_ops->ndo_open(dev);
 286}
 287
 288static int netxen_nic_get_regs_len(struct net_device *dev)
 289{
 290        return NETXEN_NIC_REGS_LEN;
 291}
 292
 293static void
 294netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 295{
 296        struct netxen_adapter *adapter = netdev_priv(dev);
 297        struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 298        struct nx_host_sds_ring *sds_ring;
 299        u32 *regs_buff = p;
 300        int ring, i = 0;
 301        int port = adapter->physical_port;
 302
 303        memset(p, 0, NETXEN_NIC_REGS_LEN);
 304
 305        regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 306            (adapter->pdev)->device;
 307
 308        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 309                return;
 310
 311        regs_buff[i++] = NXRD32(adapter, CRB_CMDPEG_STATE);
 312        regs_buff[i++] = NXRD32(adapter, CRB_RCVPEG_STATE);
 313        regs_buff[i++] = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
 314        regs_buff[i++] = NXRDIO(adapter, adapter->crb_int_state_reg);
 315        regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
 316        regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_STATE);
 317        regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
 318        regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
 319        regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS2);
 320
 321        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_0+0x3c);
 322        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_1+0x3c);
 323        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_2+0x3c);
 324        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_3+0x3c);
 325
 326        if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 327
 328                regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_4+0x3c);
 329                i += 2;
 330
 331                regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE_P3);
 332                regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
 333
 334        } else {
 335                i++;
 336
 337                regs_buff[i++] = NXRD32(adapter,
 338                                        NETXEN_NIU_XGE_CONFIG_0+(0x10000*port));
 339                regs_buff[i++] = NXRD32(adapter,
 340                                        NETXEN_NIU_XGE_CONFIG_1+(0x10000*port));
 341
 342                regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE);
 343                regs_buff[i++] = NXRDIO(adapter,
 344                                 adapter->tx_ring->crb_cmd_consumer);
 345        }
 346
 347        regs_buff[i++] = NXRDIO(adapter, adapter->tx_ring->crb_cmd_producer);
 348
 349        regs_buff[i++] = NXRDIO(adapter,
 350                         recv_ctx->rds_rings[0].crb_rcv_producer);
 351        regs_buff[i++] = NXRDIO(adapter,
 352                         recv_ctx->rds_rings[1].crb_rcv_producer);
 353
 354        regs_buff[i++] = adapter->max_sds_rings;
 355
 356        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 357                sds_ring = &(recv_ctx->sds_rings[ring]);
 358                regs_buff[i++] = NXRDIO(adapter,
 359                                        sds_ring->crb_sts_consumer);
 360        }
 361}
 362
 363static u32 netxen_nic_test_link(struct net_device *dev)
 364{
 365        struct netxen_adapter *adapter = netdev_priv(dev);
 366        u32 val, port;
 367
 368        port = adapter->physical_port;
 369        if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 370                val = NXRD32(adapter, CRB_XG_STATE_P3);
 371                val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
 372                return (val == XG_LINK_UP_P3) ? 0 : 1;
 373        } else {
 374                val = NXRD32(adapter, CRB_XG_STATE);
 375                val = (val >> port*8) & 0xff;
 376                return (val == XG_LINK_UP) ? 0 : 1;
 377        }
 378}
 379
 380static int
 381netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 382                      u8 *bytes)
 383{
 384        struct netxen_adapter *adapter = netdev_priv(dev);
 385        int offset;
 386        int ret;
 387
 388        if (eeprom->len == 0)
 389                return -EINVAL;
 390
 391        eeprom->magic = (adapter->pdev)->vendor |
 392                        ((adapter->pdev)->device << 16);
 393        offset = eeprom->offset;
 394
 395        ret = netxen_rom_fast_read_words(adapter, offset, bytes,
 396                                                eeprom->len);
 397        if (ret < 0)
 398                return ret;
 399
 400        return 0;
 401}
 402
 403static void
 404netxen_nic_get_ringparam(struct net_device *dev,
 405                struct ethtool_ringparam *ring)
 406{
 407        struct netxen_adapter *adapter = netdev_priv(dev);
 408
 409        ring->rx_pending = adapter->num_rxd;
 410        ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
 411        ring->rx_jumbo_pending += adapter->num_lro_rxd;
 412        ring->tx_pending = adapter->num_txd;
 413
 414        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 415                ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
 416                ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
 417        } else {
 418                ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
 419                ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 420        }
 421
 422        ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
 423}
 424
 425static u32
 426netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
 427{
 428        u32 num_desc;
 429        num_desc = max(val, min);
 430        num_desc = min(num_desc, max);
 431        num_desc = roundup_pow_of_two(num_desc);
 432
 433        if (val != num_desc) {
 434                printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
 435                       netxen_nic_driver_name, r_name, num_desc, val);
 436        }
 437
 438        return num_desc;
 439}
 440
 441static int
 442netxen_nic_set_ringparam(struct net_device *dev,
 443                struct ethtool_ringparam *ring)
 444{
 445        struct netxen_adapter *adapter = netdev_priv(dev);
 446        u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
 447        u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 448        u16 num_rxd, num_jumbo_rxd, num_txd;
 449
 450        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 451                return -EOPNOTSUPP;
 452
 453        if (ring->rx_mini_pending)
 454                return -EOPNOTSUPP;
 455
 456        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 457                max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
 458                max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 459        }
 460
 461        num_rxd = netxen_validate_ringparam(ring->rx_pending,
 462                        MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
 463
 464        num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
 465                        MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
 466
 467        num_txd = netxen_validate_ringparam(ring->tx_pending,
 468                        MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
 469
 470        if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
 471                        num_jumbo_rxd == adapter->num_jumbo_rxd)
 472                return 0;
 473
 474        adapter->num_rxd = num_rxd;
 475        adapter->num_jumbo_rxd = num_jumbo_rxd;
 476        adapter->num_txd = num_txd;
 477
 478        return netxen_nic_reset_context(adapter);
 479}
 480
 481static void
 482netxen_nic_get_pauseparam(struct net_device *dev,
 483                          struct ethtool_pauseparam *pause)
 484{
 485        struct netxen_adapter *adapter = netdev_priv(dev);
 486        __u32 val;
 487        int port = adapter->physical_port;
 488
 489        pause->autoneg = 0;
 490
 491        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 492                if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
 493                        return;
 494                /* get flow control settings */
 495                val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 496                pause->rx_pause = netxen_gb_get_rx_flowctl(val);
 497                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 498                switch (port) {
 499                case 0:
 500                        pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
 501                        break;
 502                case 1:
 503                        pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
 504                        break;
 505                case 2:
 506                        pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
 507                        break;
 508                case 3:
 509                default:
 510                        pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
 511                        break;
 512                }
 513        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 514                if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
 515                        return;
 516                pause->rx_pause = 1;
 517                val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 518                if (port == 0)
 519                        pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
 520                else
 521                        pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
 522        } else {
 523                printk(KERN_ERR"%s: Unknown board type: %x\n",
 524                                netxen_nic_driver_name, adapter->ahw.port_type);
 525        }
 526}
 527
 528static int
 529netxen_nic_set_pauseparam(struct net_device *dev,
 530                          struct ethtool_pauseparam *pause)
 531{
 532        struct netxen_adapter *adapter = netdev_priv(dev);
 533        __u32 val;
 534        int port = adapter->physical_port;
 535
 536        /* not supported */
 537        if (pause->autoneg)
 538                return -EINVAL;
 539
 540        /* read mode */
 541        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 542                if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
 543                        return -EIO;
 544                /* set flow control */
 545                val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 546
 547                if (pause->rx_pause)
 548                        netxen_gb_rx_flowctl(val);
 549                else
 550                        netxen_gb_unset_rx_flowctl(val);
 551
 552                NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 553                                val);
 554                /* set autoneg */
 555                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 556                switch (port) {
 557                case 0:
 558                        if (pause->tx_pause)
 559                                netxen_gb_unset_gb0_mask(val);
 560                        else
 561                                netxen_gb_set_gb0_mask(val);
 562                        break;
 563                case 1:
 564                        if (pause->tx_pause)
 565                                netxen_gb_unset_gb1_mask(val);
 566                        else
 567                                netxen_gb_set_gb1_mask(val);
 568                        break;
 569                case 2:
 570                        if (pause->tx_pause)
 571                                netxen_gb_unset_gb2_mask(val);
 572                        else
 573                                netxen_gb_set_gb2_mask(val);
 574                        break;
 575                case 3:
 576                default:
 577                        if (pause->tx_pause)
 578                                netxen_gb_unset_gb3_mask(val);
 579                        else
 580                                netxen_gb_set_gb3_mask(val);
 581                        break;
 582                }
 583                NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
 584        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 585                if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
 586                        return -EIO;
 587                val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 588                if (port == 0) {
 589                        if (pause->tx_pause)
 590                                netxen_xg_unset_xg0_mask(val);
 591                        else
 592                                netxen_xg_set_xg0_mask(val);
 593                } else {
 594                        if (pause->tx_pause)
 595                                netxen_xg_unset_xg1_mask(val);
 596                        else
 597                                netxen_xg_set_xg1_mask(val);
 598                }
 599                NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
 600        } else {
 601                printk(KERN_ERR "%s: Unknown board type: %x\n",
 602                                netxen_nic_driver_name,
 603                                adapter->ahw.port_type);
 604        }
 605        return 0;
 606}
 607
 608static int netxen_nic_reg_test(struct net_device *dev)
 609{
 610        struct netxen_adapter *adapter = netdev_priv(dev);
 611        u32 data_read, data_written;
 612
 613        data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
 614        if ((data_read & 0xffff) != adapter->pdev->vendor)
 615                return 1;
 616
 617        if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 618                return 0;
 619
 620        data_written = (u32)0xa5a5a5a5;
 621
 622        NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
 623        data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
 624        if (data_written != data_read)
 625                return 1;
 626
 627        return 0;
 628}
 629
 630static int netxen_get_sset_count(struct net_device *dev, int sset)
 631{
 632        switch (sset) {
 633        case ETH_SS_TEST:
 634                return NETXEN_NIC_TEST_LEN;
 635        case ETH_SS_STATS:
 636                return NETXEN_NIC_STATS_LEN;
 637        default:
 638                return -EOPNOTSUPP;
 639        }
 640}
 641
 642static void
 643netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 644                     u64 *data)
 645{
 646        memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
 647        if ((data[0] = netxen_nic_reg_test(dev)))
 648                eth_test->flags |= ETH_TEST_FL_FAILED;
 649        /* link test */
 650        if ((data[1] = (u64) netxen_nic_test_link(dev)))
 651                eth_test->flags |= ETH_TEST_FL_FAILED;
 652}
 653
 654static void
 655netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 656{
 657        int index;
 658
 659        switch (stringset) {
 660        case ETH_SS_TEST:
 661                memcpy(data, *netxen_nic_gstrings_test,
 662                       NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
 663                break;
 664        case ETH_SS_STATS:
 665                for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
 666                        memcpy(data + index * ETH_GSTRING_LEN,
 667                               netxen_nic_gstrings_stats[index].stat_string,
 668                               ETH_GSTRING_LEN);
 669                }
 670                break;
 671        }
 672}
 673
 674static void
 675netxen_nic_get_ethtool_stats(struct net_device *dev,
 676                             struct ethtool_stats *stats, u64 *data)
 677{
 678        struct netxen_adapter *adapter = netdev_priv(dev);
 679        int index;
 680
 681        for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
 682                char *p =
 683                    (char *)adapter +
 684                    netxen_nic_gstrings_stats[index].stat_offset;
 685                data[index] =
 686                    (netxen_nic_gstrings_stats[index].sizeof_stat ==
 687                     sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
 688        }
 689}
 690
 691static void
 692netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 693{
 694        struct netxen_adapter *adapter = netdev_priv(dev);
 695        u32 wol_cfg = 0;
 696
 697        wol->supported = 0;
 698        wol->wolopts = 0;
 699
 700        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 701                return;
 702
 703        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 704        if (wol_cfg & (1UL << adapter->portnum))
 705                wol->supported |= WAKE_MAGIC;
 706
 707        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 708        if (wol_cfg & (1UL << adapter->portnum))
 709                wol->wolopts |= WAKE_MAGIC;
 710}
 711
 712static int
 713netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 714{
 715        struct netxen_adapter *adapter = netdev_priv(dev);
 716        u32 wol_cfg = 0;
 717
 718        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 719                return -EOPNOTSUPP;
 720
 721        if (wol->wolopts & ~WAKE_MAGIC)
 722                return -EOPNOTSUPP;
 723
 724        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 725        if (!(wol_cfg & (1 << adapter->portnum)))
 726                return -EOPNOTSUPP;
 727
 728        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 729        if (wol->wolopts & WAKE_MAGIC)
 730                wol_cfg |= 1UL << adapter->portnum;
 731        else
 732                wol_cfg &= ~(1UL << adapter->portnum);
 733        NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
 734
 735        return 0;
 736}
 737
 738/*
 739 * Set the coalescing parameters. Currently only normal is supported.
 740 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
 741 * firmware coalescing to default.
 742 */
 743static int netxen_set_intr_coalesce(struct net_device *netdev,
 744                        struct ethtool_coalesce *ethcoal)
 745{
 746        struct netxen_adapter *adapter = netdev_priv(netdev);
 747
 748        if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
 749                return -EINVAL;
 750
 751        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 752                return -EINVAL;
 753
 754        /*
 755        * Return Error if unsupported values or
 756        * unsupported parameters are set.
 757        */
 758        if (ethcoal->rx_coalesce_usecs > 0xffff ||
 759                ethcoal->rx_max_coalesced_frames > 0xffff ||
 760                ethcoal->tx_coalesce_usecs > 0xffff ||
 761                ethcoal->tx_max_coalesced_frames > 0xffff ||
 762                ethcoal->rx_coalesce_usecs_irq ||
 763                ethcoal->rx_max_coalesced_frames_irq ||
 764                ethcoal->tx_coalesce_usecs_irq ||
 765                ethcoal->tx_max_coalesced_frames_irq ||
 766                ethcoal->stats_block_coalesce_usecs ||
 767                ethcoal->use_adaptive_rx_coalesce ||
 768                ethcoal->use_adaptive_tx_coalesce ||
 769                ethcoal->pkt_rate_low ||
 770                ethcoal->rx_coalesce_usecs_low ||
 771                ethcoal->rx_max_coalesced_frames_low ||
 772                ethcoal->tx_coalesce_usecs_low ||
 773                ethcoal->tx_max_coalesced_frames_low ||
 774                ethcoal->pkt_rate_high ||
 775                ethcoal->rx_coalesce_usecs_high ||
 776                ethcoal->rx_max_coalesced_frames_high ||
 777                ethcoal->tx_coalesce_usecs_high ||
 778                ethcoal->tx_max_coalesced_frames_high)
 779                return -EINVAL;
 780
 781        if (!ethcoal->rx_coalesce_usecs ||
 782                !ethcoal->rx_max_coalesced_frames) {
 783                adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
 784                adapter->coal.normal.data.rx_time_us =
 785                        NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
 786                adapter->coal.normal.data.rx_packets =
 787                        NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
 788        } else {
 789                adapter->coal.flags = 0;
 790                adapter->coal.normal.data.rx_time_us =
 791                ethcoal->rx_coalesce_usecs;
 792                adapter->coal.normal.data.rx_packets =
 793                ethcoal->rx_max_coalesced_frames;
 794        }
 795        adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
 796        adapter->coal.normal.data.tx_packets =
 797        ethcoal->tx_max_coalesced_frames;
 798
 799        netxen_config_intr_coalesce(adapter);
 800
 801        return 0;
 802}
 803
 804static int netxen_get_intr_coalesce(struct net_device *netdev,
 805                        struct ethtool_coalesce *ethcoal)
 806{
 807        struct netxen_adapter *adapter = netdev_priv(netdev);
 808
 809        if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
 810                return -EINVAL;
 811
 812        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 813                return -EINVAL;
 814
 815        ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
 816        ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
 817        ethcoal->rx_max_coalesced_frames =
 818                adapter->coal.normal.data.rx_packets;
 819        ethcoal->tx_max_coalesced_frames =
 820                adapter->coal.normal.data.tx_packets;
 821
 822        return 0;
 823}
 824
 825static int
 826netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
 827{
 828        struct netxen_adapter *adapter = netdev_priv(netdev);
 829        struct netxen_minidump *mdump = &adapter->mdump;
 830        if (adapter->fw_mdump_rdy)
 831                dump->len = mdump->md_dump_size;
 832        else
 833                dump->len = 0;
 834
 835        if (!mdump->md_enabled)
 836                dump->flag = ETH_FW_DUMP_DISABLE;
 837        else
 838                dump->flag = mdump->md_capture_mask;
 839
 840        dump->version = adapter->fw_version;
 841        return 0;
 842}
 843
 844static int
 845netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
 846{
 847        int i;
 848        struct netxen_adapter *adapter = netdev_priv(netdev);
 849        struct netxen_minidump *mdump = &adapter->mdump;
 850
 851        switch (val->flag) {
 852        case NX_FORCE_FW_DUMP_KEY:
 853                if (!mdump->md_enabled) {
 854                        netdev_info(netdev, "FW dump not enabled\n");
 855                        return 0;
 856                }
 857                if (adapter->fw_mdump_rdy) {
 858                        netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");
 859                        return 0;
 860                }
 861                netdev_info(netdev, "Forcing a fw dump\n");
 862                nx_dev_request_reset(adapter);
 863                break;
 864        case NX_DISABLE_FW_DUMP:
 865                if (mdump->md_enabled) {
 866                        netdev_info(netdev, "Disabling FW Dump\n");
 867                        mdump->md_enabled = 0;
 868                }
 869                break;
 870        case NX_ENABLE_FW_DUMP:
 871                if (!mdump->md_enabled) {
 872                        netdev_info(netdev, "Enabling FW dump\n");
 873                        mdump->md_enabled = 1;
 874                }
 875                break;
 876        case NX_FORCE_FW_RESET:
 877                netdev_info(netdev, "Forcing FW reset\n");
 878                nx_dev_request_reset(adapter);
 879                adapter->flags &= ~NETXEN_FW_RESET_OWNER;
 880                break;
 881        default:
 882                for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
 883                        if (val->flag == FW_DUMP_LEVELS[i]) {
 884                                mdump->md_capture_mask = val->flag;
 885                                netdev_info(netdev,
 886                                        "Driver mask changed to: 0x%x\n",
 887                                        mdump->md_capture_mask);
 888                                return 0;
 889                        }
 890                }
 891                netdev_info(netdev,
 892                        "Invalid dump level: 0x%x\n", val->flag);
 893                return -EINVAL;
 894        }
 895
 896        return 0;
 897}
 898
 899static int
 900netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 901                        void *buffer)
 902{
 903        int i, copy_sz;
 904        u32 *hdr_ptr, *data;
 905        struct netxen_adapter *adapter = netdev_priv(netdev);
 906        struct netxen_minidump *mdump = &adapter->mdump;
 907
 908
 909        if (!adapter->fw_mdump_rdy) {
 910                netdev_info(netdev, "Dump not available\n");
 911                return -EINVAL;
 912        }
 913        /* Copy template header first */
 914        copy_sz = mdump->md_template_size;
 915        hdr_ptr = (u32 *) mdump->md_template;
 916        data = buffer;
 917        for (i = 0; i < copy_sz/sizeof(u32); i++)
 918                *data++ = cpu_to_le32(*hdr_ptr++);
 919
 920        /* Copy captured dump data */
 921        memcpy(buffer + copy_sz,
 922                mdump->md_capture_buff + mdump->md_template_size,
 923                        mdump->md_capture_size);
 924        dump->len = copy_sz + mdump->md_capture_size;
 925        dump->flag = mdump->md_capture_mask;
 926
 927        /* Free dump area once data has been captured */
 928        vfree(mdump->md_capture_buff);
 929        mdump->md_capture_buff = NULL;
 930        adapter->fw_mdump_rdy = 0;
 931        netdev_info(netdev, "extracted the fw dump Successfully\n");
 932        return 0;
 933}
 934
 935const struct ethtool_ops netxen_nic_ethtool_ops = {
 936        .get_settings = netxen_nic_get_settings,
 937        .set_settings = netxen_nic_set_settings,
 938        .get_drvinfo = netxen_nic_get_drvinfo,
 939        .get_regs_len = netxen_nic_get_regs_len,
 940        .get_regs = netxen_nic_get_regs,
 941        .get_link = ethtool_op_get_link,
 942        .get_eeprom_len = netxen_nic_get_eeprom_len,
 943        .get_eeprom = netxen_nic_get_eeprom,
 944        .get_ringparam = netxen_nic_get_ringparam,
 945        .set_ringparam = netxen_nic_set_ringparam,
 946        .get_pauseparam = netxen_nic_get_pauseparam,
 947        .set_pauseparam = netxen_nic_set_pauseparam,
 948        .get_wol = netxen_nic_get_wol,
 949        .set_wol = netxen_nic_set_wol,
 950        .self_test = netxen_nic_diag_test,
 951        .get_strings = netxen_nic_get_strings,
 952        .get_ethtool_stats = netxen_nic_get_ethtool_stats,
 953        .get_sset_count = netxen_get_sset_count,
 954        .get_coalesce = netxen_get_intr_coalesce,
 955        .set_coalesce = netxen_set_intr_coalesce,
 956        .get_dump_flag = netxen_get_dump_flag,
 957        .get_dump_data = netxen_get_dump_data,
 958        .set_dump = netxen_set_dump,
 959};
 960