linux/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
<<
>>
Prefs
   1/*
   2 * QLogic qlcnic NIC Driver
   3 * Copyright (c)  2009-2010 QLogic Corporation
   4 *
   5 * See LICENSE.qlcnic for copyright and licensing details.
   6 */
   7
   8#include <linux/types.h>
   9#include <linux/delay.h>
  10#include <linux/pci.h>
  11#include <linux/io.h>
  12#include <linux/netdevice.h>
  13#include <linux/ethtool.h>
  14
  15#include "qlcnic.h"
  16
  17struct qlcnic_stats {
  18        char stat_string[ETH_GSTRING_LEN];
  19        int sizeof_stat;
  20        int stat_offset;
  21};
  22
  23#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
  24#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
  25
  26static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
  27        {"xmit_called",
  28                QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)},
  29        {"xmit_finished",
  30                QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)},
  31        {"rx_dropped",
  32                QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
  33        {"tx_dropped",
  34                QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
  35        {"csummed",
  36                QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
  37        {"rx_pkts",
  38                QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
  39        {"lro_pkts",
  40                QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
  41        {"rx_bytes",
  42                QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
  43        {"tx_bytes",
  44                QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
  45        {"lrobytes",
  46                QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
  47        {"lso_frames",
  48                QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
  49        {"xmit_on",
  50                QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
  51        {"xmit_off",
  52                QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
  53        {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
  54                QLC_OFF(stats.skb_alloc_failure)},
  55        {"null rxbuf",
  56                QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
  57        {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
  58                                         QLC_OFF(stats.rx_dma_map_error)},
  59        {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
  60                                         QLC_OFF(stats.tx_dma_map_error)},
  61
  62};
  63
  64static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
  65        "rx unicast frames",
  66        "rx multicast frames",
  67        "rx broadcast frames",
  68        "rx dropped frames",
  69        "rx errors",
  70        "rx local frames",
  71        "rx numbytes",
  72        "tx unicast frames",
  73        "tx multicast frames",
  74        "tx broadcast frames",
  75        "tx dropped frames",
  76        "tx errors",
  77        "tx local frames",
  78        "tx numbytes",
  79};
  80
  81#define QLCNIC_STATS_LEN        ARRAY_SIZE(qlcnic_gstrings_stats)
  82#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
  83
  84static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
  85        "Register_Test_on_offline",
  86        "Link_Test_on_offline",
  87        "Interrupt_Test_offline",
  88        "Internal_Loopback_offline",
  89        "External_Loopback_offline"
  90};
  91
  92#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
  93
  94#define QLCNIC_RING_REGS_COUNT  20
  95#define QLCNIC_RING_REGS_LEN    (QLCNIC_RING_REGS_COUNT * sizeof(u32))
  96#define QLCNIC_MAX_EEPROM_LEN   1024
  97
  98static const u32 diag_registers[] = {
  99        CRB_CMDPEG_STATE,
 100        CRB_RCVPEG_STATE,
 101        CRB_XG_STATE_P3P,
 102        CRB_FW_CAPABILITIES_1,
 103        ISR_INT_STATE_REG,
 104        QLCNIC_CRB_DRV_ACTIVE,
 105        QLCNIC_CRB_DEV_STATE,
 106        QLCNIC_CRB_DRV_STATE,
 107        QLCNIC_CRB_DRV_SCRATCH,
 108        QLCNIC_CRB_DEV_PARTITION_INFO,
 109        QLCNIC_CRB_DRV_IDC_VER,
 110        QLCNIC_PEG_ALIVE_COUNTER,
 111        QLCNIC_PEG_HALT_STATUS1,
 112        QLCNIC_PEG_HALT_STATUS2,
 113        QLCNIC_CRB_PEG_NET_0+0x3c,
 114        QLCNIC_CRB_PEG_NET_1+0x3c,
 115        QLCNIC_CRB_PEG_NET_2+0x3c,
 116        QLCNIC_CRB_PEG_NET_4+0x3c,
 117        -1
 118};
 119
 120#define QLCNIC_MGMT_API_VERSION 2
 121#define QLCNIC_DEV_INFO_SIZE    1
 122#define QLCNIC_ETHTOOL_REGS_VER 2
 123static int qlcnic_get_regs_len(struct net_device *dev)
 124{
 125        return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
 126                                QLCNIC_DEV_INFO_SIZE + 1;
 127}
 128
 129static int qlcnic_get_eeprom_len(struct net_device *dev)
 130{
 131        return QLCNIC_FLASH_TOTAL_SIZE;
 132}
 133
 134static void
 135qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 136{
 137        struct qlcnic_adapter *adapter = netdev_priv(dev);
 138        u32 fw_major, fw_minor, fw_build;
 139
 140        fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
 141        fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
 142        fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
 143        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 144                "%d.%d.%d", fw_major, fw_minor, fw_build);
 145
 146        strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
 147                sizeof(drvinfo->bus_info));
 148        strlcpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
 149        strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
 150                sizeof(drvinfo->version));
 151}
 152
 153static int
 154qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 155{
 156        struct qlcnic_adapter *adapter = netdev_priv(dev);
 157        int check_sfp_module = 0;
 158
 159        /* read which mode */
 160        if (adapter->ahw->port_type == QLCNIC_GBE) {
 161                ecmd->supported = (SUPPORTED_10baseT_Half |
 162                                   SUPPORTED_10baseT_Full |
 163                                   SUPPORTED_100baseT_Half |
 164                                   SUPPORTED_100baseT_Full |
 165                                   SUPPORTED_1000baseT_Half |
 166                                   SUPPORTED_1000baseT_Full);
 167
 168                ecmd->advertising = (ADVERTISED_100baseT_Half |
 169                                     ADVERTISED_100baseT_Full |
 170                                     ADVERTISED_1000baseT_Half |
 171                                     ADVERTISED_1000baseT_Full);
 172
 173                ethtool_cmd_speed_set(ecmd, adapter->link_speed);
 174                ecmd->duplex = adapter->link_duplex;
 175                ecmd->autoneg = adapter->link_autoneg;
 176
 177        } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
 178                u32 val;
 179
 180                val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
 181                if (val == QLCNIC_PORT_MODE_802_3_AP) {
 182                        ecmd->supported = SUPPORTED_1000baseT_Full;
 183                        ecmd->advertising = ADVERTISED_1000baseT_Full;
 184                } else {
 185                        ecmd->supported = SUPPORTED_10000baseT_Full;
 186                        ecmd->advertising = ADVERTISED_10000baseT_Full;
 187                }
 188
 189                if (netif_running(dev) && adapter->has_link_events) {
 190                        ethtool_cmd_speed_set(ecmd, adapter->link_speed);
 191                        ecmd->autoneg = adapter->link_autoneg;
 192                        ecmd->duplex = adapter->link_duplex;
 193                        goto skip;
 194                }
 195
 196                ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
 197                ecmd->duplex = DUPLEX_UNKNOWN;
 198                ecmd->autoneg = AUTONEG_DISABLE;
 199        } else
 200                return -EIO;
 201
 202skip:
 203        ecmd->phy_address = adapter->physical_port;
 204        ecmd->transceiver = XCVR_EXTERNAL;
 205
 206        switch (adapter->ahw->board_type) {
 207        case QLCNIC_BRDTYPE_P3P_REF_QG:
 208        case QLCNIC_BRDTYPE_P3P_4_GB:
 209        case QLCNIC_BRDTYPE_P3P_4_GB_MM:
 210
 211                ecmd->supported |= SUPPORTED_Autoneg;
 212                ecmd->advertising |= ADVERTISED_Autoneg;
 213        case QLCNIC_BRDTYPE_P3P_10G_CX4:
 214        case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
 215        case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
 216                ecmd->supported |= SUPPORTED_TP;
 217                ecmd->advertising |= ADVERTISED_TP;
 218                ecmd->port = PORT_TP;
 219                ecmd->autoneg =  adapter->link_autoneg;
 220                break;
 221        case QLCNIC_BRDTYPE_P3P_IMEZ:
 222        case QLCNIC_BRDTYPE_P3P_XG_LOM:
 223        case QLCNIC_BRDTYPE_P3P_HMEZ:
 224                ecmd->supported |= SUPPORTED_MII;
 225                ecmd->advertising |= ADVERTISED_MII;
 226                ecmd->port = PORT_MII;
 227                ecmd->autoneg = AUTONEG_DISABLE;
 228                break;
 229        case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
 230        case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
 231        case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
 232                ecmd->advertising |= ADVERTISED_TP;
 233                ecmd->supported |= SUPPORTED_TP;
 234                check_sfp_module = netif_running(dev) &&
 235                        adapter->has_link_events;
 236        case QLCNIC_BRDTYPE_P3P_10G_XFP:
 237                ecmd->supported |= SUPPORTED_FIBRE;
 238                ecmd->advertising |= ADVERTISED_FIBRE;
 239                ecmd->port = PORT_FIBRE;
 240                ecmd->autoneg = AUTONEG_DISABLE;
 241                break;
 242        case QLCNIC_BRDTYPE_P3P_10G_TP:
 243                if (adapter->ahw->port_type == QLCNIC_XGBE) {
 244                        ecmd->autoneg = AUTONEG_DISABLE;
 245                        ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
 246                        ecmd->advertising |=
 247                                (ADVERTISED_FIBRE | ADVERTISED_TP);
 248                        ecmd->port = PORT_FIBRE;
 249                        check_sfp_module = netif_running(dev) &&
 250                                adapter->has_link_events;
 251                } else {
 252                        ecmd->autoneg = AUTONEG_ENABLE;
 253                        ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
 254                        ecmd->advertising |=
 255                                (ADVERTISED_TP | ADVERTISED_Autoneg);
 256                        ecmd->port = PORT_TP;
 257                }
 258                break;
 259        default:
 260                dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
 261                        adapter->ahw->board_type);
 262                return -EIO;
 263        }
 264
 265        if (check_sfp_module) {
 266                switch (adapter->module_type) {
 267                case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
 268                case LINKEVENT_MODULE_OPTICAL_SRLR:
 269                case LINKEVENT_MODULE_OPTICAL_LRM:
 270                case LINKEVENT_MODULE_OPTICAL_SFP_1G:
 271                        ecmd->port = PORT_FIBRE;
 272                        break;
 273                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
 274                case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
 275                case LINKEVENT_MODULE_TWINAX:
 276                        ecmd->port = PORT_TP;
 277                        break;
 278                default:
 279                        ecmd->port = PORT_OTHER;
 280                }
 281        }
 282
 283        return 0;
 284}
 285
 286static int
 287qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 288{
 289        u32 config = 0;
 290        u32 ret = 0;
 291        struct qlcnic_adapter *adapter = netdev_priv(dev);
 292
 293        if (adapter->ahw->port_type != QLCNIC_GBE)
 294                return -EOPNOTSUPP;
 295
 296        /* read which mode */
 297        if (ecmd->duplex)
 298                config |= 0x1;
 299
 300        if (ecmd->autoneg)
 301                config |= 0x2;
 302
 303        switch (ethtool_cmd_speed(ecmd)) {
 304        case SPEED_10:
 305                config |= (0 << 8);
 306                break;
 307        case SPEED_100:
 308                config |= (1 << 8);
 309                break;
 310        case SPEED_1000:
 311                config |= (10 << 8);
 312                break;
 313        default:
 314                return -EIO;
 315        }
 316
 317        ret = qlcnic_fw_cmd_set_port(adapter, config);
 318
 319        if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
 320                return -EOPNOTSUPP;
 321        else if (ret)
 322                return -EIO;
 323
 324        adapter->link_speed = ethtool_cmd_speed(ecmd);
 325        adapter->link_duplex = ecmd->duplex;
 326        adapter->link_autoneg = ecmd->autoneg;
 327
 328        if (!netif_running(dev))
 329                return 0;
 330
 331        dev->netdev_ops->ndo_stop(dev);
 332        return dev->netdev_ops->ndo_open(dev);
 333}
 334
 335static void
 336qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 337{
 338        struct qlcnic_adapter *adapter = netdev_priv(dev);
 339        struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 340        struct qlcnic_host_sds_ring *sds_ring;
 341        u32 *regs_buff = p;
 342        int ring, i = 0, j = 0;
 343
 344        memset(p, 0, qlcnic_get_regs_len(dev));
 345        regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
 346                (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
 347
 348        regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
 349        regs_buff[1] = QLCNIC_MGMT_API_VERSION;
 350
 351        for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
 352                regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
 353
 354        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
 355                return;
 356
 357        regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
 358
 359        regs_buff[i++] = 1; /* No. of tx ring */
 360        regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
 361        regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
 362
 363        regs_buff[i++] = 2; /* No. of rx ring */
 364        regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
 365        regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
 366
 367        regs_buff[i++] = adapter->max_sds_rings;
 368
 369        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 370                sds_ring = &(recv_ctx->sds_rings[ring]);
 371                regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
 372        }
 373}
 374
 375static u32 qlcnic_test_link(struct net_device *dev)
 376{
 377        struct qlcnic_adapter *adapter = netdev_priv(dev);
 378        u32 val;
 379
 380        val = QLCRD32(adapter, CRB_XG_STATE_P3P);
 381        val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
 382        return (val == XG_LINK_UP_P3P) ? 0 : 1;
 383}
 384
 385static int
 386qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 387                      u8 *bytes)
 388{
 389        struct qlcnic_adapter *adapter = netdev_priv(dev);
 390        int offset;
 391        int ret;
 392
 393        if (eeprom->len == 0)
 394                return -EINVAL;
 395
 396        eeprom->magic = (adapter->pdev)->vendor |
 397                        ((adapter->pdev)->device << 16);
 398        offset = eeprom->offset;
 399
 400        ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
 401                                                eeprom->len);
 402        if (ret < 0)
 403                return ret;
 404
 405        return 0;
 406}
 407
 408static void
 409qlcnic_get_ringparam(struct net_device *dev,
 410                struct ethtool_ringparam *ring)
 411{
 412        struct qlcnic_adapter *adapter = netdev_priv(dev);
 413
 414        ring->rx_pending = adapter->num_rxd;
 415        ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
 416        ring->tx_pending = adapter->num_txd;
 417
 418        ring->rx_max_pending = adapter->max_rxd;
 419        ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
 420        ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
 421}
 422
 423static u32
 424qlcnic_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                       qlcnic_driver_name, r_name, num_desc, val);
 434        }
 435
 436        return num_desc;
 437}
 438
 439static int
 440qlcnic_set_ringparam(struct net_device *dev,
 441                struct ethtool_ringparam *ring)
 442{
 443        struct qlcnic_adapter *adapter = netdev_priv(dev);
 444        u16 num_rxd, num_jumbo_rxd, num_txd;
 445
 446        if (ring->rx_mini_pending)
 447                return -EOPNOTSUPP;
 448
 449        num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
 450                        MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
 451
 452        num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
 453                        MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
 454                                                "rx jumbo");
 455
 456        num_txd = qlcnic_validate_ringparam(ring->tx_pending,
 457                        MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
 458
 459        if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
 460                        num_jumbo_rxd == adapter->num_jumbo_rxd)
 461                return 0;
 462
 463        adapter->num_rxd = num_rxd;
 464        adapter->num_jumbo_rxd = num_jumbo_rxd;
 465        adapter->num_txd = num_txd;
 466
 467        return qlcnic_reset_context(adapter);
 468}
 469
 470static void qlcnic_get_channels(struct net_device *dev,
 471                struct ethtool_channels *channel)
 472{
 473        struct qlcnic_adapter *adapter = netdev_priv(dev);
 474
 475        channel->max_rx = rounddown_pow_of_two(min_t(int,
 476                        adapter->max_rx_ques, num_online_cpus()));
 477        channel->max_tx = adapter->max_tx_ques;
 478
 479        channel->rx_count = adapter->max_sds_rings;
 480        channel->tx_count = adapter->max_tx_ques;
 481}
 482
 483static int qlcnic_set_channels(struct net_device *dev,
 484                struct ethtool_channels *channel)
 485{
 486        struct qlcnic_adapter *adapter = netdev_priv(dev);
 487        int err;
 488
 489        if (channel->other_count || channel->combined_count ||
 490            channel->tx_count != channel->max_tx)
 491                return -EINVAL;
 492
 493        err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count);
 494        if (err)
 495                return err;
 496
 497        err = qlcnic_set_max_rss(adapter, channel->rx_count);
 498        netdev_info(dev, "allocated 0x%x sds rings\n",
 499                                 adapter->max_sds_rings);
 500        return err;
 501}
 502
 503static void
 504qlcnic_get_pauseparam(struct net_device *netdev,
 505                          struct ethtool_pauseparam *pause)
 506{
 507        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 508        int port = adapter->physical_port;
 509        __u32 val;
 510
 511        if (adapter->ahw->port_type == QLCNIC_GBE) {
 512                if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
 513                        return;
 514                /* get flow control settings */
 515                val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
 516                pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
 517                val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
 518                switch (port) {
 519                case 0:
 520                        pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
 521                        break;
 522                case 1:
 523                        pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
 524                        break;
 525                case 2:
 526                        pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
 527                        break;
 528                case 3:
 529                default:
 530                        pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
 531                        break;
 532                }
 533        } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
 534                if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
 535                        return;
 536                pause->rx_pause = 1;
 537                val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
 538                if (port == 0)
 539                        pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
 540                else
 541                        pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
 542        } else {
 543                dev_err(&netdev->dev, "Unknown board type: %x\n",
 544                                        adapter->ahw->port_type);
 545        }
 546}
 547
 548static int
 549qlcnic_set_pauseparam(struct net_device *netdev,
 550                          struct ethtool_pauseparam *pause)
 551{
 552        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 553        int port = adapter->physical_port;
 554        __u32 val;
 555
 556        /* read mode */
 557        if (adapter->ahw->port_type == QLCNIC_GBE) {
 558                if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
 559                        return -EIO;
 560                /* set flow control */
 561                val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
 562
 563                if (pause->rx_pause)
 564                        qlcnic_gb_rx_flowctl(val);
 565                else
 566                        qlcnic_gb_unset_rx_flowctl(val);
 567
 568                QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
 569                                val);
 570                /* set autoneg */
 571                val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
 572                switch (port) {
 573                case 0:
 574                        if (pause->tx_pause)
 575                                qlcnic_gb_unset_gb0_mask(val);
 576                        else
 577                                qlcnic_gb_set_gb0_mask(val);
 578                        break;
 579                case 1:
 580                        if (pause->tx_pause)
 581                                qlcnic_gb_unset_gb1_mask(val);
 582                        else
 583                                qlcnic_gb_set_gb1_mask(val);
 584                        break;
 585                case 2:
 586                        if (pause->tx_pause)
 587                                qlcnic_gb_unset_gb2_mask(val);
 588                        else
 589                                qlcnic_gb_set_gb2_mask(val);
 590                        break;
 591                case 3:
 592                default:
 593                        if (pause->tx_pause)
 594                                qlcnic_gb_unset_gb3_mask(val);
 595                        else
 596                                qlcnic_gb_set_gb3_mask(val);
 597                        break;
 598                }
 599                QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
 600        } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
 601                if (!pause->rx_pause || pause->autoneg)
 602                        return -EOPNOTSUPP;
 603
 604                if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
 605                        return -EIO;
 606
 607                val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
 608                if (port == 0) {
 609                        if (pause->tx_pause)
 610                                qlcnic_xg_unset_xg0_mask(val);
 611                        else
 612                                qlcnic_xg_set_xg0_mask(val);
 613                } else {
 614                        if (pause->tx_pause)
 615                                qlcnic_xg_unset_xg1_mask(val);
 616                        else
 617                                qlcnic_xg_set_xg1_mask(val);
 618                }
 619                QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
 620        } else {
 621                dev_err(&netdev->dev, "Unknown board type: %x\n",
 622                                adapter->ahw->port_type);
 623        }
 624        return 0;
 625}
 626
 627static int qlcnic_reg_test(struct net_device *dev)
 628{
 629        struct qlcnic_adapter *adapter = netdev_priv(dev);
 630        u32 data_read;
 631
 632        data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
 633        if ((data_read & 0xffff) != adapter->pdev->vendor)
 634                return 1;
 635
 636        return 0;
 637}
 638
 639static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 640{
 641        struct qlcnic_adapter *adapter = netdev_priv(dev);
 642        switch (sset) {
 643        case ETH_SS_TEST:
 644                return QLCNIC_TEST_LEN;
 645        case ETH_SS_STATS:
 646                if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
 647                        return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
 648                return QLCNIC_STATS_LEN;
 649        default:
 650                return -EOPNOTSUPP;
 651        }
 652}
 653
 654static int qlcnic_irq_test(struct net_device *netdev)
 655{
 656        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 657        int max_sds_rings = adapter->max_sds_rings;
 658        int ret;
 659        struct qlcnic_cmd_args cmd;
 660
 661        if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
 662                return -EIO;
 663
 664        ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
 665        if (ret)
 666                goto clear_it;
 667
 668        adapter->diag_cnt = 0;
 669        memset(&cmd, 0, sizeof(cmd));
 670        cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
 671        cmd.req.arg1 = adapter->ahw->pci_func;
 672        qlcnic_issue_cmd(adapter, &cmd);
 673        ret = cmd.rsp.cmd;
 674
 675        if (ret)
 676                goto done;
 677
 678        msleep(10);
 679
 680        ret = !adapter->diag_cnt;
 681
 682done:
 683        qlcnic_diag_free_res(netdev, max_sds_rings);
 684
 685clear_it:
 686        adapter->max_sds_rings = max_sds_rings;
 687        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 688        return ret;
 689}
 690
 691#define QLCNIC_ILB_PKT_SIZE 64
 692#define QLCNIC_NUM_ILB_PKT      16
 693#define QLCNIC_ILB_MAX_RCV_LOOP 10
 694
 695static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
 696{
 697        unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
 698
 699        memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
 700
 701        memcpy(data, mac, ETH_ALEN);
 702        memcpy(data + ETH_ALEN, mac, ETH_ALEN);
 703
 704        memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
 705}
 706
 707int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
 708{
 709        unsigned char buff[QLCNIC_ILB_PKT_SIZE];
 710        qlcnic_create_loopback_buff(buff, mac);
 711        return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
 712}
 713
 714static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
 715{
 716        struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 717        struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
 718        struct sk_buff *skb;
 719        int i, loop, cnt = 0;
 720
 721        for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
 722                skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
 723                qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
 724                skb_put(skb, QLCNIC_ILB_PKT_SIZE);
 725
 726                adapter->diag_cnt = 0;
 727                qlcnic_xmit_frame(skb, adapter->netdev);
 728
 729                loop = 0;
 730                do {
 731                        msleep(1);
 732                        qlcnic_process_rcv_ring_diag(sds_ring);
 733                        if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
 734                                break;
 735                } while (!adapter->diag_cnt);
 736
 737                dev_kfree_skb_any(skb);
 738
 739                if (!adapter->diag_cnt)
 740                        QLCDB(adapter, DRV,
 741                        "LB Test: packet #%d was not received\n", i + 1);
 742                else
 743                        cnt++;
 744        }
 745        if (cnt != i) {
 746                dev_warn(&adapter->pdev->dev, "LB Test failed\n");
 747                if (mode != QLCNIC_ILB_MODE) {
 748                        dev_warn(&adapter->pdev->dev,
 749                                "WARNING: Please make sure external"
 750                                "loopback connector is plugged in\n");
 751                }
 752                return -1;
 753        }
 754        return 0;
 755}
 756
 757static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
 758{
 759        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 760        int max_sds_rings = adapter->max_sds_rings;
 761        struct qlcnic_host_sds_ring *sds_ring;
 762        int loop = 0;
 763        int ret;
 764
 765        if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
 766                netdev_info(netdev, "Firmware is not loopback test capable\n");
 767                return -EOPNOTSUPP;
 768        }
 769
 770        QLCDB(adapter, DRV, "%s loopback test in progress\n",
 771                   mode == QLCNIC_ILB_MODE ? "internal" : "external");
 772        if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
 773                netdev_warn(netdev, "Loopback test not supported for non "
 774                                "privilege function\n");
 775                return 0;
 776        }
 777
 778        if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
 779                return -EBUSY;
 780
 781        ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
 782        if (ret)
 783                goto clear_it;
 784
 785        sds_ring = &adapter->recv_ctx->sds_rings[0];
 786
 787        ret = qlcnic_set_lb_mode(adapter, mode);
 788        if (ret)
 789                goto free_res;
 790
 791        adapter->diag_cnt = 0;
 792        do {
 793                msleep(500);
 794                qlcnic_process_rcv_ring_diag(sds_ring);
 795                if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
 796                        netdev_info(netdev, "firmware didnt respond to loopback"
 797                                " configure request\n");
 798                        ret = -QLCNIC_FW_NOT_RESPOND;
 799                        goto free_res;
 800                } else if (adapter->diag_cnt) {
 801                        ret = adapter->diag_cnt;
 802                        goto free_res;
 803                }
 804        } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
 805
 806        ret = qlcnic_do_lb_test(adapter, mode);
 807
 808        qlcnic_clear_lb_mode(adapter);
 809
 810 free_res:
 811        qlcnic_diag_free_res(netdev, max_sds_rings);
 812
 813 clear_it:
 814        adapter->max_sds_rings = max_sds_rings;
 815        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 816        return ret;
 817}
 818
 819static void
 820qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 821                     u64 *data)
 822{
 823        memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
 824
 825        data[0] = qlcnic_reg_test(dev);
 826        if (data[0])
 827                eth_test->flags |= ETH_TEST_FL_FAILED;
 828
 829        data[1] = (u64) qlcnic_test_link(dev);
 830        if (data[1])
 831                eth_test->flags |= ETH_TEST_FL_FAILED;
 832
 833        if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
 834                data[2] = qlcnic_irq_test(dev);
 835                if (data[2])
 836                        eth_test->flags |= ETH_TEST_FL_FAILED;
 837
 838                data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
 839                if (data[3])
 840                        eth_test->flags |= ETH_TEST_FL_FAILED;
 841                if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
 842                        data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
 843                        if (data[4])
 844                                eth_test->flags |= ETH_TEST_FL_FAILED;
 845                        eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
 846                }
 847        }
 848}
 849
 850static void
 851qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 852{
 853        struct qlcnic_adapter *adapter = netdev_priv(dev);
 854        int index, i;
 855
 856        switch (stringset) {
 857        case ETH_SS_TEST:
 858                memcpy(data, *qlcnic_gstrings_test,
 859                       QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
 860                break;
 861        case ETH_SS_STATS:
 862                for (index = 0; index < QLCNIC_STATS_LEN; index++) {
 863                        memcpy(data + index * ETH_GSTRING_LEN,
 864                               qlcnic_gstrings_stats[index].stat_string,
 865                               ETH_GSTRING_LEN);
 866                }
 867                if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
 868                        return;
 869                for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
 870                        memcpy(data + index * ETH_GSTRING_LEN,
 871                               qlcnic_device_gstrings_stats[i],
 872                               ETH_GSTRING_LEN);
 873                }
 874        }
 875}
 876
 877#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
 878        (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
 879
 880static void
 881qlcnic_fill_device_stats(int *index, u64 *data,
 882                struct __qlcnic_esw_statistics *stats)
 883{
 884        int ind = *index;
 885
 886        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
 887        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
 888        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
 889        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
 890        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
 891        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
 892        data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
 893
 894        *index = ind;
 895}
 896
 897static void
 898qlcnic_get_ethtool_stats(struct net_device *dev,
 899                             struct ethtool_stats *stats, u64 * data)
 900{
 901        struct qlcnic_adapter *adapter = netdev_priv(dev);
 902        struct qlcnic_esw_statistics port_stats;
 903        int index, ret;
 904
 905        for (index = 0; index < QLCNIC_STATS_LEN; index++) {
 906                char *p =
 907                    (char *)adapter +
 908                    qlcnic_gstrings_stats[index].stat_offset;
 909                data[index] =
 910                    (qlcnic_gstrings_stats[index].sizeof_stat ==
 911                     sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
 912        }
 913
 914        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
 915                return;
 916
 917        memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
 918        ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
 919                        QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
 920        if (ret)
 921                return;
 922
 923        qlcnic_fill_device_stats(&index, data, &port_stats.rx);
 924
 925        ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
 926                        QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
 927        if (ret)
 928                return;
 929
 930        qlcnic_fill_device_stats(&index, data, &port_stats.tx);
 931}
 932
 933static int qlcnic_set_led(struct net_device *dev,
 934                          enum ethtool_phys_id_state state)
 935{
 936        struct qlcnic_adapter *adapter = netdev_priv(dev);
 937        int max_sds_rings = adapter->max_sds_rings;
 938        int err = -EIO, active = 1;
 939
 940        if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
 941                netdev_warn(dev, "LED test not supported for non "
 942                                "privilege function\n");
 943                return -EOPNOTSUPP;
 944        }
 945
 946        switch (state) {
 947        case ETHTOOL_ID_ACTIVE:
 948                if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
 949                        return -EBUSY;
 950
 951                if (test_bit(__QLCNIC_RESETTING, &adapter->state))
 952                        break;
 953
 954                if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
 955                        if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
 956                                break;
 957                        set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
 958                }
 959
 960                if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
 961                        err = 0;
 962                        break;
 963                }
 964
 965                dev_err(&adapter->pdev->dev,
 966                        "Failed to set LED blink state.\n");
 967                break;
 968
 969        case ETHTOOL_ID_INACTIVE:
 970                active = 0;
 971
 972                if (test_bit(__QLCNIC_RESETTING, &adapter->state))
 973                        break;
 974
 975                if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
 976                        if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
 977                                break;
 978                        set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
 979                }
 980
 981                if (adapter->nic_ops->config_led(adapter, 0, 0xf))
 982                        dev_err(&adapter->pdev->dev,
 983                                "Failed to reset LED blink state.\n");
 984
 985                break;
 986
 987        default:
 988                return -EINVAL;
 989        }
 990
 991        if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
 992                qlcnic_diag_free_res(dev, max_sds_rings);
 993
 994        if (!active || err)
 995                clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
 996
 997        return err;
 998}
 999
