linux/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Atlantic Network Driver
   3 *
   4 * Copyright (C) 2014-2019 aQuantia Corporation
   5 * Copyright (C) 2019-2020 Marvell International Ltd.
   6 */
   7
   8/* File aq_ethtool.c: Definition of ethertool related functions. */
   9
  10#include "aq_ethtool.h"
  11#include "aq_nic.h"
  12#include "aq_vec.h"
  13#include "aq_ptp.h"
  14#include "aq_filters.h"
  15#include "aq_macsec.h"
  16
  17#include <linux/ptp_clock_kernel.h>
  18
  19static void aq_ethtool_get_regs(struct net_device *ndev,
  20                                struct ethtool_regs *regs, void *p)
  21{
  22        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  23        u32 regs_count;
  24
  25        regs_count = aq_nic_get_regs_count(aq_nic);
  26
  27        memset(p, 0, regs_count * sizeof(u32));
  28        aq_nic_get_regs(aq_nic, regs, p);
  29}
  30
  31static int aq_ethtool_get_regs_len(struct net_device *ndev)
  32{
  33        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  34        u32 regs_count;
  35
  36        regs_count = aq_nic_get_regs_count(aq_nic);
  37
  38        return regs_count * sizeof(u32);
  39}
  40
  41static u32 aq_ethtool_get_link(struct net_device *ndev)
  42{
  43        return ethtool_op_get_link(ndev);
  44}
  45
  46static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
  47                                         struct ethtool_link_ksettings *cmd)
  48{
  49        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  50
  51        aq_nic_get_link_ksettings(aq_nic, cmd);
  52        cmd->base.speed = netif_carrier_ok(ndev) ?
  53                                aq_nic_get_link_speed(aq_nic) : 0U;
  54
  55        return 0;
  56}
  57
  58static int
  59aq_ethtool_set_link_ksettings(struct net_device *ndev,
  60                              const struct ethtool_link_ksettings *cmd)
  61{
  62        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  63
  64        return aq_nic_set_link_ksettings(aq_nic, cmd);
  65}
  66
  67static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
  68        "InPackets",
  69        "InUCast",
  70        "InMCast",
  71        "InBCast",
  72        "InErrors",
  73        "OutPackets",
  74        "OutUCast",
  75        "OutMCast",
  76        "OutBCast",
  77        "InUCastOctets",
  78        "OutUCastOctets",
  79        "InMCastOctets",
  80        "OutMCastOctets",
  81        "InBCastOctets",
  82        "OutBCastOctets",
  83        "InOctets",
  84        "OutOctets",
  85        "InPacketsDma",
  86        "OutPacketsDma",
  87        "InOctetsDma",
  88        "OutOctetsDma",
  89        "InDroppedDma",
  90};
  91
  92static const char * const aq_ethtool_queue_rx_stat_names[] = {
  93        "%sQueue[%d] InPackets",
  94        "%sQueue[%d] InJumboPackets",
  95        "%sQueue[%d] InLroPackets",
  96        "%sQueue[%d] InErrors",
  97        "%sQueue[%d] AllocFails",
  98        "%sQueue[%d] SkbAllocFails",
  99        "%sQueue[%d] Polls",
 100};
 101
 102static const char * const aq_ethtool_queue_tx_stat_names[] = {
 103        "%sQueue[%d] OutPackets",
 104        "%sQueue[%d] Restarts",
 105};
 106
 107#if IS_ENABLED(CONFIG_MACSEC)
 108static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
 109        "MACSec InCtlPackets",
 110        "MACSec InTaggedMissPackets",
 111        "MACSec InUntaggedMissPackets",
 112        "MACSec InNotagPackets",
 113        "MACSec InUntaggedPackets",
 114        "MACSec InBadTagPackets",
 115        "MACSec InNoSciPackets",
 116        "MACSec InUnknownSciPackets",
 117        "MACSec InCtrlPortPassPackets",
 118        "MACSec InUnctrlPortPassPackets",
 119        "MACSec InCtrlPortFailPackets",
 120        "MACSec InUnctrlPortFailPackets",
 121        "MACSec InTooLongPackets",
 122        "MACSec InIgpocCtlPackets",
 123        "MACSec InEccErrorPackets",
 124        "MACSec InUnctrlHitDropRedir",
 125        "MACSec OutCtlPackets",
 126        "MACSec OutUnknownSaPackets",
 127        "MACSec OutUntaggedPackets",
 128        "MACSec OutTooLong",
 129        "MACSec OutEccErrorPackets",
 130        "MACSec OutUnctrlHitDropRedir",
 131};
 132
 133static const char * const aq_macsec_txsc_stat_names[] = {
 134        "MACSecTXSC%d ProtectedPkts",
 135        "MACSecTXSC%d EncryptedPkts",
 136        "MACSecTXSC%d ProtectedOctets",
 137        "MACSecTXSC%d EncryptedOctets",
 138};
 139
 140static const char * const aq_macsec_txsa_stat_names[] = {
 141        "MACSecTXSC%dSA%d HitDropRedirect",
 142        "MACSecTXSC%dSA%d Protected2Pkts",
 143        "MACSecTXSC%dSA%d ProtectedPkts",
 144        "MACSecTXSC%dSA%d EncryptedPkts",
 145};
 146
 147static const char * const aq_macsec_rxsa_stat_names[] = {
 148        "MACSecRXSC%dSA%d UntaggedHitPkts",
 149        "MACSecRXSC%dSA%d CtrlHitDrpRedir",
 150        "MACSecRXSC%dSA%d NotUsingSa",
 151        "MACSecRXSC%dSA%d UnusedSa",
 152        "MACSecRXSC%dSA%d NotValidPkts",
 153        "MACSecRXSC%dSA%d InvalidPkts",
 154        "MACSecRXSC%dSA%d OkPkts",
 155        "MACSecRXSC%dSA%d LatePkts",
 156        "MACSecRXSC%dSA%d DelayedPkts",
 157        "MACSecRXSC%dSA%d UncheckedPkts",
 158        "MACSecRXSC%dSA%d ValidatedOctets",
 159        "MACSecRXSC%dSA%d DecryptedOctets",
 160};
 161#endif
 162
 163static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
 164        "DMASystemLoopback",
 165        "PKTSystemLoopback",
 166        "DMANetworkLoopback",
 167        "PHYInternalLoopback",
 168        "PHYExternalLoopback",
 169};
 170
 171static u32 aq_ethtool_n_stats(struct net_device *ndev)
 172{
 173        const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
 174        const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
 175        struct aq_nic_s *nic = netdev_priv(ndev);
 176        struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
 177        u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
 178                      (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
 179
 180#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 181        n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) +
 182                   tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
 183#endif
 184
 185#if IS_ENABLED(CONFIG_MACSEC)
 186        if (nic->macsec_cfg) {
 187                n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
 188                           ARRAY_SIZE(aq_macsec_txsc_stat_names) *
 189                                   aq_macsec_tx_sc_cnt(nic) +
 190                           ARRAY_SIZE(aq_macsec_txsa_stat_names) *
 191                                   aq_macsec_tx_sa_cnt(nic) +
 192                           ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
 193                                   aq_macsec_rx_sa_cnt(nic);
 194        }
 195#endif
 196
 197        return n_stats;
 198}
 199
 200static void aq_ethtool_stats(struct net_device *ndev,
 201                             struct ethtool_stats *stats, u64 *data)
 202{
 203        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 204
 205        memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
 206        data = aq_nic_get_stats(aq_nic, data);
 207#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 208        data = aq_ptp_get_stats(aq_nic, data);
 209#endif
 210#if IS_ENABLED(CONFIG_MACSEC)
 211        data = aq_macsec_get_stats(aq_nic, data);
 212#endif
 213}
 214
 215static void aq_ethtool_get_drvinfo(struct net_device *ndev,
 216                                   struct ethtool_drvinfo *drvinfo)
 217{
 218        struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
 219        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 220        u32 firmware_version;
 221        u32 regs_count;
 222
 223        firmware_version = aq_nic_get_fw_version(aq_nic);
 224        regs_count = aq_nic_get_regs_count(aq_nic);
 225
 226        strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
 227
 228        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 229                 "%u.%u.%u", firmware_version >> 24,
 230                 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
 231
 232        strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
 233                sizeof(drvinfo->bus_info));
 234        drvinfo->n_stats = aq_ethtool_n_stats(ndev);
 235        drvinfo->testinfo_len = 0;
 236        drvinfo->regdump_len = regs_count;
 237        drvinfo->eedump_len = 0;
 238}
 239
 240static void aq_ethtool_get_strings(struct net_device *ndev,
 241                                   u32 stringset, u8 *data)
 242{
 243        struct aq_nic_s *nic = netdev_priv(ndev);
 244        struct aq_nic_cfg_s *cfg;
 245        u8 *p = data;
 246        int i, si;
 247#if IS_ENABLED(CONFIG_MACSEC)
 248        int sa;
 249#endif
 250
 251        cfg = aq_nic_get_cfg(nic);
 252
 253        switch (stringset) {
 254        case ETH_SS_STATS: {
 255                const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
 256                const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
 257                char tc_string[8];
 258                int tc;
 259
 260                memset(tc_string, 0, sizeof(tc_string));
 261                memcpy(p, aq_ethtool_stat_names,
 262                       sizeof(aq_ethtool_stat_names));
 263                p = p + sizeof(aq_ethtool_stat_names);
 264
 265                for (tc = 0; tc < cfg->tcs; tc++) {
 266                        if (cfg->is_qos)
 267                                snprintf(tc_string, 8, "TC%d ", tc);
 268
 269                        for (i = 0; i < cfg->vecs; i++) {
 270                                for (si = 0; si < rx_stat_cnt; si++) {
 271                                        snprintf(p, ETH_GSTRING_LEN,
 272                                             aq_ethtool_queue_rx_stat_names[si],
 273                                             tc_string,
 274                                             AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
 275                                        p += ETH_GSTRING_LEN;
 276                                }
 277                                for (si = 0; si < tx_stat_cnt; si++) {
 278                                        snprintf(p, ETH_GSTRING_LEN,
 279                                             aq_ethtool_queue_tx_stat_names[si],
 280                                             tc_string,
 281                                             AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
 282                                        p += ETH_GSTRING_LEN;
 283                                }
 284                        }
 285                }
 286#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 287                if (nic->aq_ptp) {
 288                        const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
 289                        const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
 290                        unsigned int ptp_ring_idx =
 291                                aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
 292
 293                        snprintf(tc_string, 8, "PTP ");
 294
 295                        for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
 296                                for (si = 0; si < rx_stat_cnt; si++) {
 297                                        snprintf(p, ETH_GSTRING_LEN,
 298                                                 aq_ethtool_queue_rx_stat_names[si],
 299                                                 tc_string,
 300                                                 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
 301                                        p += ETH_GSTRING_LEN;
 302                                }
 303                                if (i >= tx_ring_cnt)
 304                                        continue;
 305                                for (si = 0; si < tx_stat_cnt; si++) {
 306                                        snprintf(p, ETH_GSTRING_LEN,
 307                                                 aq_ethtool_queue_tx_stat_names[si],
 308                                                 tc_string,
 309                                                 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
 310                                        p += ETH_GSTRING_LEN;
 311                                }
 312                        }
 313                }
 314#endif
 315#if IS_ENABLED(CONFIG_MACSEC)
 316                if (!nic->macsec_cfg)
 317                        break;
 318
 319                memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
 320                p = p + sizeof(aq_macsec_stat_names);
 321                for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
 322                        struct aq_macsec_txsc *aq_txsc;
 323
 324                        if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
 325                                continue;
 326
 327                        for (si = 0;
 328                                si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
 329                                si++) {
 330                                snprintf(p, ETH_GSTRING_LEN,
 331                                         aq_macsec_txsc_stat_names[si], i);
 332                                p += ETH_GSTRING_LEN;
 333                        }
 334                        aq_txsc = &nic->macsec_cfg->aq_txsc[i];
 335                        for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
 336                                if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
 337                                        continue;
 338                                for (si = 0;
 339                                     si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
 340                                     si++) {
 341                                        snprintf(p, ETH_GSTRING_LEN,
 342                                                 aq_macsec_txsa_stat_names[si],
 343                                                 i, sa);
 344                                        p += ETH_GSTRING_LEN;
 345                                }
 346                        }
 347                }
 348                for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
 349                        struct aq_macsec_rxsc *aq_rxsc;
 350
 351                        if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
 352                                continue;
 353
 354                        aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
 355                        for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
 356                                if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
 357                                        continue;
 358                                for (si = 0;
 359                                     si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
 360                                     si++) {
 361                                        snprintf(p, ETH_GSTRING_LEN,
 362                                                 aq_macsec_rxsa_stat_names[si],
 363                                                 i, sa);
 364                                        p += ETH_GSTRING_LEN;
 365                                }
 366                        }
 367                }
 368#endif
 369                break;
 370        }
 371        case ETH_SS_PRIV_FLAGS:
 372                memcpy(p, aq_ethtool_priv_flag_names,
 373                       sizeof(aq_ethtool_priv_flag_names));
 374                break;
 375        }
 376}
 377
 378static int aq_ethtool_set_phys_id(struct net_device *ndev,
 379                                  enum ethtool_phys_id_state state)
 380{
 381        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 382        struct aq_hw_s *hw = aq_nic->aq_hw;
 383        int ret = 0;
 384
 385        if (!aq_nic->aq_fw_ops->led_control)
 386                return -EOPNOTSUPP;
 387
 388        mutex_lock(&aq_nic->fwreq_mutex);
 389
 390        switch (state) {
 391        case ETHTOOL_ID_ACTIVE:
 392                ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
 393                                 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
 394                break;
 395        case ETHTOOL_ID_INACTIVE:
 396                ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
 397                break;
 398        default:
 399                break;
 400        }
 401
 402        mutex_unlock(&aq_nic->fwreq_mutex);
 403
 404        return ret;
 405}
 406
 407static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
 408{
 409        int ret = 0;
 410
 411        switch (stringset) {
 412        case ETH_SS_STATS:
 413                ret = aq_ethtool_n_stats(ndev);
 414                break;
 415        case ETH_SS_PRIV_FLAGS:
 416                ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
 417                break;
 418        default:
 419                ret = -EOPNOTSUPP;
 420        }
 421
 422        return ret;
 423}
 424
 425static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
 426{
 427        return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
 428}
 429
 430static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
 431{
 432        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 433        struct aq_nic_cfg_s *cfg;
 434
 435        cfg = aq_nic_get_cfg(aq_nic);
 436
 437        return sizeof(cfg->aq_rss.hash_secret_key);
 438}
 439
 440static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
 441                              u8 *hfunc)
 442{
 443        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 444        struct aq_nic_cfg_s *cfg;
 445        unsigned int i = 0U;
 446
 447        cfg = aq_nic_get_cfg(aq_nic);
 448
 449        if (hfunc)
 450                *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
 451        if (indir) {
 452                for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
 453                        indir[i] = cfg->aq_rss.indirection_table[i];
 454        }
 455        if (key)
 456                memcpy(key, cfg->aq_rss.hash_secret_key,
 457                       sizeof(cfg->aq_rss.hash_secret_key));
 458
 459        return 0;
 460}
 461
 462static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
 463                              const u8 *key, const u8 hfunc)
 464{
 465        struct aq_nic_s *aq_nic = netdev_priv(netdev);
 466        struct aq_nic_cfg_s *cfg;
 467        unsigned int i = 0U;
 468        u32 rss_entries;
 469        int err = 0;
 470
 471        cfg = aq_nic_get_cfg(aq_nic);
 472        rss_entries = cfg->aq_rss.indirection_table_size;
 473
 474        /* We do not allow change in unsupported parameters */
 475        if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
 476                return -EOPNOTSUPP;
 477        /* Fill out the redirection table */
 478        if (indir)
 479                for (i = 0; i < rss_entries; i++)
 480                        cfg->aq_rss.indirection_table[i] = indir[i];
 481
 482        /* Fill out the rss hash key */
 483        if (key) {
 484                memcpy(cfg->aq_rss.hash_secret_key, key,
 485                       sizeof(cfg->aq_rss.hash_secret_key));
 486                err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
 487                        &cfg->aq_rss);
 488                if (err)
 489                        return err;
 490        }
 491
 492        err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
 493
 494        return err;
 495}
 496
 497static int aq_ethtool_get_rxnfc(struct net_device *ndev,
 498                                struct ethtool_rxnfc *cmd,
 499                                u32 *rule_locs)
 500{
 501        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 502        struct aq_nic_cfg_s *cfg;
 503        int err = 0;
 504
 505        cfg = aq_nic_get_cfg(aq_nic);
 506
 507        switch (cmd->cmd) {
 508        case ETHTOOL_GRXRINGS:
 509                cmd->data = cfg->vecs;
 510                break;
 511        case ETHTOOL_GRXCLSRLCNT:
 512                cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
 513                break;
 514        case ETHTOOL_GRXCLSRULE:
 515                err = aq_get_rxnfc_rule(aq_nic, cmd);
 516                break;
 517        case ETHTOOL_GRXCLSRLALL:
 518                err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
 519                break;
 520        default:
 521                err = -EOPNOTSUPP;
 522                break;
 523        }
 524
 525        return err;
 526}
 527
 528static int aq_ethtool_set_rxnfc(struct net_device *ndev,
 529                                struct ethtool_rxnfc *cmd)
 530{
 531        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 532        int err = 0;
 533
 534        switch (cmd->cmd) {
 535        case ETHTOOL_SRXCLSRLINS:
 536                err = aq_add_rxnfc_rule(aq_nic, cmd);
 537                break;
 538        case ETHTOOL_SRXCLSRLDEL:
 539                err = aq_del_rxnfc_rule(aq_nic, cmd);
 540                break;
 541        default:
 542                err = -EOPNOTSUPP;
 543                break;
 544        }
 545
 546        return err;
 547}
 548
 549static int aq_ethtool_get_coalesce(struct net_device *ndev,
 550                                   struct ethtool_coalesce *coal)
 551{
 552        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 553        struct aq_nic_cfg_s *cfg;
 554
 555        cfg = aq_nic_get_cfg(aq_nic);
 556
 557        if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
 558            cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
 559                coal->rx_coalesce_usecs = cfg->rx_itr;
 560                coal->tx_coalesce_usecs = cfg->tx_itr;
 561                coal->rx_max_coalesced_frames = 0;
 562                coal->tx_max_coalesced_frames = 0;
 563        } else {
 564                coal->rx_coalesce_usecs = 0;
 565                coal->tx_coalesce_usecs = 0;
 566                coal->rx_max_coalesced_frames = 1;
 567                coal->tx_max_coalesced_frames = 1;
 568        }
 569
 570        return 0;
 571}
 572
 573static int aq_ethtool_set_coalesce(struct net_device *ndev,
 574                                   struct ethtool_coalesce *coal)
 575{
 576        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 577        struct aq_nic_cfg_s *cfg;
 578
 579        cfg = aq_nic_get_cfg(aq_nic);
 580
 581        /* Atlantic only supports timing based coalescing
 582         */
 583        if (coal->rx_max_coalesced_frames > 1 ||
 584            coal->tx_max_coalesced_frames > 1)
 585                return -EOPNOTSUPP;
 586
 587        /* We do not support frame counting. Check this
 588         */
 589        if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
 590                return -EOPNOTSUPP;
 591        if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
 592                return -EOPNOTSUPP;
 593
 594        if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
 595            coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
 596                return -EINVAL;
 597
 598        cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
 599
 600        cfg->rx_itr = coal->rx_coalesce_usecs;
 601        cfg->tx_itr = coal->tx_coalesce_usecs;
 602
 603        return aq_nic_update_interrupt_moderation_settings(aq_nic);
 604}
 605
 606static void aq_ethtool_get_wol(struct net_device *ndev,
 607                               struct ethtool_wolinfo *wol)
 608{
 609        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 610        struct aq_nic_cfg_s *cfg;
 611
 612        cfg = aq_nic_get_cfg(aq_nic);
 613
 614        wol->supported = AQ_NIC_WOL_MODES;
 615        wol->wolopts = cfg->wol;
 616}
 617
 618static int aq_ethtool_set_wol(struct net_device *ndev,
 619                              struct ethtool_wolinfo *wol)
 620{
 621        struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
 622        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 623        struct aq_nic_cfg_s *cfg;
 624        int err = 0;
 625
 626        cfg = aq_nic_get_cfg(aq_nic);
 627
 628        if (wol->wolopts & ~AQ_NIC_WOL_MODES)
 629                return -EOPNOTSUPP;
 630
 631        cfg->wol = wol->wolopts;
 632
 633        err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
 634
 635        return err;
 636}
 637
 638static int aq_ethtool_get_ts_info(struct net_device *ndev,
 639                                  struct ethtool_ts_info *info)
 640{
 641        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 642
 643        ethtool_op_get_ts_info(ndev, info);
 644
 645        if (!aq_nic->aq_ptp)
 646                return 0;
 647
 648        info->so_timestamping |=
 649                SOF_TIMESTAMPING_TX_HARDWARE |
 650                SOF_TIMESTAMPING_RX_HARDWARE |
 651                SOF_TIMESTAMPING_RAW_HARDWARE;
 652
 653        info->tx_types = BIT(HWTSTAMP_TX_OFF) |
 654                         BIT(HWTSTAMP_TX_ON);
 655
 656        info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
 657
 658        info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
 659                            BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
 660                            BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
 661
 662#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 663        info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
 664#endif
 665
 666        return 0;
 667}
 668
 669static u32 eee_mask_to_ethtool_mask(u32 speed)
 670{
 671        u32 rate = 0;
 672
 673        if (speed & AQ_NIC_RATE_EEE_10G)
 674                rate |= SUPPORTED_10000baseT_Full;
 675
 676        if (speed & AQ_NIC_RATE_EEE_1G)
 677                rate |= SUPPORTED_1000baseT_Full;
 678
 679        if (speed & AQ_NIC_RATE_EEE_100M)
 680                rate |= SUPPORTED_100baseT_Full;
 681
 682        return rate;
 683}
 684
 685static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
 686{
 687        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 688        u32 rate, supported_rates;
 689        int err = 0;
 690
 691        if (!aq_nic->aq_fw_ops->get_eee_rate)
 692                return -EOPNOTSUPP;
 693
 694        mutex_lock(&aq_nic->fwreq_mutex);
 695        err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
 696                                              &supported_rates);
 697        mutex_unlock(&aq_nic->fwreq_mutex);
 698        if (err < 0)
 699                return err;
 700
 701        eee->supported = eee_mask_to_ethtool_mask(supported_rates);
 702
 703        if (aq_nic->aq_nic_cfg.eee_speeds)
 704                eee->advertised = eee->supported;
 705
 706        eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
 707
 708        eee->eee_enabled = !!eee->advertised;
 709
 710        eee->tx_lpi_enabled = eee->eee_enabled;
 711        if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
 712                eee->eee_active = true;
 713
 714        return 0;
 715}
 716
 717static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
 718{
 719        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 720        u32 rate, supported_rates;
 721        struct aq_nic_cfg_s *cfg;
 722        int err = 0;
 723
 724        cfg = aq_nic_get_cfg(aq_nic);
 725
 726        if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
 727                     !aq_nic->aq_fw_ops->set_eee_rate))
 728                return -EOPNOTSUPP;
 729
 730        mutex_lock(&aq_nic->fwreq_mutex);
 731        err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
 732                                              &supported_rates);
 733        mutex_unlock(&aq_nic->fwreq_mutex);
 734        if (err < 0)
 735                return err;
 736
 737        if (eee->eee_enabled) {
 738                rate = supported_rates;
 739                cfg->eee_speeds = rate;
 740        } else {
 741                rate = 0;
 742                cfg->eee_speeds = 0;
 743        }
 744
 745        mutex_lock(&aq_nic->fwreq_mutex);
 746        err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
 747        mutex_unlock(&aq_nic->fwreq_mutex);
 748
 749        return err;
 750}
 751
 752static int aq_ethtool_nway_reset(struct net_device *ndev)
 753{
 754        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 755        int err = 0;
 756
 757        if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
 758                return -EOPNOTSUPP;
 759
 760        if (netif_running(ndev)) {
 761                mutex_lock(&aq_nic->fwreq_mutex);
 762                err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
 763                mutex_unlock(&aq_nic->fwreq_mutex);
 764        }
 765
 766        return err;
 767}
 768
 769static void aq_ethtool_get_pauseparam(struct net_device *ndev,
 770                                      struct ethtool_pauseparam *pause)
 771{
 772        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 773        int fc = aq_nic->aq_nic_cfg.fc.req;
 774
 775        pause->autoneg = 0;
 776
 777        pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
 778        pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
 779}
 780
 781static int aq_ethtool_set_pauseparam(struct net_device *ndev,
 782                                     struct ethtool_pauseparam *pause)
 783{
 784        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 785        int err = 0;
 786
 787        if (!aq_nic->aq_fw_ops->set_flow_control)
 788                return -EOPNOTSUPP;
 789
 790        if (pause->autoneg == AUTONEG_ENABLE)
 791                return -EOPNOTSUPP;
 792
 793        if (pause->rx_pause)
 794                aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
 795        else
 796                aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
 797
 798        if (pause->tx_pause)
 799                aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
 800        else
 801                aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
 802
 803        mutex_lock(&aq_nic->fwreq_mutex);
 804        err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
 805        mutex_unlock(&aq_nic->fwreq_mutex);
 806
 807        return err;
 808}
 809
 810static void aq_get_ringparam(struct net_device *ndev,
 811                             struct ethtool_ringparam *ring)
 812{
 813        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 814        struct aq_nic_cfg_s *cfg;
 815
 816        cfg = aq_nic_get_cfg(aq_nic);
 817
 818        ring->rx_pending = cfg->rxds;
 819        ring->tx_pending = cfg->txds;
 820
 821        ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
 822        ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
 823}
 824
 825static int aq_set_ringparam(struct net_device *ndev,
 826                            struct ethtool_ringparam *ring)
 827{
 828        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 829        const struct aq_hw_caps_s *hw_caps;
 830        bool ndev_running = false;
 831        struct aq_nic_cfg_s *cfg;
 832        int err = 0;
 833
 834        cfg = aq_nic_get_cfg(aq_nic);
 835        hw_caps = cfg->aq_hw_caps;
 836
 837        if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
 838                err = -EOPNOTSUPP;
 839                goto err_exit;
 840        }
 841
 842        if (netif_running(ndev)) {
 843                ndev_running = true;
 844                dev_close(ndev);
 845        }
 846
 847        cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
 848        cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
 849        cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
 850
 851        cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
 852        cfg->txds = min(cfg->txds, hw_caps->txds_max);
 853        cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
 854
 855        err = aq_nic_realloc_vectors(aq_nic);
 856        if (err)
 857                goto err_exit;
 858
 859        if (ndev_running)
 860                err = dev_open(ndev, NULL);
 861
 862err_exit:
 863        return err;
 864}
 865
 866static u32 aq_get_msg_level(struct net_device *ndev)
 867{
 868        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 869
 870        return aq_nic->msg_enable;
 871}
 872
 873static void aq_set_msg_level(struct net_device *ndev, u32 data)
 874{
 875        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 876
 877        aq_nic->msg_enable = data;
 878}
 879
 880static u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
 881{
 882        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 883
 884        return aq_nic->aq_nic_cfg.priv_flags;
 885}
 886
 887static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
 888{
 889        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 890        struct aq_nic_cfg_s *cfg;
 891        u32 priv_flags;
 892        int ret = 0;
 893
 894        cfg = aq_nic_get_cfg(aq_nic);
 895        priv_flags = cfg->priv_flags;
 896
 897        if (flags & ~AQ_PRIV_FLAGS_MASK)
 898                return -EOPNOTSUPP;
 899
 900        if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
 901                netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
 902                return -EINVAL;
 903        }
 904
 905        cfg->priv_flags = flags;
 906
 907        if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
 908                if (netif_running(ndev)) {
 909                        dev_close(ndev);
 910
 911                        dev_open(ndev, NULL);
 912                }
 913        } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
 914                ret = aq_nic_set_loopback(aq_nic);
 915        }
 916
 917        return ret;
 918}
 919
 920const struct ethtool_ops aq_ethtool_ops = {
 921        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 922                                     ETHTOOL_COALESCE_MAX_FRAMES,
 923        .get_link            = aq_ethtool_get_link,
 924        .get_regs_len        = aq_ethtool_get_regs_len,
 925        .get_regs            = aq_ethtool_get_regs,
 926        .get_drvinfo         = aq_ethtool_get_drvinfo,
 927        .get_strings         = aq_ethtool_get_strings,
 928        .set_phys_id         = aq_ethtool_set_phys_id,
 929        .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
 930        .get_wol             = aq_ethtool_get_wol,
 931        .set_wol             = aq_ethtool_set_wol,
 932        .nway_reset          = aq_ethtool_nway_reset,
 933        .get_ringparam       = aq_get_ringparam,
 934        .set_ringparam       = aq_set_ringparam,
 935        .get_eee             = aq_ethtool_get_eee,
 936        .set_eee             = aq_ethtool_set_eee,
 937        .get_pauseparam      = aq_ethtool_get_pauseparam,
 938        .set_pauseparam      = aq_ethtool_set_pauseparam,
 939        .get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
 940        .get_rxfh            = aq_ethtool_get_rss,
 941        .set_rxfh            = aq_ethtool_set_rss,
 942        .get_rxnfc           = aq_ethtool_get_rxnfc,
 943        .set_rxnfc           = aq_ethtool_set_rxnfc,
 944        .get_msglevel        = aq_get_msg_level,
 945        .set_msglevel        = aq_set_msg_level,
 946        .get_sset_count      = aq_ethtool_get_sset_count,
 947        .get_ethtool_stats   = aq_ethtool_stats,
 948        .get_priv_flags      = aq_ethtool_get_priv_flags,
 949        .set_priv_flags      = aq_ethtool_set_priv_flags,
 950        .get_link_ksettings  = aq_ethtool_get_link_ksettings,
 951        .set_link_ksettings  = aq_ethtool_set_link_ksettings,
 952        .get_coalesce        = aq_ethtool_get_coalesce,
 953        .set_coalesce        = aq_ethtool_set_coalesce,
 954        .get_ts_info         = aq_ethtool_get_ts_info,
 955};
 956