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