linux/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
<<
>>
Prefs
   1/*
   2 * aQuantia Corporation Network Driver
   3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 */
   9
  10/* File aq_ethtool.c: Definition of ethertool related functions. */
  11
  12#include "aq_ethtool.h"
  13#include "aq_nic.h"
  14#include "aq_vec.h"
  15#include "aq_filters.h"
  16
  17static void aq_ethtool_get_regs(struct net_device *ndev,
  18                                struct ethtool_regs *regs, void *p)
  19{
  20        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  21        u32 regs_count = aq_nic_get_regs_count(aq_nic);
  22
  23        memset(p, 0, regs_count * sizeof(u32));
  24        aq_nic_get_regs(aq_nic, regs, p);
  25}
  26
  27static int aq_ethtool_get_regs_len(struct net_device *ndev)
  28{
  29        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  30        u32 regs_count = aq_nic_get_regs_count(aq_nic);
  31
  32        return regs_count * sizeof(u32);
  33}
  34
  35static u32 aq_ethtool_get_link(struct net_device *ndev)
  36{
  37        return ethtool_op_get_link(ndev);
  38}
  39
  40static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
  41                                         struct ethtool_link_ksettings *cmd)
  42{
  43        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  44
  45        aq_nic_get_link_ksettings(aq_nic, cmd);
  46        cmd->base.speed = netif_carrier_ok(ndev) ?
  47                                aq_nic_get_link_speed(aq_nic) : 0U;
  48
  49        return 0;
  50}
  51
  52static int
  53aq_ethtool_set_link_ksettings(struct net_device *ndev,
  54                              const struct ethtool_link_ksettings *cmd)
  55{
  56        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  57
  58        return aq_nic_set_link_ksettings(aq_nic, cmd);
  59}
  60
  61static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
  62        "InPackets",
  63        "InUCast",
  64        "InMCast",
  65        "InBCast",
  66        "InErrors",
  67        "OutPackets",
  68        "OutUCast",
  69        "OutMCast",
  70        "OutBCast",
  71        "InUCastOctets",
  72        "OutUCastOctets",
  73        "InMCastOctets",
  74        "OutMCastOctets",
  75        "InBCastOctets",
  76        "OutBCastOctets",
  77        "InOctets",
  78        "OutOctets",
  79        "InPacketsDma",
  80        "OutPacketsDma",
  81        "InOctetsDma",
  82        "OutOctetsDma",
  83        "InDroppedDma",
  84};
  85
  86static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
  87        "Queue[%d] InPackets",
  88        "Queue[%d] OutPackets",
  89        "Queue[%d] Restarts",
  90        "Queue[%d] InJumboPackets",
  91        "Queue[%d] InLroPackets",
  92        "Queue[%d] InErrors",
  93};
  94
  95static void aq_ethtool_stats(struct net_device *ndev,
  96                             struct ethtool_stats *stats, u64 *data)
  97{
  98        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  99        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 100
 101        memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
 102                         ARRAY_SIZE(aq_ethtool_queue_stat_names) *
 103                         cfg->vecs) * sizeof(u64));
 104        aq_nic_get_stats(aq_nic, data);
 105}
 106
 107static void aq_ethtool_get_drvinfo(struct net_device *ndev,
 108                                   struct ethtool_drvinfo *drvinfo)
 109{
 110        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 111        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 112        struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
 113        u32 firmware_version = aq_nic_get_fw_version(aq_nic);
 114        u32 regs_count = aq_nic_get_regs_count(aq_nic);
 115
 116        strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
 117        strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version));
 118
 119        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 120                 "%u.%u.%u", firmware_version >> 24,
 121                 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
 122
 123        strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
 124                sizeof(drvinfo->bus_info));
 125        drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
 126                cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
 127        drvinfo->testinfo_len = 0;
 128        drvinfo->regdump_len = regs_count;
 129        drvinfo->eedump_len = 0;
 130}
 131
 132static void aq_ethtool_get_strings(struct net_device *ndev,
 133                                   u32 stringset, u8 *data)
 134{
 135        int i, si;
 136        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 137        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 138        u8 *p = data;
 139
 140        if (stringset == ETH_SS_STATS) {
 141                memcpy(p, aq_ethtool_stat_names,
 142                       sizeof(aq_ethtool_stat_names));
 143                p = p + sizeof(aq_ethtool_stat_names);
 144                for (i = 0; i < cfg->vecs; i++) {
 145                        for (si = 0;
 146                                si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
 147                                si++) {
 148                                snprintf(p, ETH_GSTRING_LEN,
 149                                         aq_ethtool_queue_stat_names[si], i);
 150                                p += ETH_GSTRING_LEN;
 151                        }
 152                }
 153        }
 154}
 155
 156static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
 157{
 158        int ret = 0;
 159        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 160        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 161
 162        switch (stringset) {
 163        case ETH_SS_STATS:
 164                ret = ARRAY_SIZE(aq_ethtool_stat_names) +
 165                        cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
 166                break;
 167        default:
 168                ret = -EOPNOTSUPP;
 169        }
 170        return ret;
 171}
 172
 173static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
 174{
 175        return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
 176}
 177
 178static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
 179{
 180        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 181        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 182
 183        return sizeof(cfg->aq_rss.hash_secret_key);
 184}
 185
 186static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
 187                              u8 *hfunc)
 188{
 189        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 190        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 191        unsigned int i = 0U;
 192
 193        if (hfunc)
 194                *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
 195        if (indir) {
 196                for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
 197                        indir[i] = cfg->aq_rss.indirection_table[i];
 198        }
 199        if (key)
 200                memcpy(key, cfg->aq_rss.hash_secret_key,
 201                       sizeof(cfg->aq_rss.hash_secret_key));
 202        return 0;
 203}
 204
 205static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
 206                              const u8 *key, const u8 hfunc)
 207{
 208        struct aq_nic_s *aq_nic = netdev_priv(netdev);
 209        struct aq_nic_cfg_s *cfg;
 210        unsigned int i = 0U;
 211        u32 rss_entries;
 212        int err = 0;
 213
 214        cfg = aq_nic_get_cfg(aq_nic);
 215        rss_entries = cfg->aq_rss.indirection_table_size;
 216
 217        /* We do not allow change in unsupported parameters */
 218        if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
 219                return -EOPNOTSUPP;
 220        /* Fill out the redirection table */
 221        if (indir)
 222                for (i = 0; i < rss_entries; i++)
 223                        cfg->aq_rss.indirection_table[i] = indir[i];
 224
 225        /* Fill out the rss hash key */
 226        if (key) {
 227                memcpy(cfg->aq_rss.hash_secret_key, key,
 228                       sizeof(cfg->aq_rss.hash_secret_key));
 229                err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
 230                        &cfg->aq_rss);
 231                if (err)
 232                        return err;
 233        }
 234
 235        err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
 236
 237        return err;
 238}
 239
 240static int aq_ethtool_get_rxnfc(struct net_device *ndev,
 241                                struct ethtool_rxnfc *cmd,
 242                                u32 *rule_locs)
 243{
 244        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 245        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 246        int err = 0;
 247
 248        switch (cmd->cmd) {
 249        case ETHTOOL_GRXRINGS:
 250                cmd->data = cfg->vecs;
 251                break;
 252        case ETHTOOL_GRXCLSRLCNT:
 253                cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
 254                break;
 255        case ETHTOOL_GRXCLSRULE:
 256                err = aq_get_rxnfc_rule(aq_nic, cmd);
 257                break;
 258        case ETHTOOL_GRXCLSRLALL:
 259                err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
 260                break;
 261        default:
 262                err = -EOPNOTSUPP;
 263                break;
 264        }
 265
 266        return err;
 267}
 268
 269static int aq_ethtool_set_rxnfc(struct net_device *ndev,
 270                                struct ethtool_rxnfc *cmd)
 271{
 272        int err = 0;
 273        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 274
 275        switch (cmd->cmd) {
 276        case ETHTOOL_SRXCLSRLINS:
 277                err = aq_add_rxnfc_rule(aq_nic, cmd);
 278                break;
 279        case ETHTOOL_SRXCLSRLDEL:
 280                err = aq_del_rxnfc_rule(aq_nic, cmd);
 281                break;
 282        default:
 283                err = -EOPNOTSUPP;
 284                break;
 285        }
 286
 287        return err;
 288}
 289
 290static int aq_ethtool_get_coalesce(struct net_device *ndev,
 291                                   struct ethtool_coalesce *coal)
 292{
 293        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 294        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 295
 296        if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
 297            cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
 298                coal->rx_coalesce_usecs = cfg->rx_itr;
 299                coal->tx_coalesce_usecs = cfg->tx_itr;
 300                coal->rx_max_coalesced_frames = 0;
 301                coal->tx_max_coalesced_frames = 0;
 302        } else {
 303                coal->rx_coalesce_usecs = 0;
 304                coal->tx_coalesce_usecs = 0;
 305                coal->rx_max_coalesced_frames = 1;
 306                coal->tx_max_coalesced_frames = 1;
 307        }
 308        return 0;
 309}
 310
 311static int aq_ethtool_set_coalesce(struct net_device *ndev,
 312                                   struct ethtool_coalesce *coal)
 313{
 314        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 315        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 316
 317        /* This is not yet supported
 318         */
 319        if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce)
 320                return -EOPNOTSUPP;
 321
 322        /* Atlantic only supports timing based coalescing
 323         */
 324        if (coal->rx_max_coalesced_frames > 1 ||
 325            coal->rx_coalesce_usecs_irq ||
 326            coal->rx_max_coalesced_frames_irq)
 327                return -EOPNOTSUPP;
 328
 329        if (coal->tx_max_coalesced_frames > 1 ||
 330            coal->tx_coalesce_usecs_irq ||
 331            coal->tx_max_coalesced_frames_irq)
 332                return -EOPNOTSUPP;
 333
 334        /* We do not support frame counting. Check this
 335         */
 336        if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
 337                return -EOPNOTSUPP;
 338        if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
 339                return -EOPNOTSUPP;
 340
 341        if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
 342            coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
 343                return -EINVAL;
 344
 345        cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
 346
 347        cfg->rx_itr = coal->rx_coalesce_usecs;
 348        cfg->tx_itr = coal->tx_coalesce_usecs;
 349
 350        return aq_nic_update_interrupt_moderation_settings(aq_nic);
 351}
 352
 353static void aq_ethtool_get_wol(struct net_device *ndev,
 354                               struct ethtool_wolinfo *wol)
 355{
 356        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 357        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 358
 359        wol->supported = WAKE_MAGIC;
 360        wol->wolopts = 0;
 361
 362        if (cfg->wol)
 363                wol->wolopts |= WAKE_MAGIC;
 364}
 365
 366static int aq_ethtool_set_wol(struct net_device *ndev,
 367                              struct ethtool_wolinfo *wol)
 368{
 369        struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
 370        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 371        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 372        int err = 0;
 373
 374        if (wol->wolopts & WAKE_MAGIC)
 375                cfg->wol |= AQ_NIC_WOL_ENABLED;
 376        else
 377                cfg->wol &= ~AQ_NIC_WOL_ENABLED;
 378        err = device_set_wakeup_enable(&pdev->dev, wol->wolopts);
 379
 380        return err;
 381}
 382
 383static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
 384{
 385        u32 rate = 0;
 386
 387        if (speed & AQ_NIC_RATE_EEE_10G)
 388                rate |= SUPPORTED_10000baseT_Full;
 389
 390        if (speed & AQ_NIC_RATE_EEE_2GS)
 391                rate |= SUPPORTED_2500baseX_Full;
 392
 393        if (speed & AQ_NIC_RATE_EEE_1G)
 394                rate |= SUPPORTED_1000baseT_Full;
 395
 396        return rate;
 397}
 398
 399static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
 400{
 401        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 402        u32 rate, supported_rates;
 403        int err = 0;
 404
 405        if (!aq_nic->aq_fw_ops->get_eee_rate)
 406                return -EOPNOTSUPP;
 407
 408        mutex_lock(&aq_nic->fwreq_mutex);
 409        err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
 410                                              &supported_rates);
 411        mutex_unlock(&aq_nic->fwreq_mutex);
 412        if (err < 0)
 413                return err;
 414
 415        eee->supported = eee_mask_to_ethtool_mask(supported_rates);
 416
 417        if (aq_nic->aq_nic_cfg.eee_speeds)
 418                eee->advertised = eee->supported;
 419
 420        eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
 421
 422        eee->eee_enabled = !!eee->advertised;
 423
 424        eee->tx_lpi_enabled = eee->eee_enabled;
 425        if (eee->advertised & eee->lp_advertised)
 426                eee->eee_active = true;
 427
 428        return 0;
 429}
 430
 431static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
 432{
 433        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 434        u32 rate, supported_rates;
 435        struct aq_nic_cfg_s *cfg;
 436        int err = 0;
 437
 438        cfg = aq_nic_get_cfg(aq_nic);
 439
 440        if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
 441                     !aq_nic->aq_fw_ops->set_eee_rate))
 442                return -EOPNOTSUPP;
 443
 444        mutex_lock(&aq_nic->fwreq_mutex);
 445        err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
 446                                              &supported_rates);
 447        mutex_unlock(&aq_nic->fwreq_mutex);
 448        if (err < 0)
 449                return err;
 450
 451        if (eee->eee_enabled) {
 452                rate = supported_rates;
 453                cfg->eee_speeds = rate;
 454        } else {
 455                rate = 0;
 456                cfg->eee_speeds = 0;
 457        }
 458
 459        mutex_lock(&aq_nic->fwreq_mutex);
 460        err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
 461        mutex_unlock(&aq_nic->fwreq_mutex);
 462
 463        return err;
 464}
 465
 466static int aq_ethtool_nway_reset(struct net_device *ndev)
 467{
 468        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 469        int err = 0;
 470
 471        if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
 472                return -EOPNOTSUPP;
 473
 474        if (netif_running(ndev)) {
 475                mutex_lock(&aq_nic->fwreq_mutex);
 476                err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
 477                mutex_unlock(&aq_nic->fwreq_mutex);
 478        }
 479
 480        return err;
 481}
 482
 483static void aq_ethtool_get_pauseparam(struct net_device *ndev,
 484                                      struct ethtool_pauseparam *pause)
 485{
 486        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 487        u32 fc = aq_nic->aq_nic_cfg.flow_control;
 488
 489        pause->autoneg = 0;
 490
 491        pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
 492        pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
 493
 494}
 495
 496static int aq_ethtool_set_pauseparam(struct net_device *ndev,
 497                                     struct ethtool_pauseparam *pause)
 498{
 499        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 500        int err = 0;
 501
 502        if (!aq_nic->aq_fw_ops->set_flow_control)
 503                return -EOPNOTSUPP;
 504
 505        if (pause->autoneg == AUTONEG_ENABLE)
 506                return -EOPNOTSUPP;
 507
 508        if (pause->rx_pause)
 509                aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX;
 510        else
 511                aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX;
 512
 513        if (pause->tx_pause)
 514                aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX;
 515        else
 516                aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
 517
 518        mutex_lock(&aq_nic->fwreq_mutex);
 519        err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
 520        mutex_unlock(&aq_nic->fwreq_mutex);
 521
 522        return err;
 523}
 524
 525static void aq_get_ringparam(struct net_device *ndev,
 526                             struct ethtool_ringparam *ring)
 527{
 528        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 529        struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
 530
 531        ring->rx_pending = aq_nic_cfg->rxds;
 532        ring->tx_pending = aq_nic_cfg->txds;
 533
 534        ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max;
 535        ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max;
 536}
 537
 538static int aq_set_ringparam(struct net_device *ndev,
 539                            struct ethtool_ringparam *ring)
 540{
 541        int err = 0;
 542        bool ndev_running = false;
 543        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 544        struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
 545        const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps;
 546
 547        if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
 548                err = -EOPNOTSUPP;
 549                goto err_exit;
 550        }
 551
 552        if (netif_running(ndev)) {
 553                ndev_running = true;
 554                dev_close(ndev);
 555        }
 556
 557        aq_nic_free_vectors(aq_nic);
 558
 559        aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
 560        aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max);
 561        aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE);
 562
 563        aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
 564        aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max);
 565        aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE);
 566
 567        for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs;
 568             aq_nic->aq_vecs++) {
 569                aq_nic->aq_vec[aq_nic->aq_vecs] =
 570                    aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg);
 571                if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
 572                        err = -ENOMEM;
 573                        goto err_exit;
 574                }
 575        }
 576        if (ndev_running)
 577                err = dev_open(ndev, NULL);
 578
 579err_exit:
 580        return err;
 581}
 582
 583const struct ethtool_ops aq_ethtool_ops = {
 584        .get_link            = aq_ethtool_get_link,
 585        .get_regs_len        = aq_ethtool_get_regs_len,
 586        .get_regs            = aq_ethtool_get_regs,
 587        .get_drvinfo         = aq_ethtool_get_drvinfo,
 588        .get_strings         = aq_ethtool_get_strings,
 589        .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
 590        .get_wol             = aq_ethtool_get_wol,
 591        .set_wol             = aq_ethtool_set_wol,
 592        .nway_reset          = aq_ethtool_nway_reset,
 593        .get_ringparam       = aq_get_ringparam,
 594        .set_ringparam       = aq_set_ringparam,
 595        .get_eee             = aq_ethtool_get_eee,
 596        .set_eee             = aq_ethtool_set_eee,
 597        .get_pauseparam      = aq_ethtool_get_pauseparam,
 598        .set_pauseparam      = aq_ethtool_set_pauseparam,
 599        .get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
 600        .get_rxfh            = aq_ethtool_get_rss,
 601        .set_rxfh            = aq_ethtool_set_rss,
 602        .get_rxnfc           = aq_ethtool_get_rxnfc,
 603        .set_rxnfc           = aq_ethtool_set_rxnfc,
 604        .get_sset_count      = aq_ethtool_get_sset_count,
 605        .get_ethtool_stats   = aq_ethtool_stats,
 606        .get_link_ksettings  = aq_ethtool_get_link_ksettings,
 607        .set_link_ksettings  = aq_ethtool_set_link_ksettings,
 608        .get_coalesce        = aq_ethtool_get_coalesce,
 609        .set_coalesce        = aq_ethtool_set_coalesce,
 610};
 611