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