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}
  97
  98static int
  99netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 100{
 101        struct netxen_adapter *adapter = netdev_priv(dev);
 102        int check_sfp_module = 0;
 103
 104        /* read which mode */
 105        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 106                ecmd->supported = (SUPPORTED_10baseT_Half |
 107                                   SUPPORTED_10baseT_Full |
 108                                   SUPPORTED_100baseT_Half |
 109                                   SUPPORTED_100baseT_Full |
 110                                   SUPPORTED_1000baseT_Half |
 111                                   SUPPORTED_1000baseT_Full);
 112
 113                ecmd->advertising = (ADVERTISED_100baseT_Half |
 114                                     ADVERTISED_100baseT_Full |
 115                                     ADVERTISED_1000baseT_Half |
 116                                     ADVERTISED_1000baseT_Full);
 117
 118                ecmd->port = PORT_TP;
 119
 120                ethtool_cmd_speed_set(ecmd, adapter->link_speed);
 121                ecmd->duplex = adapter->link_duplex;
 122                ecmd->autoneg = adapter->link_autoneg;
 123
 124        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 125                u32 val;
 126
 127                val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
 128                if (val == NETXEN_PORT_MODE_802_3_AP) {
 129                        ecmd->supported = SUPPORTED_1000baseT_Full;
 130                        ecmd->advertising = ADVERTISED_1000baseT_Full;
 131                } else {
 132                        ecmd->supported = SUPPORTED_10000baseT_Full;
 133                        ecmd->advertising = ADVERTISED_10000baseT_Full;
 134                }
 135
 136                if (netif_running(dev) && adapter->has_link_events) {
 137                        ethtool_cmd_speed_set(ecmd, adapter->link_speed);
 138                        ecmd->autoneg = adapter->link_autoneg;
 139                        ecmd->duplex = adapter->link_duplex;
 140                        goto skip;
 141                }
 142
 143                ecmd->port = PORT_TP;
 144
 145                if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 146                        u16 pcifn = adapter->ahw.pci_func;
 147
 148                        val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));
 149                        ethtool_cmd_speed_set(ecmd, P3_LINK_SPEED_MHZ *
 150                                              P3_LINK_SPEED_VAL(pcifn, val));
 151                } else
 152                        ethtool_cmd_speed_set(ecmd, SPEED_10000);
 153
 154                ecmd->duplex = DUPLEX_FULL;
 155                ecmd->autoneg = AUTONEG_DISABLE;
 156        } else
 157                return -EIO;
 158
 159skip:
 160        ecmd->phy_address = adapter->physical_port;
 161        ecmd->transceiver = XCVR_EXTERNAL;
 162
 163        switch (adapter->ahw.board_type) {
 164        case NETXEN_BRDTYPE_P2_SB35_4G:
 165        case NETXEN_BRDTYPE_P2_SB31_2G:
 166        case NETXEN_BRDTYPE_P3_REF_QG:
 167        case NETXEN_BRDTYPE_P3_4_GB:
 168        case NETXEN_BRDTYPE_P3_4_GB_MM:
 169
 170                ecmd->supported |= SUPPORTED_Autoneg;
 171                ecmd->advertising |= ADVERTISED_Autoneg;
 172        case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
 173        case NETXEN_BRDTYPE_P3_10G_CX4:
 174        case NETXEN_BRDTYPE_P3_10G_CX4_LP:
 175        case NETXEN_BRDTYPE_P3_10000_BASE_T:
 176                ecmd->supported |= SUPPORTED_TP;
 177                ecmd->advertising |= ADVERTISED_TP;
 178                ecmd->port = PORT_TP;
 179                ecmd->autoneg = (adapter->ahw.board_type ==
 180                                 NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
 181                    (AUTONEG_DISABLE) : (adapter->link_autoneg);
 182                break;
 183        case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
 184        case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
 185        case NETXEN_BRDTYPE_P3_IMEZ:
 186        case NETXEN_BRDTYPE_P3_XG_LOM:
 187        case NETXEN_BRDTYPE_P3_HMEZ:
 188                ecmd->supported |= SUPPORTED_MII;
 189                ecmd->advertising |= ADVERTISED_MII;
 190                ecmd->port = PORT_MII;
 191                ecmd->autoneg = AUTONEG_DISABLE;
 192                break;
 193        case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
 194        case NETXEN_BRDTYPE_P3_10G_SFP_CT:
 195        case NETXEN_BRDTYPE_P3_10G_SFP_QT:
 196                ecmd->advertising |= ADVERTISED_TP;
 197                ecmd->supported |= SUPPORTED_TP;
 198                check_sfp_module = netif_running(dev) &&
 199                        adapter->has_link_events;
 200        case NETXEN_BRDTYPE_P2_SB31_10G:
 201        case NETXEN_BRDTYPE_P3_10G_XFP:
 202                ecmd->supported |= SUPPORTED_FIBRE;
 203                ecmd->advertising |= ADVERTISED_FIBRE;
 204                ecmd->port = PORT_FIBRE;
 205                ecmd->autoneg = AUTONEG_DISABLE;
 206                break;
 207        case NETXEN_BRDTYPE_P3_10G_TP:
 208                if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 209                        ecmd->autoneg = AUTONEG_DISABLE;
 210                        ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
 211                        ecmd->advertising |=
 212                                (ADVERTISED_FIBRE | ADVERTISED_TP);
 213                        ecmd->port = PORT_FIBRE;
 214                        check_sfp_module = netif_running(dev) &&
 215                                adapter->has_link_events;
 216                } else {
 217                        ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
 218                        ecmd->advertising |=
 219                                (ADVERTISED_TP | ADVERTISED_Autoneg);
 220                        ecmd->port = PORT_TP;
 221                }
 222                break;
 223        default:
 224                printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
 225                                adapter->ahw.board_type);
 226                return -EIO;
 227        }
 228
 229        if (check_sfp_module) {
 230                switch (adapter->module_type) {
 231                case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
 232                case LINKEVENT_MODULE_OPTICAL_SRLR:
 233                case LINKEVENT_MODULE_OPTICAL_LRM:
 234                case LINKEVENT_MODULE_OPTICAL_SFP_1G:
 235                        ecmd->port = PORT_FIBRE;
 236                        break;
 237                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
 238                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
 239                case LINKEVENT_MODULE_TWINAX:
 240                        ecmd->port = PORT_TP;
 241                        break;
 242                default:
 243                        ecmd->port = -1;
 244                }
 245        }
 246
 247        if (!netif_running(dev) || !adapter->ahw.linkup) {
 248                ecmd->duplex = DUPLEX_UNKNOWN;
 249                ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
 250        }
 251
 252        return 0;
 253}
 254
 255static int
 256netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 257{
 258        struct netxen_adapter *adapter = netdev_priv(dev);
 259        u32 speed = ethtool_cmd_speed(ecmd);
 260        int ret;
 261
 262        if (adapter->ahw.port_type != NETXEN_NIC_GBE)
 263                return -EOPNOTSUPP;
 264
 265        if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
 266                return -EOPNOTSUPP;
 267
 268        ret = nx_fw_cmd_set_gbe_port(adapter, speed, ecmd->duplex,
 269                                     ecmd->autoneg);
 270        if (ret == NX_RCODE_NOT_SUPPORTED)
 271                return -EOPNOTSUPP;
 272        else if (ret)
 273                return -EIO;
 274
 275        adapter->link_speed = speed;
 276        adapter->link_duplex = ecmd->duplex;
 277        adapter->link_autoneg = ecmd->autoneg;
 278
 279        if (!netif_running(dev))
 280                return 0;
 281
 282        dev->netdev_ops->ndo_stop(dev);
 283        return dev->netdev_ops->ndo_open(dev);
 284}
 285
 286static int netxen_nic_get_regs_len(struct net_device *dev)
 287{
 288        return NETXEN_NIC_REGS_LEN;
 289}
 290
 291static void
 292netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 293{
 294        struct netxen_adapter *adapter = netdev_priv(dev);
 295        struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 296        struct nx_host_sds_ring *sds_ring;
 297        u32 *regs_buff = p;
 298        int ring, i = 0;
 299        int port = adapter->physical_port;
 300
 301        memset(p, 0, NETXEN_NIC_REGS_LEN);
 302
 303        regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 304            (adapter->pdev)->device;
 305
 306        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 307                return;
 308
 309        regs_buff[i++] = NXRD32(adapter, CRB_CMDPEG_STATE);
 310        regs_buff[i++] = NXRD32(adapter, CRB_RCVPEG_STATE);
 311        regs_buff[i++] = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
 312        regs_buff[i++] = NXRDIO(adapter, adapter->crb_int_state_reg);
 313        regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
 314        regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_STATE);
 315        regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
 316        regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
 317        regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS2);
 318
 319        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_0+0x3c);
 320        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_1+0x3c);
 321        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_2+0x3c);
 322        regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_3+0x3c);
 323
 324        if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 325
 326                regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_4+0x3c);
 327                i += 2;
 328
 329                regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE_P3);
 330                regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
 331
 332        } else {
 333                i++;
 334
 335                regs_buff[i++] = NXRD32(adapter,
 336                                        NETXEN_NIU_XGE_CONFIG_0+(0x10000*port));
 337                regs_buff[i++] = NXRD32(adapter,
 338                                        NETXEN_NIU_XGE_CONFIG_1+(0x10000*port));
 339
 340                regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE);
 341                regs_buff[i++] = NXRDIO(adapter,
 342                                 adapter->tx_ring->crb_cmd_consumer);
 343        }
 344
 345        regs_buff[i++] = NXRDIO(adapter, adapter->tx_ring->crb_cmd_producer);
 346
 347        regs_buff[i++] = NXRDIO(adapter,
 348                         recv_ctx->rds_rings[0].crb_rcv_producer);
 349        regs_buff[i++] = NXRDIO(adapter,
 350                         recv_ctx->rds_rings[1].crb_rcv_producer);
 351
 352        regs_buff[i++] = adapter->max_sds_rings;
 353
 354        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 355                sds_ring = &(recv_ctx->sds_rings[ring]);
 356                regs_buff[i++] = NXRDIO(adapter,
 357                                        sds_ring->crb_sts_consumer);
 358        }
 359}
 360
 361static u32 netxen_nic_test_link(struct net_device *dev)
 362{
 363        struct netxen_adapter *adapter = netdev_priv(dev);
 364        u32 val, port;
 365
 366        port = adapter->physical_port;
 367        if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 368                val = NXRD32(adapter, CRB_XG_STATE_P3);
 369                val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
 370                return (val == XG_LINK_UP_P3) ? 0 : 1;
 371        } else {
 372                val = NXRD32(adapter, CRB_XG_STATE);
 373                val = (val >> port*8) & 0xff;
 374                return (val == XG_LINK_UP) ? 0 : 1;
 375        }
 376}
 377
 378static int
 379netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 380                      u8 *bytes)
 381{
 382        struct netxen_adapter *adapter = netdev_priv(dev);
 383        int offset;
 384        int ret;
 385
 386        if (eeprom->len == 0)
 387                return -EINVAL;
 388
 389        eeprom->magic = (adapter->pdev)->vendor |
 390                        ((adapter->pdev)->device << 16);
 391        offset = eeprom->offset;
 392
 393        ret = netxen_rom_fast_read_words(adapter, offset, bytes,
 394                                                eeprom->len);
 395        if (ret < 0)
 396                return ret;
 397
 398        return 0;
 399}
 400
 401static void
 402netxen_nic_get_ringparam(struct net_device *dev,
 403                struct ethtool_ringparam *ring)
 404{
 405        struct netxen_adapter *adapter = netdev_priv(dev);
 406
 407        ring->rx_pending = adapter->num_rxd;
 408        ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
 409        ring->rx_jumbo_pending += adapter->num_lro_rxd;
 410        ring->tx_pending = adapter->num_txd;
 411
 412        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 413                ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
 414                ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
 415        } else {
 416                ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
 417                ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 418        }
 419
 420        ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
 421}
 422
 423static u32
 424netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
 425{
 426        u32 num_desc;
 427        num_desc = max(val, min);
 428        num_desc = min(num_desc, max);
 429        num_desc = roundup_pow_of_two(num_desc);
 430
 431        if (val != num_desc) {
 432                printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
 433                       netxen_nic_driver_name, r_name, num_desc, val);
 434        }
 435
 436        return num_desc;
 437}
 438
 439static int
 440netxen_nic_set_ringparam(struct net_device *dev,
 441                struct ethtool_ringparam *ring)
 442{
 443        struct netxen_adapter *adapter = netdev_priv(dev);
 444        u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
 445        u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 446        u16 num_rxd, num_jumbo_rxd, num_txd;
 447
 448        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 449                return -EOPNOTSUPP;
 450
 451        if (ring->rx_mini_pending)
 452                return -EOPNOTSUPP;
 453
 454        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 455                max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
 456                max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
 457        }
 458
 459        num_rxd = netxen_validate_ringparam(ring->rx_pending,
 460                        MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
 461
 462        num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
 463                        MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
 464
 465        num_txd = netxen_validate_ringparam(ring->tx_pending,
 466                        MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
 467
 468        if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
 469                        num_jumbo_rxd == adapter->num_jumbo_rxd)
 470                return 0;
 471
 472        adapter->num_rxd = num_rxd;
 473        adapter->num_jumbo_rxd = num_jumbo_rxd;
 474        adapter->num_txd = num_txd;
 475
 476        return netxen_nic_reset_context(adapter);
 477}
 478
 479static void
 480netxen_nic_get_pauseparam(struct net_device *dev,
 481                          struct ethtool_pauseparam *pause)
 482{
 483        struct netxen_adapter *adapter = netdev_priv(dev);
 484        __u32 val;
 485        int port = adapter->physical_port;
 486
 487        pause->autoneg = 0;
 488
 489        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 490                if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
 491                        return;
 492                /* get flow control settings */
 493                val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 494                pause->rx_pause = netxen_gb_get_rx_flowctl(val);
 495                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 496                switch (port) {
 497                case 0:
 498                        pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
 499                        break;
 500                case 1:
 501                        pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
 502                        break;
 503                case 2:
 504                        pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
 505                        break;
 506                case 3:
 507                default:
 508                        pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
 509                        break;
 510                }
 511        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 512                if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
 513                        return;
 514                pause->rx_pause = 1;
 515                val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 516                if (port == 0)
 517                        pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
 518                else
 519                        pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
 520        } else {
 521                printk(KERN_ERR"%s: Unknown board type: %x\n",
 522                                netxen_nic_driver_name, adapter->ahw.port_type);
 523        }
 524}
 525
 526static int
 527netxen_nic_set_pauseparam(struct net_device *dev,
 528                          struct ethtool_pauseparam *pause)
 529{
 530        struct netxen_adapter *adapter = netdev_priv(dev);
 531        __u32 val;
 532        int port = adapter->physical_port;
 533
 534        /* not supported */
 535        if (pause->autoneg)
 536                return -EINVAL;
 537
 538        /* read mode */
 539        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 540                if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
 541                        return -EIO;
 542                /* set flow control */
 543                val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 544
 545                if (pause->rx_pause)
 546                        netxen_gb_rx_flowctl(val);
 547                else
 548                        netxen_gb_unset_rx_flowctl(val);
 549
 550                NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 551                                val);
 552                /* set autoneg */
 553                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 554                switch (port) {
 555                case 0:
 556                        if (pause->tx_pause)
 557                                netxen_gb_unset_gb0_mask(val);
 558                        else
 559                                netxen_gb_set_gb0_mask(val);
 560                        break;
 561                case 1:
 562                        if (pause->tx_pause)
 563                                netxen_gb_unset_gb1_mask(val);
 564                        else
 565                                netxen_gb_set_gb1_mask(val);
 566                        break;
 567                case 2:
 568                        if (pause->tx_pause)
 569                                netxen_gb_unset_gb2_mask(val);
 570                        else
 571                                netxen_gb_set_gb2_mask(val);
 572                        break;
 573                case 3:
 574                default:
 575                        if (pause->tx_pause)
 576                                netxen_gb_unset_gb3_mask(val);
 577                        else
 578                                netxen_gb_set_gb3_mask(val);
 579                        break;
 580                }
 581                NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
 582        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 583                if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
 584                        return -EIO;
 585                val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 586                if (port == 0) {
 587                        if (pause->tx_pause)
 588                                netxen_xg_unset_xg0_mask(val);
 589                        else
 590                                netxen_xg_set_xg0_mask(val);
 591                } else {
 592                        if (pause->tx_pause)
 593                                netxen_xg_unset_xg1_mask(val);
 594                        else
 595                                netxen_xg_set_xg1_mask(val);
 596                }
 597                NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
 598        } else {
 599                printk(KERN_ERR "%s: Unknown board type: %x\n",
 600                                netxen_nic_driver_name,
 601                                adapter->ahw.port_type);
 602        }
 603        return 0;
 604}
 605
 606static int netxen_nic_reg_test(struct net_device *dev)
 607{
 608        struct netxen_adapter *adapter = netdev_priv(dev);
 609        u32 data_read, data_written;
 610
 611        data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
 612        if ((data_read & 0xffff) != adapter->pdev->vendor)
 613                return 1;
 614
 615        if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 616                return 0;
 617
 618        data_written = (u32)0xa5a5a5a5;
 619
 620        NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
 621        data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
 622        if (data_written != data_read)
 623                return 1;
 624
 625        return 0;
 626}
 627
 628static int netxen_get_sset_count(struct net_device *dev, int sset)
 629{
 630        switch (sset) {
 631        case ETH_SS_TEST:
 632                return NETXEN_NIC_TEST_LEN;
 633        case ETH_SS_STATS:
 634                return NETXEN_NIC_STATS_LEN;
 635        default:
 636                return -EOPNOTSUPP;
 637        }
 638}
 639
 640static void
 641netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 642                     u64 *data)
 643{
 644        memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
 645        if ((data[0] = netxen_nic_reg_test(dev)))
 646                eth_test->flags |= ETH_TEST_FL_FAILED;
 647        /* link test */
 648        if ((data[1] = (u64) netxen_nic_test_link(dev)))
 649                eth_test->flags |= ETH_TEST_FL_FAILED;
 650}
 651
 652static void
 653netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 654{
 655        int index;
 656
 657        switch (stringset) {
 658        case ETH_SS_TEST:
 659                memcpy(data, *netxen_nic_gstrings_test,
 660                       NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
 661                break;
 662        case ETH_SS_STATS:
 663                for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
 664                        memcpy(data + index * ETH_GSTRING_LEN,
 665                               netxen_nic_gstrings_stats[index].stat_string,
 666                               ETH_GSTRING_LEN);
 667                }
 668                break;
 669        }
 670}
 671
 672static void
 673netxen_nic_get_ethtool_stats(struct net_device *dev,
 674                             struct ethtool_stats *stats, u64 *data)
 675{
 676        struct netxen_adapter *adapter = netdev_priv(dev);
 677        int index;
 678
 679        for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
 680                char *p =
 681                    (char *)adapter +
 682                    netxen_nic_gstrings_stats[index].stat_offset;
 683                data[index] =
 684                    (netxen_nic_gstrings_stats[index].sizeof_stat ==
 685                     sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
 686        }
 687}
 688
 689static void
 690netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 691{
 692        struct netxen_adapter *adapter = netdev_priv(dev);
 693        u32 wol_cfg = 0;
 694
 695        wol->supported = 0;
 696        wol->wolopts = 0;
 697
 698        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 699                return;
 700
 701        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 702        if (wol_cfg & (1UL << adapter->portnum))
 703                wol->supported |= WAKE_MAGIC;
 704
 705        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 706        if (wol_cfg & (1UL << adapter->portnum))
 707                wol->wolopts |= WAKE_MAGIC;
 708}
 709
 710static int
 711netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 712{
 713        struct netxen_adapter *adapter = netdev_priv(dev);
 714        u32 wol_cfg = 0;
 715
 716        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 717                return -EOPNOTSUPP;
 718
 719        if (wol->wolopts & ~WAKE_MAGIC)
 720                return -EOPNOTSUPP;
 721
 722        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 723        if (!(wol_cfg & (1 << adapter->portnum)))
 724                return -EOPNOTSUPP;
 725
 726        wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 727        if (wol->wolopts & WAKE_MAGIC)
 728                wol_cfg |= 1UL << adapter->portnum;
 729        else
 730                wol_cfg &= ~(1UL << adapter->portnum);
 731        NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
 732
 733        return 0;
 734}
 735
 736/*
 737 * Set the coalescing parameters. Currently only normal is supported.
 738 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
 739 * firmware coalescing to default.
 740 */
 741static int netxen_set_intr_coalesce(struct net_device *netdev,
 742                        struct ethtool_coalesce *ethcoal)
 743{
 744        struct netxen_adapter *adapter = netdev_priv(netdev);
 745
 746        if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
 747                return -EINVAL;
 748
 749        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 750                return -EINVAL;
 751
 752        /*
 753        * Return Error if unsupported values or
 754        * unsupported parameters are set.
 755        */
 756        if (ethcoal->rx_coalesce_usecs > 0xffff ||
 757                ethcoal->rx_max_coalesced_frames > 0xffff ||
 758                ethcoal->tx_coalesce_usecs > 0xffff ||
 759                ethcoal->tx_max_coalesced_frames > 0xffff ||
 760                ethcoal->rx_coalesce_usecs_irq ||
 761                ethcoal->rx_max_coalesced_frames_irq ||
 762                ethcoal->tx_coalesce_usecs_irq ||
 763                ethcoal->tx_max_coalesced_frames_irq ||
 764                ethcoal->stats_block_coalesce_usecs ||
 765                ethcoal->use_adaptive_rx_coalesce ||
 766                ethcoal->use_adaptive_tx_coalesce ||
 767                ethcoal->pkt_rate_low ||
 768                ethcoal->rx_coalesce_usecs_low ||
 769                ethcoal->rx_max_coalesced_frames_low ||
 770                ethcoal->tx_coalesce_usecs_low ||
 771                ethcoal->tx_max_coalesced_frames_low ||
 772                ethcoal->pkt_rate_high ||
 773                ethcoal->rx_coalesce_usecs_high ||
 774                ethcoal->rx_max_coalesced_frames_high ||
 775                ethcoal->tx_coalesce_usecs_high ||
 776                ethcoal->tx_max_coalesced_frames_high)
 777                return -EINVAL;
 778
 779        if (!ethcoal->rx_coalesce_usecs ||
 780                !ethcoal->rx_max_coalesced_frames) {
 781                adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
 782                adapter->coal.normal.data.rx_time_us =
 783                        NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
 784                adapter->coal.normal.data.rx_packets =
 785                        NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
 786        } else {
 787                adapter->coal.flags = 0;
 788                adapter->coal.normal.data.rx_time_us =
 789                ethcoal->rx_coalesce_usecs;
 790                adapter->coal.normal.data.rx_packets =
 791                ethcoal->rx_max_coalesced_frames;
 792        }
 793        adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
 794        adapter->coal.normal.data.tx_packets =
 795        ethcoal->tx_max_coalesced_frames;
 796
 797        netxen_config_intr_coalesce(adapter);
 798
 799        return 0;
 800}
 801
 802static int netxen_get_intr_coalesce(struct net_device *netdev,
 803                        struct ethtool_coalesce *ethcoal)
 804{
 805        struct netxen_adapter *adapter = netdev_priv(netdev);
 806
 807        if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
 808                return -EINVAL;
 809
 810        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
 811                return -EINVAL;
 812
 813        ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
 814        ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
 815        ethcoal->rx_max_coalesced_frames =
 816                adapter->coal.normal.data.rx_packets;
 817        ethcoal->tx_max_coalesced_frames =
 818                adapter->coal.normal.data.tx_packets;
 819
 820        return 0;
 821}
 822
 823static int
 824netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
 825{
 826        struct netxen_adapter *adapter = netdev_priv(netdev);
 827        struct netxen_minidump *mdump = &adapter->mdump;
 828        if (adapter->fw_mdump_rdy)
 829                dump->len = mdump->md_dump_size;
 830        else
 831                dump->len = 0;
 832
 833        if (!mdump->md_enabled)
 834                dump->flag = ETH_FW_DUMP_DISABLE;
 835        else
 836                dump->flag = mdump->md_capture_mask;
 837
 838        dump->version = adapter->fw_version;
 839        return 0;
 840}
 841
 842static int
 843netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
 844{
 845        int i;
 846        struct netxen_adapter *adapter = netdev_priv(netdev);
 847        struct netxen_minidump *mdump = &adapter->mdump;
 848
 849        switch (val->flag) {
 850        case NX_FORCE_FW_DUMP_KEY:
 851                if (!mdump->md_enabled) {
 852                        netdev_info(netdev, "FW dump not enabled\n");
 853                        return 0;
 854                }
 855                if (adapter->fw_mdump_rdy) {
 856                        netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");
 857                        return 0;
 858                }
 859                netdev_info(netdev, "Forcing a fw dump\n");
 860                nx_dev_request_reset(adapter);
 861                break;
 862        case NX_DISABLE_FW_DUMP:
 863                if (mdump->md_enabled) {
 864                        netdev_info(netdev, "Disabling FW Dump\n");
 865                        mdump->md_enabled = 0;
 866                }
 867                break;
 868        case NX_ENABLE_FW_DUMP:
 869                if (!mdump->md_enabled) {
 870                        netdev_info(netdev, "Enabling FW dump\n");
 871                        mdump->md_enabled = 1;
 872                }
 873                break;
 874        case NX_FORCE_FW_RESET:
 875                netdev_info(netdev, "Forcing FW reset\n");
 876                nx_dev_request_reset(adapter);
 877                adapter->flags &= ~NETXEN_FW_RESET_OWNER;
 878                break;
 879        default:
 880                for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
 881                        if (val->flag == FW_DUMP_LEVELS[i]) {
 882                                mdump->md_capture_mask = val->flag;
 883                                netdev_info(netdev,
 884                                        "Driver mask changed to: 0x%x\n",
 885                                        mdump->md_capture_mask);
 886                                return 0;
 887                        }
 888                }
 889                netdev_info(netdev,
 890                        "Invalid dump level: 0x%x\n", val->flag);
 891                return -EINVAL;
 892        }
 893
 894        return 0;
 895}
 896
 897static int
 898netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 899                        void *buffer)
 900{
 901        int i, copy_sz;
 902        u32 *hdr_ptr, *data;
 903        struct netxen_adapter *adapter = netdev_priv(netdev);
 904        struct netxen_minidump *mdump = &adapter->mdump;
 905
 906
 907        if (!adapter->fw_mdump_rdy) {
 908                netdev_info(netdev, "Dump not available\n");
 909                return -EINVAL;
 910        }
 911        /* Copy template header first */
 912        copy_sz = mdump->md_template_size;
 913        hdr_ptr = (u32 *) mdump->md_template;
 914        data = buffer;
 915        for (i = 0; i < copy_sz/sizeof(u32); i++)
 916                *data++ = cpu_to_le32(*hdr_ptr++);
 917
 918        /* Copy captured dump data */
 919        memcpy(buffer + copy_sz,
 920                mdump->md_capture_buff + mdump->md_template_size,
 921                        mdump->md_capture_size);
 922        dump->len = copy_sz + mdump->md_capture_size;
 923        dump->flag = mdump->md_capture_mask;
 924
 925        /* Free dump area once data has been captured */
 926        vfree(mdump->md_capture_buff);
 927        mdump->md_capture_buff = NULL;
 928        adapter->fw_mdump_rdy = 0;
 929        netdev_info(netdev, "extracted the fw dump Successfully\n");
 930        return 0;
 931}
 932
 933const struct ethtool_ops netxen_nic_ethtool_ops = {
 934        .get_settings = netxen_nic_get_settings,
 935        .set_settings = netxen_nic_set_settings,
 936        .get_drvinfo = netxen_nic_get_drvinfo,
 937        .get_regs_len = netxen_nic_get_regs_len,
 938        .get_regs = netxen_nic_get_regs,
 939        .get_link = ethtool_op_get_link,
 940        .get_eeprom_len = netxen_nic_get_eeprom_len,
 941        .get_eeprom = netxen_nic_get_eeprom,
 942        .get_ringparam = netxen_nic_get_ringparam,
 943        .set_ringparam = netxen_nic_set_ringparam,
 944        .get_pauseparam = netxen_nic_get_pauseparam,
 945        .set_pauseparam = netxen_nic_set_pauseparam,
 946        .get_wol = netxen_nic_get_wol,
 947        .set_wol = netxen_nic_set_wol,
 948        .self_test = netxen_nic_diag_test,
 949        .get_strings = netxen_nic_get_strings,
 950        .get_ethtool_stats = netxen_nic_get_ethtool_stats,
 951        .get_sset_count = netxen_get_sset_count,
 952        .get_coalesce = netxen_get_intr_coalesce,
 953        .set_coalesce = netxen_set_intr_coalesce,
 954        .get_dump_flag = netxen_get_dump_flag,
 955        .get_dump_data = netxen_get_dump_data,
 956        .set_dump = netxen_set_dump,
 957};
 958