1000static void
1001qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1002{
1003        struct qlcnic_adapter *adapter = netdev_priv(dev);
1004        u32 wol_cfg;
1005
1006        wol->supported = 0;
1007        wol->wolopts = 0;
1008
1009        wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1010        if (wol_cfg & (1UL << adapter->portnum))
1011                wol->supported |= WAKE_MAGIC;
1012
1013        wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1014        if (wol_cfg & (1UL << adapter->portnum))
1015                wol->wolopts |= WAKE_MAGIC;
1016}
1017
1018static int
1019qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1020{
1021        struct qlcnic_adapter *adapter = netdev_priv(dev);
1022        u32 wol_cfg;
1023
1024        if (wol->wolopts & ~WAKE_MAGIC)
1025                return -EOPNOTSUPP;
1026
1027        wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1028        if (!(wol_cfg & (1 << adapter->portnum)))
1029                return -EOPNOTSUPP;
1030
1031        wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1032        if (wol->wolopts & WAKE_MAGIC)
1033                wol_cfg |= 1UL << adapter->portnum;
1034        else
1035                wol_cfg &= ~(1UL << adapter->portnum);
1036
1037        QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1038
1039        return 0;
1040}
1041
1042/*
1043 * Set the coalescing parameters. Currently only normal is supported.
1044 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1045 * firmware coalescing to default.
1046 */
1047static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1048                        struct ethtool_coalesce *ethcoal)
1049{
1050        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1051
1052        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
1053                return -EINVAL;
1054
1055        /*
1056        * Return Error if unsupported values or
1057        * unsupported parameters are set.
1058        */
1059        if (ethcoal->rx_coalesce_usecs > 0xffff ||
1060                ethcoal->rx_max_coalesced_frames > 0xffff ||
1061                ethcoal->tx_coalesce_usecs ||
1062                ethcoal->tx_max_coalesced_frames ||
1063                ethcoal->rx_coalesce_usecs_irq ||
1064                ethcoal->rx_max_coalesced_frames_irq ||
1065                ethcoal->tx_coalesce_usecs_irq ||
1066                ethcoal->tx_max_coalesced_frames_irq ||
1067                ethcoal->stats_block_coalesce_usecs ||
1068                ethcoal->use_adaptive_rx_coalesce ||
1069                ethcoal->use_adaptive_tx_coalesce ||
1070                ethcoal->pkt_rate_low ||
1071                ethcoal->rx_coalesce_usecs_low ||
1072                ethcoal->rx_max_coalesced_frames_low ||
1073                ethcoal->tx_coalesce_usecs_low ||
1074                ethcoal->tx_max_coalesced_frames_low ||
1075                ethcoal->pkt_rate_high ||
1076                ethcoal->rx_coalesce_usecs_high ||
1077                ethcoal->rx_max_coalesced_frames_high ||
1078                ethcoal->tx_coalesce_usecs_high ||
1079                ethcoal->tx_max_coalesced_frames_high)
1080                return -EINVAL;
1081
1082        if (!ethcoal->rx_coalesce_usecs ||
1083                !ethcoal->rx_max_coalesced_frames) {
1084                adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
1085                adapter->ahw->coal.rx_time_us =
1086                        QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
1087                adapter->ahw->coal.rx_packets =
1088                        QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
1089        } else {
1090                adapter->ahw->coal.flag = 0;
1091                adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
1092                adapter->ahw->coal.rx_packets =
1093                        ethcoal->rx_max_coalesced_frames;
1094        }
1095
1096        qlcnic_config_intr_coalesce(adapter);
1097
1098        return 0;
1099}
1100
1101static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1102                        struct ethtool_coalesce *ethcoal)
1103{
1104        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1105
1106        if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1107                return -EINVAL;
1108
1109        ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1110        ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
1111
1112        return 0;
1113}
1114
1115static u32 qlcnic_get_msglevel(struct net_device *netdev)
1116{
1117        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1118
1119        return adapter->msg_enable;
1120}
1121
1122static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1123{
1124        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1125
1126        adapter->msg_enable = msglvl;
1127}
1128
1129static int
1130qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1131{
1132        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1133        struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1134
1135        if (fw_dump->clr)
1136                dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
1137        else
1138                dump->len = 0;
1139        dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1140        dump->version = adapter->fw_version;
1141        return 0;
1142}
1143
1144static int
1145qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1146                        void *buffer)
1147{
1148        int i, copy_sz;
1149        u32 *hdr_ptr, *data;
1150        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1151        struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1152
1153        if (!fw_dump->clr) {
1154                netdev_info(netdev, "Dump not available\n");
1155                return -EINVAL;
1156        }
1157        /* Copy template header first */
1158        copy_sz = fw_dump->tmpl_hdr->size;
1159        hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
1160        data = buffer;
1161        for (i = 0; i < copy_sz/sizeof(u32); i++)
1162                *data++ = cpu_to_le32(*hdr_ptr++);
1163
1164        /* Copy captured dump data */
1165        memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1166        dump->len = copy_sz + fw_dump->size;
1167        dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1168
1169        /* Free dump area once data has been captured */
1170        vfree(fw_dump->data);
1171        fw_dump->data = NULL;
1172        fw_dump->clr = 0;
1173        netdev_info(netdev, "extracted the FW dump Successfully\n");
1174        return 0;
1175}
1176
1177static int
1178qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1179{
1180        int ret = 0;
1181        struct qlcnic_adapter *adapter = netdev_priv(netdev);
1182        struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1183
1184        switch (val->flag) {
1185        case QLCNIC_FORCE_FW_DUMP_KEY:
1186                if (!fw_dump->enable) {
1187                        netdev_info(netdev, "FW dump not enabled\n");
1188                        return ret;
1189                }
1190                if (fw_dump->clr) {
1191                        netdev_info(netdev,
1192                        "Previous dump not cleared, not forcing dump\n");
1193                        return ret;
1194                }
1195                netdev_info(netdev, "Forcing a FW dump\n");
1196                qlcnic_dev_request_reset(adapter);
1197                break;
1198        case QLCNIC_DISABLE_FW_DUMP:
1199                if (fw_dump->enable) {
1200                        netdev_info(netdev, "Disabling FW dump\n");
1201                        fw_dump->enable = 0;
1202                }
1203                break;
1204        case QLCNIC_ENABLE_FW_DUMP:
1205                if (!fw_dump->enable && fw_dump->tmpl_hdr) {
1206                        netdev_info(netdev, "Enabling FW dump\n");
1207                        fw_dump->enable = 1;
1208                }
1209                break;
1210        case QLCNIC_FORCE_FW_RESET:
1211                netdev_info(netdev, "Forcing a FW reset\n");
1212                qlcnic_dev_request_reset(adapter);
1213                adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
1214                break;
1215        default:
1216                if (val->flag > QLCNIC_DUMP_MASK_MAX ||
1217                        val->flag < QLCNIC_DUMP_MASK_MIN) {
1218                                netdev_info(netdev,
1219                                "Invalid dump level: 0x%x\n", val->flag);
1220                                ret = -EINVAL;
1221                                goto out;
1222                }
1223                fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff;
1224                netdev_info(netdev, "Driver mask changed to: 0x%x\n",
1225                        fw_dump->tmpl_hdr->drv_cap_mask);
1226        }
1227out:
1228        return ret;
1229}
1230
1231const struct ethtool_ops qlcnic_ethtool_ops = {
1232        .get_settings = qlcnic_get_settings,
1233        .set_settings = qlcnic_set_settings,
1234        .get_drvinfo = qlcnic_get_drvinfo,
1235        .get_regs_len = qlcnic_get_regs_len,
1236        .get_regs = qlcnic_get_regs,
1237        .get_link = ethtool_op_get_link,
1238        .get_eeprom_len = qlcnic_get_eeprom_len,
1239        .get_eeprom = qlcnic_get_eeprom,
1240        .get_ringparam = qlcnic_get_ringparam,
1241        .set_ringparam = qlcnic_set_ringparam,
1242        .get_channels = qlcnic_get_channels,
1243        .set_channels = qlcnic_set_channels,
1244        .get_pauseparam = qlcnic_get_pauseparam,
1245        .set_pauseparam = qlcnic_set_pauseparam,
1246        .get_wol = qlcnic_get_wol,
1247        .set_wol = qlcnic_set_wol,
1248        .self_test = qlcnic_diag_test,
1249        .get_strings = qlcnic_get_strings,
1250        .get_ethtool_stats = qlcnic_get_ethtool_stats,
1251        .get_sset_count = qlcnic_get_sset_count,
1252        .get_coalesce = qlcnic_get_intr_coalesce,
1253        .set_coalesce = qlcnic_set_intr_coalesce,
1254        .set_phys_id = qlcnic_set_led,
1255        .set_msglevel = qlcnic_set_msglevel,
1256        .get_msglevel = qlcnic_get_msglevel,
1257        .get_dump_flag = qlcnic_get_dump_flag,
1258        .get_dump_data = qlcnic_get_dump_data,
1259        .set_dump = qlcnic_set_dump,
1260};
1261