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