linux/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
   2/* Copyright (C) 2015-2018 Netronome Systems, Inc. */
   3
   4/*
   5 * nfp_net_ethtool.c
   6 * Netronome network device driver: ethtool support
   7 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
   8 *          Jason McMullan <jason.mcmullan@netronome.com>
   9 *          Rolf Neugebauer <rolf.neugebauer@netronome.com>
  10 *          Brad Petrus <brad.petrus@netronome.com>
  11 */
  12
  13#include <linux/bitfield.h>
  14#include <linux/kernel.h>
  15#include <linux/netdevice.h>
  16#include <linux/etherdevice.h>
  17#include <linux/interrupt.h>
  18#include <linux/pci.h>
  19#include <linux/ethtool.h>
  20#include <linux/firmware.h>
  21#include <linux/sfp.h>
  22
  23#include "nfpcore/nfp.h"
  24#include "nfpcore/nfp_nsp.h"
  25#include "nfp_app.h"
  26#include "nfp_main.h"
  27#include "nfp_net_ctrl.h"
  28#include "nfp_net.h"
  29#include "nfp_port.h"
  30
  31struct nfp_et_stat {
  32        char name[ETH_GSTRING_LEN];
  33        int off;
  34};
  35
  36static const struct nfp_et_stat nfp_net_et_stats[] = {
  37        /* Stats from the device */
  38        { "dev_rx_discards",    NFP_NET_CFG_STATS_RX_DISCARDS },
  39        { "dev_rx_errors",      NFP_NET_CFG_STATS_RX_ERRORS },
  40        { "dev_rx_bytes",       NFP_NET_CFG_STATS_RX_OCTETS },
  41        { "dev_rx_uc_bytes",    NFP_NET_CFG_STATS_RX_UC_OCTETS },
  42        { "dev_rx_mc_bytes",    NFP_NET_CFG_STATS_RX_MC_OCTETS },
  43        { "dev_rx_bc_bytes",    NFP_NET_CFG_STATS_RX_BC_OCTETS },
  44        { "dev_rx_pkts",        NFP_NET_CFG_STATS_RX_FRAMES },
  45        { "dev_rx_mc_pkts",     NFP_NET_CFG_STATS_RX_MC_FRAMES },
  46        { "dev_rx_bc_pkts",     NFP_NET_CFG_STATS_RX_BC_FRAMES },
  47
  48        { "dev_tx_discards",    NFP_NET_CFG_STATS_TX_DISCARDS },
  49        { "dev_tx_errors",      NFP_NET_CFG_STATS_TX_ERRORS },
  50        { "dev_tx_bytes",       NFP_NET_CFG_STATS_TX_OCTETS },
  51        { "dev_tx_uc_bytes",    NFP_NET_CFG_STATS_TX_UC_OCTETS },
  52        { "dev_tx_mc_bytes",    NFP_NET_CFG_STATS_TX_MC_OCTETS },
  53        { "dev_tx_bc_bytes",    NFP_NET_CFG_STATS_TX_BC_OCTETS },
  54        { "dev_tx_pkts",        NFP_NET_CFG_STATS_TX_FRAMES },
  55        { "dev_tx_mc_pkts",     NFP_NET_CFG_STATS_TX_MC_FRAMES },
  56        { "dev_tx_bc_pkts",     NFP_NET_CFG_STATS_TX_BC_FRAMES },
  57
  58        { "bpf_pass_pkts",      NFP_NET_CFG_STATS_APP0_FRAMES },
  59        { "bpf_pass_bytes",     NFP_NET_CFG_STATS_APP0_BYTES },
  60        /* see comments in outro functions in nfp_bpf_jit.c to find out
  61         * how different BPF modes use app-specific counters
  62         */
  63        { "bpf_app1_pkts",      NFP_NET_CFG_STATS_APP1_FRAMES },
  64        { "bpf_app1_bytes",     NFP_NET_CFG_STATS_APP1_BYTES },
  65        { "bpf_app2_pkts",      NFP_NET_CFG_STATS_APP2_FRAMES },
  66        { "bpf_app2_bytes",     NFP_NET_CFG_STATS_APP2_BYTES },
  67        { "bpf_app3_pkts",      NFP_NET_CFG_STATS_APP3_FRAMES },
  68        { "bpf_app3_bytes",     NFP_NET_CFG_STATS_APP3_BYTES },
  69};
  70
  71static const struct nfp_et_stat nfp_mac_et_stats[] = {
  72        { "rx_octets",                  NFP_MAC_STATS_RX_IN_OCTETS, },
  73        { "rx_frame_too_long_errors",
  74                        NFP_MAC_STATS_RX_FRAME_TOO_LONG_ERRORS, },
  75        { "rx_range_length_errors",     NFP_MAC_STATS_RX_RANGE_LENGTH_ERRORS, },
  76        { "rx_vlan_received_ok",        NFP_MAC_STATS_RX_VLAN_RECEIVED_OK, },
  77        { "rx_errors",                  NFP_MAC_STATS_RX_IN_ERRORS, },
  78        { "rx_broadcast_pkts",          NFP_MAC_STATS_RX_IN_BROADCAST_PKTS, },
  79        { "rx_drop_events",             NFP_MAC_STATS_RX_DROP_EVENTS, },
  80        { "rx_alignment_errors",        NFP_MAC_STATS_RX_ALIGNMENT_ERRORS, },
  81        { "rx_pause_mac_ctrl_frames",
  82                        NFP_MAC_STATS_RX_PAUSE_MAC_CTRL_FRAMES, },
  83        { "rx_frames_received_ok",      NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK, },
  84        { "rx_frame_check_sequence_errors",
  85                        NFP_MAC_STATS_RX_FRAME_CHECK_SEQUENCE_ERRORS, },
  86        { "rx_unicast_pkts",            NFP_MAC_STATS_RX_UNICAST_PKTS, },
  87        { "rx_multicast_pkts",          NFP_MAC_STATS_RX_MULTICAST_PKTS, },
  88        { "rx_pkts",                    NFP_MAC_STATS_RX_PKTS, },
  89        { "rx_undersize_pkts",          NFP_MAC_STATS_RX_UNDERSIZE_PKTS, },
  90        { "rx_pkts_64_octets",          NFP_MAC_STATS_RX_PKTS_64_OCTETS, },
  91        { "rx_pkts_65_to_127_octets",
  92                        NFP_MAC_STATS_RX_PKTS_65_TO_127_OCTETS, },
  93        { "rx_pkts_128_to_255_octets",
  94                        NFP_MAC_STATS_RX_PKTS_128_TO_255_OCTETS, },
  95        { "rx_pkts_256_to_511_octets",
  96                        NFP_MAC_STATS_RX_PKTS_256_TO_511_OCTETS, },
  97        { "rx_pkts_512_to_1023_octets",
  98                        NFP_MAC_STATS_RX_PKTS_512_TO_1023_OCTETS, },
  99        { "rx_pkts_1024_to_1518_octets",
 100                        NFP_MAC_STATS_RX_PKTS_1024_TO_1518_OCTETS, },
 101        { "rx_pkts_1519_to_max_octets",
 102                        NFP_MAC_STATS_RX_PKTS_1519_TO_MAX_OCTETS, },
 103        { "rx_jabbers",                 NFP_MAC_STATS_RX_JABBERS, },
 104        { "rx_fragments",               NFP_MAC_STATS_RX_FRAGMENTS, },
 105        { "rx_oversize_pkts",           NFP_MAC_STATS_RX_OVERSIZE_PKTS, },
 106        { "rx_pause_frames_class0",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS0, },
 107        { "rx_pause_frames_class1",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS1, },
 108        { "rx_pause_frames_class2",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS2, },
 109        { "rx_pause_frames_class3",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS3, },
 110        { "rx_pause_frames_class4",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS4, },
 111        { "rx_pause_frames_class5",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS5, },
 112        { "rx_pause_frames_class6",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS6, },
 113        { "rx_pause_frames_class7",     NFP_MAC_STATS_RX_PAUSE_FRAMES_CLASS7, },
 114        { "rx_mac_ctrl_frames_received",
 115                        NFP_MAC_STATS_RX_MAC_CTRL_FRAMES_RECEIVED, },
 116        { "rx_mac_head_drop",           NFP_MAC_STATS_RX_MAC_HEAD_DROP, },
 117        { "tx_queue_drop",              NFP_MAC_STATS_TX_QUEUE_DROP, },
 118        { "tx_octets",                  NFP_MAC_STATS_TX_OUT_OCTETS, },
 119        { "tx_vlan_transmitted_ok",     NFP_MAC_STATS_TX_VLAN_TRANSMITTED_OK, },
 120        { "tx_errors",                  NFP_MAC_STATS_TX_OUT_ERRORS, },
 121        { "tx_broadcast_pkts",          NFP_MAC_STATS_TX_BROADCAST_PKTS, },
 122        { "tx_pause_mac_ctrl_frames",
 123                        NFP_MAC_STATS_TX_PAUSE_MAC_CTRL_FRAMES, },
 124        { "tx_frames_transmitted_ok",
 125                        NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK, },
 126        { "tx_unicast_pkts",            NFP_MAC_STATS_TX_UNICAST_PKTS, },
 127        { "tx_multicast_pkts",          NFP_MAC_STATS_TX_MULTICAST_PKTS, },
 128        { "tx_pkts_64_octets",          NFP_MAC_STATS_TX_PKTS_64_OCTETS, },
 129        { "tx_pkts_65_to_127_octets",
 130                        NFP_MAC_STATS_TX_PKTS_65_TO_127_OCTETS, },
 131        { "tx_pkts_128_to_255_octets",
 132                        NFP_MAC_STATS_TX_PKTS_128_TO_255_OCTETS, },
 133        { "tx_pkts_256_to_511_octets",
 134                        NFP_MAC_STATS_TX_PKTS_256_TO_511_OCTETS, },
 135        { "tx_pkts_512_to_1023_octets",
 136                        NFP_MAC_STATS_TX_PKTS_512_TO_1023_OCTETS, },
 137        { "tx_pkts_1024_to_1518_octets",
 138                        NFP_MAC_STATS_TX_PKTS_1024_TO_1518_OCTETS, },
 139        { "tx_pkts_1519_to_max_octets",
 140                        NFP_MAC_STATS_TX_PKTS_1519_TO_MAX_OCTETS, },
 141        { "tx_pause_frames_class0",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS0, },
 142        { "tx_pause_frames_class1",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS1, },
 143        { "tx_pause_frames_class2",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS2, },
 144        { "tx_pause_frames_class3",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS3, },
 145        { "tx_pause_frames_class4",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS4, },
 146        { "tx_pause_frames_class5",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS5, },
 147        { "tx_pause_frames_class6",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS6, },
 148        { "tx_pause_frames_class7",     NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS7, },
 149};
 150
 151static const char nfp_tlv_stat_names[][ETH_GSTRING_LEN] = {
 152        [1]     = "dev_rx_discards",
 153        [2]     = "dev_rx_errors",
 154        [3]     = "dev_rx_bytes",
 155        [4]     = "dev_rx_uc_bytes",
 156        [5]     = "dev_rx_mc_bytes",
 157        [6]     = "dev_rx_bc_bytes",
 158        [7]     = "dev_rx_pkts",
 159        [8]     = "dev_rx_mc_pkts",
 160        [9]     = "dev_rx_bc_pkts",
 161
 162        [10]    = "dev_tx_discards",
 163        [11]    = "dev_tx_errors",
 164        [12]    = "dev_tx_bytes",
 165        [13]    = "dev_tx_uc_bytes",
 166        [14]    = "dev_tx_mc_bytes",
 167        [15]    = "dev_tx_bc_bytes",
 168        [16]    = "dev_tx_pkts",
 169        [17]    = "dev_tx_mc_pkts",
 170        [18]    = "dev_tx_bc_pkts",
 171};
 172
 173#define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats)
 174#define NN_ET_SWITCH_STATS_LEN 9
 175#define NN_RVEC_GATHER_STATS    13
 176#define NN_RVEC_PER_Q_STATS     3
 177#define NN_CTRL_PATH_STATS      4
 178
 179#define SFP_SFF_REV_COMPLIANCE  1
 180
 181static void nfp_net_get_nspinfo(struct nfp_app *app, char *version)
 182{
 183        struct nfp_nsp *nsp;
 184
 185        if (!app)
 186                return;
 187
 188        nsp = nfp_nsp_open(app->cpp);
 189        if (IS_ERR(nsp))
 190                return;
 191
 192        snprintf(version, ETHTOOL_FWVERS_LEN, "%hu.%hu",
 193                 nfp_nsp_get_abi_ver_major(nsp),
 194                 nfp_nsp_get_abi_ver_minor(nsp));
 195
 196        nfp_nsp_close(nsp);
 197}
 198
 199static void
 200nfp_get_drvinfo(struct nfp_app *app, struct pci_dev *pdev,
 201                const char *vnic_version, struct ethtool_drvinfo *drvinfo)
 202{
 203        char nsp_version[ETHTOOL_FWVERS_LEN] = {};
 204
 205        strlcpy(drvinfo->driver, pdev->driver->name, sizeof(drvinfo->driver));
 206        nfp_net_get_nspinfo(app, nsp_version);
 207        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 208                 "%s %s %s %s", vnic_version, nsp_version,
 209                 nfp_app_mip_name(app), nfp_app_name(app));
 210}
 211
 212static void
 213nfp_net_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 214{
 215        char vnic_version[ETHTOOL_FWVERS_LEN] = {};
 216        struct nfp_net *nn = netdev_priv(netdev);
 217
 218        snprintf(vnic_version, sizeof(vnic_version), "%d.%d.%d.%d",
 219                 nn->fw_ver.resv, nn->fw_ver.class,
 220                 nn->fw_ver.major, nn->fw_ver.minor);
 221        strlcpy(drvinfo->bus_info, pci_name(nn->pdev),
 222                sizeof(drvinfo->bus_info));
 223
 224        nfp_get_drvinfo(nn->app, nn->pdev, vnic_version, drvinfo);
 225}
 226
 227static void
 228nfp_app_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 229{
 230        struct nfp_app *app = nfp_app_from_netdev(netdev);
 231
 232        strlcpy(drvinfo->bus_info, pci_name(app->pdev),
 233                sizeof(drvinfo->bus_info));
 234        nfp_get_drvinfo(app, app->pdev, "*", drvinfo);
 235}
 236
 237static void
 238nfp_net_set_fec_link_mode(struct nfp_eth_table_port *eth_port,
 239                          struct ethtool_link_ksettings *c)
 240{
 241        unsigned int modes;
 242
 243        ethtool_link_ksettings_add_link_mode(c, supported, FEC_NONE);
 244        if (!nfp_eth_can_support_fec(eth_port)) {
 245                ethtool_link_ksettings_add_link_mode(c, advertising, FEC_NONE);
 246                return;
 247        }
 248
 249        modes = nfp_eth_supported_fec_modes(eth_port);
 250        if (modes & NFP_FEC_BASER) {
 251                ethtool_link_ksettings_add_link_mode(c, supported, FEC_BASER);
 252                ethtool_link_ksettings_add_link_mode(c, advertising, FEC_BASER);
 253        }
 254
 255        if (modes & NFP_FEC_REED_SOLOMON) {
 256                ethtool_link_ksettings_add_link_mode(c, supported, FEC_RS);
 257                ethtool_link_ksettings_add_link_mode(c, advertising, FEC_RS);
 258        }
 259}
 260
 261/**
 262 * nfp_net_get_link_ksettings - Get Link Speed settings
 263 * @netdev:     network interface device structure
 264 * @cmd:        ethtool command
 265 *
 266 * Reports speed settings based on info in the BAR provided by the fw.
 267 */
 268static int
 269nfp_net_get_link_ksettings(struct net_device *netdev,
 270                           struct ethtool_link_ksettings *cmd)
 271{
 272        static const u32 ls_to_ethtool[] = {
 273                [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
 274                [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = SPEED_UNKNOWN,
 275                [NFP_NET_CFG_STS_LINK_RATE_1G]          = SPEED_1000,
 276                [NFP_NET_CFG_STS_LINK_RATE_10G]         = SPEED_10000,
 277                [NFP_NET_CFG_STS_LINK_RATE_25G]         = SPEED_25000,
 278                [NFP_NET_CFG_STS_LINK_RATE_40G]         = SPEED_40000,
 279                [NFP_NET_CFG_STS_LINK_RATE_50G]         = SPEED_50000,
 280                [NFP_NET_CFG_STS_LINK_RATE_100G]        = SPEED_100000,
 281        };
 282        struct nfp_eth_table_port *eth_port;
 283        struct nfp_port *port;
 284        struct nfp_net *nn;
 285        u32 sts, ls;
 286
 287        /* Init to unknowns */
 288        ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
 289        ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
 290        ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
 291        cmd->base.port = PORT_OTHER;
 292        cmd->base.speed = SPEED_UNKNOWN;
 293        cmd->base.duplex = DUPLEX_UNKNOWN;
 294
 295        port = nfp_port_from_netdev(netdev);
 296        eth_port = nfp_port_get_eth_port(port);
 297        if (eth_port) {
 298                cmd->base.autoneg = eth_port->aneg != NFP_ANEG_DISABLED ?
 299                        AUTONEG_ENABLE : AUTONEG_DISABLE;
 300                nfp_net_set_fec_link_mode(eth_port, cmd);
 301        }
 302
 303        if (!netif_carrier_ok(netdev))
 304                return 0;
 305
 306        /* Use link speed from ETH table if available, otherwise try the BAR */
 307        if (eth_port) {
 308                cmd->base.port = eth_port->port_type;
 309                cmd->base.speed = eth_port->speed;
 310                cmd->base.duplex = DUPLEX_FULL;
 311                return 0;
 312        }
 313
 314        if (!nfp_netdev_is_nfp_net(netdev))
 315                return -EOPNOTSUPP;
 316        nn = netdev_priv(netdev);
 317
 318        sts = nn_readl(nn, NFP_NET_CFG_STS);
 319
 320        ls = FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts);
 321        if (ls == NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED)
 322                return -EOPNOTSUPP;
 323
 324        if (ls == NFP_NET_CFG_STS_LINK_RATE_UNKNOWN ||
 325            ls >= ARRAY_SIZE(ls_to_ethtool))
 326                return 0;
 327
 328        cmd->base.speed = ls_to_ethtool[ls];
 329        cmd->base.duplex = DUPLEX_FULL;
 330
 331        return 0;
 332}
 333
 334static int
 335nfp_net_set_link_ksettings(struct net_device *netdev,
 336                           const struct ethtool_link_ksettings *cmd)
 337{
 338        struct nfp_eth_table_port *eth_port;
 339        struct nfp_port *port;
 340        struct nfp_nsp *nsp;
 341        int err;
 342
 343        port = nfp_port_from_netdev(netdev);
 344        eth_port = __nfp_port_get_eth_port(port);
 345        if (!eth_port)
 346                return -EOPNOTSUPP;
 347
 348        if (netif_running(netdev)) {
 349                netdev_warn(netdev, "Changing settings not allowed on an active interface. It may cause the port to be disabled until driver reload.\n");
 350                return -EBUSY;
 351        }
 352
 353        nsp = nfp_eth_config_start(port->app->cpp, eth_port->index);
 354        if (IS_ERR(nsp))
 355                return PTR_ERR(nsp);
 356
 357        err = __nfp_eth_set_aneg(nsp, cmd->base.autoneg == AUTONEG_ENABLE ?
 358                                 NFP_ANEG_AUTO : NFP_ANEG_DISABLED);
 359        if (err)
 360                goto err_bad_set;
 361        if (cmd->base.speed != SPEED_UNKNOWN) {
 362                u32 speed = cmd->base.speed / eth_port->lanes;
 363
 364                err = __nfp_eth_set_speed(nsp, speed);
 365                if (err)
 366                        goto err_bad_set;
 367        }
 368
 369        err = nfp_eth_config_commit_end(nsp);
 370        if (err > 0)
 371                return 0; /* no change */
 372
 373        nfp_net_refresh_port_table(port);
 374
 375        return err;
 376
 377err_bad_set:
 378        nfp_eth_config_cleanup_end(nsp);
 379        return err;
 380}
 381
 382static void nfp_net_get_ringparam(struct net_device *netdev,
 383                                  struct ethtool_ringparam *ring)
 384{
 385        struct nfp_net *nn = netdev_priv(netdev);
 386
 387        ring->rx_max_pending = NFP_NET_MAX_RX_DESCS;
 388        ring->tx_max_pending = NFP_NET_MAX_TX_DESCS;
 389        ring->rx_pending = nn->dp.rxd_cnt;
 390        ring->tx_pending = nn->dp.txd_cnt;
 391}
 392
 393static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt)
 394{
 395        struct nfp_net_dp *dp;
 396
 397        dp = nfp_net_clone_dp(nn);
 398        if (!dp)
 399                return -ENOMEM;
 400
 401        dp->rxd_cnt = rxd_cnt;
 402        dp->txd_cnt = txd_cnt;
 403
 404        return nfp_net_ring_reconfig(nn, dp, NULL);
 405}
 406
 407static int nfp_net_set_ringparam(struct net_device *netdev,
 408                                 struct ethtool_ringparam *ring)
 409{
 410        struct nfp_net *nn = netdev_priv(netdev);
 411        u32 rxd_cnt, txd_cnt;
 412
 413        /* We don't have separate queues/rings for small/large frames. */
 414        if (ring->rx_mini_pending || ring->rx_jumbo_pending)
 415                return -EINVAL;
 416
 417        /* Round up to supported values */
 418        rxd_cnt = roundup_pow_of_two(ring->rx_pending);
 419        txd_cnt = roundup_pow_of_two(ring->tx_pending);
 420
 421        if (rxd_cnt < NFP_NET_MIN_RX_DESCS || rxd_cnt > NFP_NET_MAX_RX_DESCS ||
 422            txd_cnt < NFP_NET_MIN_TX_DESCS || txd_cnt > NFP_NET_MAX_TX_DESCS)
 423                return -EINVAL;
 424
 425        if (nn->dp.rxd_cnt == rxd_cnt && nn->dp.txd_cnt == txd_cnt)
 426                return 0;
 427
 428        nn_dbg(nn, "Change ring size: RxQ %u->%u, TxQ %u->%u\n",
 429               nn->dp.rxd_cnt, rxd_cnt, nn->dp.txd_cnt, txd_cnt);
 430
 431        return nfp_net_set_ring_size(nn, rxd_cnt, txd_cnt);
 432}
 433
 434static unsigned int nfp_vnic_get_sw_stats_count(struct net_device *netdev)
 435{
 436        struct nfp_net *nn = netdev_priv(netdev);
 437
 438        return NN_RVEC_GATHER_STATS + nn->max_r_vecs * NN_RVEC_PER_Q_STATS +
 439                NN_CTRL_PATH_STATS;
 440}
 441
 442static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data)
 443{
 444        struct nfp_net *nn = netdev_priv(netdev);
 445        int i;
 446
 447        for (i = 0; i < nn->max_r_vecs; i++) {
 448                ethtool_sprintf(&data, "rvec_%u_rx_pkts", i);
 449                ethtool_sprintf(&data, "rvec_%u_tx_pkts", i);
 450                ethtool_sprintf(&data, "rvec_%u_tx_busy", i);
 451        }
 452
 453        ethtool_sprintf(&data, "hw_rx_csum_ok");
 454        ethtool_sprintf(&data, "hw_rx_csum_inner_ok");
 455        ethtool_sprintf(&data, "hw_rx_csum_complete");
 456        ethtool_sprintf(&data, "hw_rx_csum_err");
 457        ethtool_sprintf(&data, "rx_replace_buf_alloc_fail");
 458        ethtool_sprintf(&data, "rx_tls_decrypted_packets");
 459        ethtool_sprintf(&data, "hw_tx_csum");
 460        ethtool_sprintf(&data, "hw_tx_inner_csum");
 461        ethtool_sprintf(&data, "tx_gather");
 462        ethtool_sprintf(&data, "tx_lso");
 463        ethtool_sprintf(&data, "tx_tls_encrypted_packets");
 464        ethtool_sprintf(&data, "tx_tls_ooo");
 465        ethtool_sprintf(&data, "tx_tls_drop_no_sync_data");
 466
 467        ethtool_sprintf(&data, "hw_tls_no_space");
 468        ethtool_sprintf(&data, "rx_tls_resync_req_ok");
 469        ethtool_sprintf(&data, "rx_tls_resync_req_ign");
 470        ethtool_sprintf(&data, "rx_tls_resync_sent");
 471
 472        return data;
 473}
 474
 475static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
 476{
 477        u64 gathered_stats[NN_RVEC_GATHER_STATS] = {};
 478        struct nfp_net *nn = netdev_priv(netdev);
 479        u64 tmp[NN_RVEC_GATHER_STATS];
 480        unsigned int i, j;
 481
 482        for (i = 0; i < nn->max_r_vecs; i++) {
 483                unsigned int start;
 484
 485                do {
 486                        start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync);
 487                        data[0] = nn->r_vecs[i].rx_pkts;
 488                        tmp[0] = nn->r_vecs[i].hw_csum_rx_ok;
 489                        tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok;
 490                        tmp[2] = nn->r_vecs[i].hw_csum_rx_complete;
 491                        tmp[3] = nn->r_vecs[i].hw_csum_rx_error;
 492                        tmp[4] = nn->r_vecs[i].rx_replace_buf_alloc_fail;
 493                        tmp[5] = nn->r_vecs[i].hw_tls_rx;
 494                } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start));
 495
 496                do {
 497                        start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync);
 498                        data[1] = nn->r_vecs[i].tx_pkts;
 499                        data[2] = nn->r_vecs[i].tx_busy;
 500                        tmp[6] = nn->r_vecs[i].hw_csum_tx;
 501                        tmp[7] = nn->r_vecs[i].hw_csum_tx_inner;
 502                        tmp[8] = nn->r_vecs[i].tx_gather;
 503                        tmp[9] = nn->r_vecs[i].tx_lso;
 504                        tmp[10] = nn->r_vecs[i].hw_tls_tx;
 505                        tmp[11] = nn->r_vecs[i].tls_tx_fallback;
 506                        tmp[12] = nn->r_vecs[i].tls_tx_no_fallback;
 507                } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start));
 508
 509                data += NN_RVEC_PER_Q_STATS;
 510
 511                for (j = 0; j < NN_RVEC_GATHER_STATS; j++)
 512                        gathered_stats[j] += tmp[j];
 513        }
 514
 515        for (j = 0; j < NN_RVEC_GATHER_STATS; j++)
 516                *data++ = gathered_stats[j];
 517
 518        *data++ = atomic_read(&nn->ktls_no_space);
 519        *data++ = atomic_read(&nn->ktls_rx_resync_req);
 520        *data++ = atomic_read(&nn->ktls_rx_resync_ign);
 521        *data++ = atomic_read(&nn->ktls_rx_resync_sent);
 522
 523        return data;
 524}
 525
 526static unsigned int nfp_vnic_get_hw_stats_count(unsigned int num_vecs)
 527{
 528        return NN_ET_GLOBAL_STATS_LEN + num_vecs * 4;
 529}
 530
 531static u8 *
 532nfp_vnic_get_hw_stats_strings(u8 *data, unsigned int num_vecs, bool repr)
 533{
 534        int swap_off, i;
 535
 536        BUILD_BUG_ON(NN_ET_GLOBAL_STATS_LEN < NN_ET_SWITCH_STATS_LEN * 2);
 537        /* If repr is true first add SWITCH_STATS_LEN and then subtract it
 538         * effectively swapping the RX and TX statistics (giving us the RX
 539         * and TX from perspective of the switch).
 540         */
 541        swap_off = repr * NN_ET_SWITCH_STATS_LEN;
 542
 543        for (i = 0; i < NN_ET_SWITCH_STATS_LEN; i++)
 544                ethtool_sprintf(&data, nfp_net_et_stats[i + swap_off].name);
 545
 546        for (i = NN_ET_SWITCH_STATS_LEN; i < NN_ET_SWITCH_STATS_LEN * 2; i++)
 547                ethtool_sprintf(&data, nfp_net_et_stats[i - swap_off].name);
 548
 549        for (i = NN_ET_SWITCH_STATS_LEN * 2; i < NN_ET_GLOBAL_STATS_LEN; i++)
 550                ethtool_sprintf(&data, nfp_net_et_stats[i].name);
 551
 552        for (i = 0; i < num_vecs; i++) {
 553                ethtool_sprintf(&data, "rxq_%u_pkts", i);
 554                ethtool_sprintf(&data, "rxq_%u_bytes", i);
 555                ethtool_sprintf(&data, "txq_%u_pkts", i);
 556                ethtool_sprintf(&data, "txq_%u_bytes", i);
 557        }
 558
 559        return data;
 560}
 561
 562static u64 *
 563nfp_vnic_get_hw_stats(u64 *data, u8 __iomem *mem, unsigned int num_vecs)
 564{
 565        unsigned int i;
 566
 567        for (i = 0; i < NN_ET_GLOBAL_STATS_LEN; i++)
 568                *data++ = readq(mem + nfp_net_et_stats[i].off);
 569
 570        for (i = 0; i < num_vecs; i++) {
 571                *data++ = readq(mem + NFP_NET_CFG_RXR_STATS(i));
 572                *data++ = readq(mem + NFP_NET_CFG_RXR_STATS(i) + 8);
 573                *data++ = readq(mem + NFP_NET_CFG_TXR_STATS(i));
 574                *data++ = readq(mem + NFP_NET_CFG_TXR_STATS(i) + 8);
 575        }
 576
 577        return data;
 578}
 579
 580static unsigned int nfp_vnic_get_tlv_stats_count(struct nfp_net *nn)
 581{
 582        return nn->tlv_caps.vnic_stats_cnt + nn->max_r_vecs * 4;
 583}
 584
 585static u8 *nfp_vnic_get_tlv_stats_strings(struct nfp_net *nn, u8 *data)
 586{
 587        unsigned int i, id;
 588        u8 __iomem *mem;
 589        u64 id_word = 0;
 590
 591        mem = nn->dp.ctrl_bar + nn->tlv_caps.vnic_stats_off;
 592        for (i = 0; i < nn->tlv_caps.vnic_stats_cnt; i++) {
 593                if (!(i % 4))
 594                        id_word = readq(mem + i * 2);
 595
 596                id = (u16)id_word;
 597                id_word >>= 16;
 598
 599                if (id < ARRAY_SIZE(nfp_tlv_stat_names) &&
 600                    nfp_tlv_stat_names[id][0]) {
 601                        memcpy(data, nfp_tlv_stat_names[id], ETH_GSTRING_LEN);
 602                        data += ETH_GSTRING_LEN;
 603                } else {
 604                        ethtool_sprintf(&data, "dev_unknown_stat%u", id);
 605                }
 606        }
 607
 608        for (i = 0; i < nn->max_r_vecs; i++) {
 609                ethtool_sprintf(&data, "rxq_%u_pkts", i);
 610                ethtool_sprintf(&data, "rxq_%u_bytes", i);
 611                ethtool_sprintf(&data, "txq_%u_pkts", i);
 612                ethtool_sprintf(&data, "txq_%u_bytes", i);
 613        }
 614
 615        return data;
 616}
 617
 618static u64 *nfp_vnic_get_tlv_stats(struct nfp_net *nn, u64 *data)
 619{
 620        u8 __iomem *mem;
 621        unsigned int i;
 622
 623        mem = nn->dp.ctrl_bar + nn->tlv_caps.vnic_stats_off;
 624        mem += roundup(2 * nn->tlv_caps.vnic_stats_cnt, 8);
 625        for (i = 0; i < nn->tlv_caps.vnic_stats_cnt; i++)
 626                *data++ = readq(mem + i * 8);
 627
 628        mem = nn->dp.ctrl_bar;
 629        for (i = 0; i < nn->max_r_vecs; i++) {
 630                *data++ = readq(mem + NFP_NET_CFG_RXR_STATS(i));
 631                *data++ = readq(mem + NFP_NET_CFG_RXR_STATS(i) + 8);
 632                *data++ = readq(mem + NFP_NET_CFG_TXR_STATS(i));
 633                *data++ = readq(mem + NFP_NET_CFG_TXR_STATS(i) + 8);
 634        }
 635
 636        return data;
 637}
 638
 639static unsigned int nfp_mac_get_stats_count(struct net_device *netdev)
 640{
 641        struct nfp_port *port;
 642
 643        port = nfp_port_from_netdev(netdev);
 644        if (!__nfp_port_get_eth_port(port) || !port->eth_stats)
 645                return 0;
 646
 647        return ARRAY_SIZE(nfp_mac_et_stats);
 648}
 649
 650static u8 *nfp_mac_get_stats_strings(struct net_device *netdev, u8 *data)
 651{
 652        struct nfp_port *port;
 653        unsigned int i;
 654
 655        port = nfp_port_from_netdev(netdev);
 656        if (!__nfp_port_get_eth_port(port) || !port->eth_stats)
 657                return data;
 658
 659        for (i = 0; i < ARRAY_SIZE(nfp_mac_et_stats); i++)
 660                ethtool_sprintf(&data, "mac.%s", nfp_mac_et_stats[i].name);
 661
 662        return data;
 663}
 664
 665static u64 *nfp_mac_get_stats(struct net_device *netdev, u64 *data)
 666{
 667        struct nfp_port *port;
 668        unsigned int i;
 669
 670        port = nfp_port_from_netdev(netdev);
 671        if (!__nfp_port_get_eth_port(port) || !port->eth_stats)
 672                return data;
 673
 674        for (i = 0; i < ARRAY_SIZE(nfp_mac_et_stats); i++)
 675                *data++ = readq(port->eth_stats + nfp_mac_et_stats[i].off);
 676
 677        return data;
 678}
 679
 680static void nfp_net_get_strings(struct net_device *netdev,
 681                                u32 stringset, u8 *data)
 682{
 683        struct nfp_net *nn = netdev_priv(netdev);
 684
 685        switch (stringset) {
 686        case ETH_SS_STATS:
 687                data = nfp_vnic_get_sw_stats_strings(netdev, data);
 688                if (!nn->tlv_caps.vnic_stats_off)
 689                        data = nfp_vnic_get_hw_stats_strings(data,
 690                                                             nn->max_r_vecs,
 691                                                             false);
 692                else
 693                        data = nfp_vnic_get_tlv_stats_strings(nn, data);
 694                data = nfp_mac_get_stats_strings(netdev, data);
 695                data = nfp_app_port_get_stats_strings(nn->port, data);
 696                break;
 697        }
 698}
 699
 700static void
 701nfp_net_get_stats(struct net_device *netdev, struct ethtool_stats *stats,
 702                  u64 *data)
 703{
 704        struct nfp_net *nn = netdev_priv(netdev);
 705
 706        data = nfp_vnic_get_sw_stats(netdev, data);
 707        if (!nn->tlv_caps.vnic_stats_off)
 708                data = nfp_vnic_get_hw_stats(data, nn->dp.ctrl_bar,
 709                                             nn->max_r_vecs);
 710        else
 711                data = nfp_vnic_get_tlv_stats(nn, data);
 712        data = nfp_mac_get_stats(netdev, data);
 713        data = nfp_app_port_get_stats(nn->port, data);
 714}
 715
 716static int nfp_net_get_sset_count(struct net_device *netdev, int sset)
 717{
 718        struct nfp_net *nn = netdev_priv(netdev);
 719        unsigned int cnt;
 720
 721        switch (sset) {
 722        case ETH_SS_STATS:
 723                cnt = nfp_vnic_get_sw_stats_count(netdev);
 724                if (!nn->tlv_caps.vnic_stats_off)
 725                        cnt += nfp_vnic_get_hw_stats_count(nn->max_r_vecs);
 726                else
 727                        cnt += nfp_vnic_get_tlv_stats_count(nn);
 728                cnt += nfp_mac_get_stats_count(netdev);
 729                cnt += nfp_app_port_get_stats_count(nn->port);
 730                return cnt;
 731        default:
 732                return -EOPNOTSUPP;
 733        }
 734}
 735
 736static void nfp_port_get_strings(struct net_device *netdev,
 737                                 u32 stringset, u8 *data)
 738{
 739        struct nfp_port *port = nfp_port_from_netdev(netdev);
 740
 741        switch (stringset) {
 742        case ETH_SS_STATS:
 743                if (nfp_port_is_vnic(port))
 744                        data = nfp_vnic_get_hw_stats_strings(data, 0, true);
 745                else
 746                        data = nfp_mac_get_stats_strings(netdev, data);
 747                data = nfp_app_port_get_stats_strings(port, data);
 748                break;
 749        }
 750}
 751
 752static void
 753nfp_port_get_stats(struct net_device *netdev, struct ethtool_stats *stats,
 754                   u64 *data)
 755{
 756        struct nfp_port *port = nfp_port_from_netdev(netdev);
 757
 758        if (nfp_port_is_vnic(port))
 759                data = nfp_vnic_get_hw_stats(data, port->vnic, 0);
 760        else
 761                data = nfp_mac_get_stats(netdev, data);
 762        data = nfp_app_port_get_stats(port, data);
 763}
 764
 765static int nfp_port_get_sset_count(struct net_device *netdev, int sset)
 766{
 767        struct nfp_port *port = nfp_port_from_netdev(netdev);
 768        unsigned int count;
 769
 770        switch (sset) {
 771        case ETH_SS_STATS:
 772                if (nfp_port_is_vnic(port))
 773                        count = nfp_vnic_get_hw_stats_count(0);
 774                else
 775                        count = nfp_mac_get_stats_count(netdev);
 776                count += nfp_app_port_get_stats_count(port);
 777                return count;
 778        default:
 779                return -EOPNOTSUPP;
 780        }
 781}
 782
 783static int nfp_port_fec_ethtool_to_nsp(u32 fec)
 784{
 785        switch (fec) {
 786        case ETHTOOL_FEC_AUTO:
 787                return NFP_FEC_AUTO_BIT;
 788        case ETHTOOL_FEC_OFF:
 789                return NFP_FEC_DISABLED_BIT;
 790        case ETHTOOL_FEC_RS:
 791                return NFP_FEC_REED_SOLOMON_BIT;
 792        case ETHTOOL_FEC_BASER:
 793                return NFP_FEC_BASER_BIT;
 794        default:
 795                /* NSP only supports a single mode at a time */
 796                return -EOPNOTSUPP;
 797        }
 798}
 799
 800static u32 nfp_port_fec_nsp_to_ethtool(u32 fec)
 801{
 802        u32 result = 0;
 803
 804        if (fec & NFP_FEC_AUTO)
 805                result |= ETHTOOL_FEC_AUTO;
 806        if (fec & NFP_FEC_BASER)
 807                result |= ETHTOOL_FEC_BASER;
 808        if (fec & NFP_FEC_REED_SOLOMON)
 809                result |= ETHTOOL_FEC_RS;
 810        if (fec & NFP_FEC_DISABLED)
 811                result |= ETHTOOL_FEC_OFF;
 812
 813        return result ?: ETHTOOL_FEC_NONE;
 814}
 815
 816static int
 817nfp_port_get_fecparam(struct net_device *netdev,
 818                      struct ethtool_fecparam *param)
 819{
 820        struct nfp_eth_table_port *eth_port;
 821        struct nfp_port *port;
 822
 823        param->active_fec = ETHTOOL_FEC_NONE;
 824        param->fec = ETHTOOL_FEC_NONE;
 825
 826        port = nfp_port_from_netdev(netdev);
 827        eth_port = nfp_port_get_eth_port(port);
 828        if (!eth_port)
 829                return -EOPNOTSUPP;
 830
 831        if (!nfp_eth_can_support_fec(eth_port))
 832                return 0;
 833
 834        param->fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec_modes_supported);
 835        param->active_fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec);
 836
 837        return 0;
 838}
 839
 840static int
 841nfp_port_set_fecparam(struct net_device *netdev,
 842                      struct ethtool_fecparam *param)
 843{
 844        struct nfp_eth_table_port *eth_port;
 845        struct nfp_port *port;
 846        int err, fec;
 847
 848        port = nfp_port_from_netdev(netdev);
 849        eth_port = nfp_port_get_eth_port(port);
 850        if (!eth_port)
 851                return -EOPNOTSUPP;
 852
 853        if (!nfp_eth_can_support_fec(eth_port))
 854                return -EOPNOTSUPP;
 855
 856        fec = nfp_port_fec_ethtool_to_nsp(param->fec);
 857        if (fec < 0)
 858                return fec;
 859
 860        err = nfp_eth_set_fec(port->app->cpp, eth_port->index, fec);
 861        if (!err)
 862                /* Only refresh if we did something */
 863                nfp_net_refresh_port_table(port);
 864
 865        return err < 0 ? err : 0;
 866}
 867
 868/* RX network flow classification (RSS, filters, etc)
 869 */
 870static u32 ethtool_flow_to_nfp_flag(u32 flow_type)
 871{
 872        static const u32 xlate_ethtool_to_nfp[IPV6_FLOW + 1] = {
 873                [TCP_V4_FLOW]   = NFP_NET_CFG_RSS_IPV4_TCP,
 874                [TCP_V6_FLOW]   = NFP_NET_CFG_RSS_IPV6_TCP,
 875                [UDP_V4_FLOW]   = NFP_NET_CFG_RSS_IPV4_UDP,
 876                [UDP_V6_FLOW]   = NFP_NET_CFG_RSS_IPV6_UDP,
 877                [IPV4_FLOW]     = NFP_NET_CFG_RSS_IPV4,
 878                [IPV6_FLOW]     = NFP_NET_CFG_RSS_IPV6,
 879        };
 880
 881        if (flow_type >= ARRAY_SIZE(xlate_ethtool_to_nfp))
 882                return 0;
 883
 884        return xlate_ethtool_to_nfp[flow_type];
 885}
 886
 887static int nfp_net_get_rss_hash_opts(struct nfp_net *nn,
 888                                     struct ethtool_rxnfc *cmd)
 889{
 890        u32 nfp_rss_flag;
 891
 892        cmd->data = 0;
 893
 894        if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
 895                return -EOPNOTSUPP;
 896
 897        nfp_rss_flag = ethtool_flow_to_nfp_flag(cmd->flow_type);
 898        if (!nfp_rss_flag)
 899                return -EINVAL;
 900
 901        cmd->data |= RXH_IP_SRC | RXH_IP_DST;
 902        if (nn->rss_cfg & nfp_rss_flag)
 903                cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 904
 905        return 0;
 906}
 907
 908static int nfp_net_get_rxnfc(struct net_device *netdev,
 909                             struct ethtool_rxnfc *cmd, u32 *rule_locs)
 910{
 911        struct nfp_net *nn = netdev_priv(netdev);
 912
 913        switch (cmd->cmd) {
 914        case ETHTOOL_GRXRINGS:
 915                cmd->data = nn->dp.num_rx_rings;
 916                return 0;
 917        case ETHTOOL_GRXFH:
 918                return nfp_net_get_rss_hash_opts(nn, cmd);
 919        default:
 920                return -EOPNOTSUPP;
 921        }
 922}
 923
 924static int nfp_net_set_rss_hash_opt(struct nfp_net *nn,
 925                                    struct ethtool_rxnfc *nfc)
 926{
 927        u32 new_rss_cfg = nn->rss_cfg;
 928        u32 nfp_rss_flag;
 929        int err;
 930
 931        if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
 932                return -EOPNOTSUPP;
 933
 934        /* RSS only supports IP SA/DA and L4 src/dst ports  */
 935        if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
 936                          RXH_L4_B_0_1 | RXH_L4_B_2_3))
 937                return -EINVAL;
 938
 939        /* We need at least the IP SA/DA fields for hashing */
 940        if (!(nfc->data & RXH_IP_SRC) ||
 941            !(nfc->data & RXH_IP_DST))
 942                return -EINVAL;
 943
 944        nfp_rss_flag = ethtool_flow_to_nfp_flag(nfc->flow_type);
 945        if (!nfp_rss_flag)
 946                return -EINVAL;
 947
 948        switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 949        case 0:
 950                new_rss_cfg &= ~nfp_rss_flag;
 951                break;
 952        case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 953                new_rss_cfg |= nfp_rss_flag;
 954                break;
 955        default:
 956                return -EINVAL;
 957        }
 958
 959        new_rss_cfg |= FIELD_PREP(NFP_NET_CFG_RSS_HFUNC, nn->rss_hfunc);
 960        new_rss_cfg |= NFP_NET_CFG_RSS_MASK;
 961
 962        if (new_rss_cfg == nn->rss_cfg)
 963                return 0;
 964
 965        writel(new_rss_cfg, nn->dp.ctrl_bar + NFP_NET_CFG_RSS_CTRL);
 966        err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_RSS);
 967        if (err)
 968                return err;
 969
 970        nn->rss_cfg = new_rss_cfg;
 971
 972        nn_dbg(nn, "Changed RSS config to 0x%x\n", nn->rss_cfg);
 973        return 0;
 974}
 975
 976static int nfp_net_set_rxnfc(struct net_device *netdev,
 977                             struct ethtool_rxnfc *cmd)
 978{
 979        struct nfp_net *nn = netdev_priv(netdev);
 980
 981        switch (cmd->cmd) {
 982        case ETHTOOL_SRXFH:
 983                return nfp_net_set_rss_hash_opt(nn, cmd);
 984        default:
 985                return -EOPNOTSUPP;
 986        }
 987}
 988
 989static u32 nfp_net_get_rxfh_indir_size(struct net_device *netdev)
 990{
 991        struct nfp_net *nn = netdev_priv(netdev);
 992
 993        if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
 994                return 0;
 995
 996        return ARRAY_SIZE(nn->rss_itbl);
 997}
 998
 999static u32 nfp_net_get_rxfh_key_size(struct net_device *netdev)
1000{
1001        struct nfp_net *nn = netdev_priv(netdev);
1002
1003        if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
1004                return -EOPNOTSUPP;
1005
1006        return nfp_net_rss_key_sz(nn);
1007}
1008
1009static int nfp_net_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
1010                            u8 *hfunc)
1011{
1012        struct nfp_net *nn = netdev_priv(netdev);
1013        int i;
1014
1015        if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
1016                return -EOPNOTSUPP;
1017
1018        if (indir)
1019                for (i = 0; i < ARRAY_SIZE(nn->rss_itbl); i++)
1020                        indir[i] = nn->rss_itbl[i];
1021        if (key)
1022                memcpy(key, nn->rss_key, nfp_net_rss_key_sz(nn));
1023        if (hfunc) {
1024                *hfunc = nn->rss_hfunc;
1025                if (*hfunc >= 1 << ETH_RSS_HASH_FUNCS_COUNT)
1026                        *hfunc = ETH_RSS_HASH_UNKNOWN;
1027        }
1028
1029        return 0;
1030}
1031
1032static int nfp_net_set_rxfh(struct net_device *netdev,
1033                            const u32 *indir, const u8 *key,
1034                            const u8 hfunc)
1035{
1036        struct nfp_net *nn = netdev_priv(netdev);
1037        int i;
1038
1039        if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY) ||
1040            !(hfunc == ETH_RSS_HASH_NO_CHANGE || hfunc == nn->rss_hfunc))
1041                return -EOPNOTSUPP;
1042
1043        if (!key && !indir)
1044                return 0;
1045
1046        if (key) {
1047                memcpy(nn->rss_key, key, nfp_net_rss_key_sz(nn));
1048                nfp_net_rss_write_key(nn);
1049        }
1050        if (indir) {
1051                for (i = 0; i < ARRAY_SIZE(nn->rss_itbl); i++)
1052                        nn->rss_itbl[i] = indir[i];
1053
1054                nfp_net_rss_write_itbl(nn);
1055        }
1056
1057        return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_RSS);
1058}
1059
1060/* Dump BAR registers
1061 */
1062static int nfp_net_get_regs_len(struct net_device *netdev)
1063{
1064        return NFP_NET_CFG_BAR_SZ;
1065}
1066
1067static void nfp_net_get_regs(struct net_device *netdev,
1068                             struct ethtool_regs *regs, void *p)
1069{
1070        struct nfp_net *nn = netdev_priv(netdev);
1071        u32 *regs_buf = p;
1072        int i;
1073
1074        regs->version = nn_readl(nn, NFP_NET_CFG_VERSION);
1075
1076        for (i = 0; i < NFP_NET_CFG_BAR_SZ / sizeof(u32); i++)
1077                regs_buf[i] = readl(nn->dp.ctrl_bar + (i * sizeof(u32)));
1078}
1079
1080static int nfp_net_get_coalesce(struct net_device *netdev,
1081                                struct ethtool_coalesce *ec,
1082                                struct kernel_ethtool_coalesce *kernel_coal,
1083                                struct netlink_ext_ack *extack)
1084{
1085        struct nfp_net *nn = netdev_priv(netdev);
1086
1087        if (!(nn->cap & NFP_NET_CFG_CTRL_IRQMOD))
1088                return -EINVAL;
1089
1090        ec->use_adaptive_rx_coalesce = nn->rx_coalesce_adapt_on;
1091        ec->use_adaptive_tx_coalesce = nn->tx_coalesce_adapt_on;
1092
1093        ec->rx_coalesce_usecs       = nn->rx_coalesce_usecs;
1094        ec->rx_max_coalesced_frames = nn->rx_coalesce_max_frames;
1095        ec->tx_coalesce_usecs       = nn->tx_coalesce_usecs;
1096        ec->tx_max_coalesced_frames = nn->tx_coalesce_max_frames;
1097
1098        return 0;
1099}
1100
1101/* Other debug dumps
1102 */
1103static int
1104nfp_dump_nsp_diag(struct nfp_app *app, struct ethtool_dump *dump, void *buffer)
1105{
1106        struct nfp_resource *res;
1107        int ret;
1108
1109        if (!app)
1110                return -EOPNOTSUPP;
1111
1112        dump->version = 1;
1113        dump->flag = NFP_DUMP_NSP_DIAG;
1114
1115        res = nfp_resource_acquire(app->cpp, NFP_RESOURCE_NSP_DIAG);
1116        if (IS_ERR(res))
1117                return PTR_ERR(res);
1118
1119        if (buffer) {
1120                if (dump->len != nfp_resource_size(res)) {
1121                        ret = -EINVAL;
1122                        goto exit_release;
1123                }
1124
1125                ret = nfp_cpp_read(app->cpp, nfp_resource_cpp_id(res),
1126                                   nfp_resource_address(res),
1127                                   buffer, dump->len);
1128                if (ret != dump->len)
1129                        ret = ret < 0 ? ret : -EIO;
1130                else
1131                        ret = 0;
1132        } else {
1133                dump->len = nfp_resource_size(res);
1134                ret = 0;
1135        }
1136exit_release:
1137        nfp_resource_release(res);
1138
1139        return ret;
1140}
1141
1142/* Set the dump flag/level. Calculate the dump length for flag > 0 only (new TLV
1143 * based dumps), since flag 0 (default) calculates the length in
1144 * nfp_app_get_dump_flag(), and we need to support triggering a level 0 dump
1145 * without setting the flag first, for backward compatibility.
1146 */
1147static int nfp_app_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1148{
1149        struct nfp_app *app = nfp_app_from_netdev(netdev);
1150        s64 len;
1151
1152        if (!app)
1153                return -EOPNOTSUPP;
1154
1155        if (val->flag == NFP_DUMP_NSP_DIAG) {
1156                app->pf->dump_flag = val->flag;
1157                return 0;
1158        }
1159
1160        if (!app->pf->dumpspec)
1161                return -EOPNOTSUPP;
1162
1163        len = nfp_net_dump_calculate_size(app->pf, app->pf->dumpspec,
1164                                          val->flag);
1165        if (len < 0)
1166                return len;
1167
1168        app->pf->dump_flag = val->flag;
1169        app->pf->dump_len = len;
1170
1171        return 0;
1172}
1173
1174static int
1175nfp_app_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1176{
1177        struct nfp_app *app = nfp_app_from_netdev(netdev);
1178
1179        if (!app)
1180                return -EOPNOTSUPP;
1181
1182        if (app->pf->dump_flag == NFP_DUMP_NSP_DIAG)
1183                return nfp_dump_nsp_diag(app, dump, NULL);
1184
1185        dump->flag = app->pf->dump_flag;
1186        dump->len = app->pf->dump_len;
1187
1188        return 0;
1189}
1190
1191static int
1192nfp_app_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1193                      void *buffer)
1194{
1195        struct nfp_app *app = nfp_app_from_netdev(netdev);
1196
1197        if (!app)
1198                return -EOPNOTSUPP;
1199
1200        if (app->pf->dump_flag == NFP_DUMP_NSP_DIAG)
1201                return nfp_dump_nsp_diag(app, dump, buffer);
1202
1203        dump->flag = app->pf->dump_flag;
1204        dump->len = app->pf->dump_len;
1205
1206        return nfp_net_dump_populate_buffer(app->pf, app->pf->dumpspec, dump,
1207                                            buffer);
1208}
1209
1210static int
1211nfp_port_get_module_info(struct net_device *netdev,
1212                         struct ethtool_modinfo *modinfo)
1213{
1214        struct nfp_eth_table_port *eth_port;
1215        struct nfp_port *port;
1216        unsigned int read_len;
1217        struct nfp_nsp *nsp;
1218        int err = 0;
1219        u8 data;
1220
1221        port = nfp_port_from_netdev(netdev);
1222        eth_port = nfp_port_get_eth_port(port);
1223        if (!eth_port)
1224                return -EOPNOTSUPP;
1225
1226        nsp = nfp_nsp_open(port->app->cpp);
1227        if (IS_ERR(nsp)) {
1228                err = PTR_ERR(nsp);
1229                netdev_err(netdev, "Failed to access the NSP: %d\n", err);
1230                return err;
1231        }
1232
1233        if (!nfp_nsp_has_read_module_eeprom(nsp)) {
1234                netdev_info(netdev, "reading module EEPROM not supported. Please update flash\n");
1235                err = -EOPNOTSUPP;
1236                goto exit_close_nsp;
1237        }
1238
1239        switch (eth_port->interface) {
1240        case NFP_INTERFACE_SFP:
1241        case NFP_INTERFACE_SFP28:
1242                err = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index,
1243                                                 SFP_SFF8472_COMPLIANCE, &data,
1244                                                 1, &read_len);
1245                if (err < 0)
1246                        goto exit_close_nsp;
1247
1248                if (!data) {
1249                        modinfo->type = ETH_MODULE_SFF_8079;
1250                        modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
1251                } else {
1252                        modinfo->type = ETH_MODULE_SFF_8472;
1253                        modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
1254                }
1255                break;
1256        case NFP_INTERFACE_QSFP:
1257                err = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index,
1258                                                 SFP_SFF_REV_COMPLIANCE, &data,
1259                                                 1, &read_len);
1260                if (err < 0)
1261                        goto exit_close_nsp;
1262
1263                if (data < 0x3) {
1264                        modinfo->type = ETH_MODULE_SFF_8436;
1265                        modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
1266                } else {
1267                        modinfo->type = ETH_MODULE_SFF_8636;
1268                        modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
1269                }
1270                break;
1271        case NFP_INTERFACE_QSFP28:
1272                modinfo->type = ETH_MODULE_SFF_8636;
1273                modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
1274                break;
1275        default:
1276                netdev_err(netdev, "Unsupported module 0x%x detected\n",
1277                           eth_port->interface);
1278                err = -EINVAL;
1279        }
1280
1281exit_close_nsp:
1282        nfp_nsp_close(nsp);
1283        return err;
1284}
1285
1286static int
1287nfp_port_get_module_eeprom(struct net_device *netdev,
1288                           struct ethtool_eeprom *eeprom, u8 *data)
1289{
1290        struct nfp_eth_table_port *eth_port;
1291        struct nfp_port *port;
1292        struct nfp_nsp *nsp;
1293        int err;
1294
1295        port = nfp_port_from_netdev(netdev);
1296        eth_port = __nfp_port_get_eth_port(port);
1297        if (!eth_port)
1298                return -EOPNOTSUPP;
1299
1300        nsp = nfp_nsp_open(port->app->cpp);
1301        if (IS_ERR(nsp)) {
1302                err = PTR_ERR(nsp);
1303                netdev_err(netdev, "Failed to access the NSP: %d\n", err);
1304                return err;
1305        }
1306
1307        if (!nfp_nsp_has_read_module_eeprom(nsp)) {
1308                netdev_info(netdev, "reading module EEPROM not supported. Please update flash\n");
1309                err = -EOPNOTSUPP;
1310                goto exit_close_nsp;
1311        }
1312
1313        err = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index,
1314                                         eeprom->offset, data, eeprom->len,
1315                                         &eeprom->len);
1316        if (err < 0) {
1317                if (eeprom->len) {
1318                        netdev_warn(netdev,
1319                                    "Incomplete read from module EEPROM: %d\n",
1320                                     err);
1321                        err = 0;
1322                } else {
1323                        netdev_err(netdev,
1324                                   "Reading from module EEPROM failed: %d\n",
1325                                   err);
1326                }
1327        }
1328
1329exit_close_nsp:
1330        nfp_nsp_close(nsp);
1331        return err;
1332}
1333
1334static int nfp_net_set_coalesce(struct net_device *netdev,
1335                                struct ethtool_coalesce *ec,
1336                                struct kernel_ethtool_coalesce *kernel_coal,
1337                                struct netlink_ext_ack *extack)
1338{
1339        struct nfp_net *nn = netdev_priv(netdev);
1340        unsigned int factor;
1341
1342        /* Compute factor used to convert coalesce '_usecs' parameters to
1343         * ME timestamp ticks.  There are 16 ME clock cycles for each timestamp
1344         * count.
1345         */
1346        factor = nn->me_freq_mhz / 16;
1347
1348        /* Each pair of (usecs, max_frames) fields specifies that interrupts
1349         * should be coalesced until
1350         *      (usecs > 0 && time_since_first_completion >= usecs) ||
1351         *      (max_frames > 0 && completed_frames >= max_frames)
1352         *
1353         * It is illegal to set both usecs and max_frames to zero as this would
1354         * cause interrupts to never be generated.  To disable coalescing, set
1355         * usecs = 0 and max_frames = 1.
1356         *
1357         * Some implementations ignore the value of max_frames and use the
1358         * condition time_since_first_completion >= usecs
1359         */
1360
1361        if (!(nn->cap & NFP_NET_CFG_CTRL_IRQMOD))
1362                return -EINVAL;
1363
1364        /* ensure valid configuration */
1365        if (!ec->rx_coalesce_usecs && !ec->rx_max_coalesced_frames)
1366                return -EINVAL;
1367
1368        if (!ec->tx_coalesce_usecs && !ec->tx_max_coalesced_frames)
1369                return -EINVAL;
1370
1371        if (nfp_net_coalesce_para_check(ec->rx_coalesce_usecs * factor,
1372                                        ec->rx_max_coalesced_frames))
1373                return -EINVAL;
1374
1375        if (nfp_net_coalesce_para_check(ec->tx_coalesce_usecs * factor,
1376                                        ec->tx_max_coalesced_frames))
1377                return -EINVAL;
1378
1379        /* configuration is valid */
1380        nn->rx_coalesce_adapt_on = !!ec->use_adaptive_rx_coalesce;
1381        nn->tx_coalesce_adapt_on = !!ec->use_adaptive_tx_coalesce;
1382
1383        nn->rx_coalesce_usecs      = ec->rx_coalesce_usecs;
1384        nn->rx_coalesce_max_frames = ec->rx_max_coalesced_frames;
1385        nn->tx_coalesce_usecs      = ec->tx_coalesce_usecs;
1386        nn->tx_coalesce_max_frames = ec->tx_max_coalesced_frames;
1387
1388        /* write configuration to device */
1389        nfp_net_coalesce_write_cfg(nn);
1390        return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD);
1391}
1392
1393static void nfp_net_get_channels(struct net_device *netdev,
1394                                 struct ethtool_channels *channel)
1395{
1396        struct nfp_net *nn = netdev_priv(netdev);
1397        unsigned int num_tx_rings;
1398
1399        num_tx_rings = nn->dp.num_tx_rings;
1400        if (nn->dp.xdp_prog)
1401                num_tx_rings -= nn->dp.num_rx_rings;
1402
1403        channel->max_rx = min(nn->max_rx_rings, nn->max_r_vecs);
1404        channel->max_tx = min(nn->max_tx_rings, nn->max_r_vecs);
1405        channel->max_combined = min(channel->max_rx, channel->max_tx);
1406        channel->max_other = NFP_NET_NON_Q_VECTORS;
1407        channel->combined_count = min(nn->dp.num_rx_rings, num_tx_rings);
1408        channel->rx_count = nn->dp.num_rx_rings - channel->combined_count;
1409        channel->tx_count = num_tx_rings - channel->combined_count;
1410        channel->other_count = NFP_NET_NON_Q_VECTORS;
1411}
1412
1413static int nfp_net_set_num_rings(struct nfp_net *nn, unsigned int total_rx,
1414                                 unsigned int total_tx)
1415{
1416        struct nfp_net_dp *dp;
1417
1418        dp = nfp_net_clone_dp(nn);
1419        if (!dp)
1420                return -ENOMEM;
1421
1422        dp->num_rx_rings = total_rx;
1423        dp->num_tx_rings = total_tx;
1424        /* nfp_net_check_config() will catch num_tx_rings > nn->max_tx_rings */
1425        if (dp->xdp_prog)
1426                dp->num_tx_rings += total_rx;
1427
1428        return nfp_net_ring_reconfig(nn, dp, NULL);
1429}
1430
1431static int nfp_net_set_channels(struct net_device *netdev,
1432                                struct ethtool_channels *channel)
1433{
1434        struct nfp_net *nn = netdev_priv(netdev);
1435        unsigned int total_rx, total_tx;
1436
1437        /* Reject unsupported */
1438        if (channel->other_count != NFP_NET_NON_Q_VECTORS ||
1439            (channel->rx_count && channel->tx_count))
1440                return -EINVAL;
1441
1442        total_rx = channel->combined_count + channel->rx_count;
1443        total_tx = channel->combined_count + channel->tx_count;
1444
1445        if (total_rx > min(nn->max_rx_rings, nn->max_r_vecs) ||
1446            total_tx > min(nn->max_tx_rings, nn->max_r_vecs))
1447                return -EINVAL;
1448
1449        return nfp_net_set_num_rings(nn, total_rx, total_tx);
1450}
1451
1452static const struct ethtool_ops nfp_net_ethtool_ops = {
1453        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
1454                                     ETHTOOL_COALESCE_MAX_FRAMES |
1455                                     ETHTOOL_COALESCE_USE_ADAPTIVE,
1456        .get_drvinfo            = nfp_net_get_drvinfo,
1457        .get_link               = ethtool_op_get_link,
1458        .get_ringparam          = nfp_net_get_ringparam,
1459        .set_ringparam          = nfp_net_set_ringparam,
1460        .get_strings            = nfp_net_get_strings,
1461        .get_ethtool_stats      = nfp_net_get_stats,
1462        .get_sset_count         = nfp_net_get_sset_count,
1463        .get_rxnfc              = nfp_net_get_rxnfc,
1464        .set_rxnfc              = nfp_net_set_rxnfc,
1465        .get_rxfh_indir_size    = nfp_net_get_rxfh_indir_size,
1466        .get_rxfh_key_size      = nfp_net_get_rxfh_key_size,
1467        .get_rxfh               = nfp_net_get_rxfh,
1468        .set_rxfh               = nfp_net_set_rxfh,
1469        .get_regs_len           = nfp_net_get_regs_len,
1470        .get_regs               = nfp_net_get_regs,
1471        .set_dump               = nfp_app_set_dump,
1472        .get_dump_flag          = nfp_app_get_dump_flag,
1473        .get_dump_data          = nfp_app_get_dump_data,
1474        .get_module_info        = nfp_port_get_module_info,
1475        .get_module_eeprom      = nfp_port_get_module_eeprom,
1476        .get_coalesce           = nfp_net_get_coalesce,
1477        .set_coalesce           = nfp_net_set_coalesce,
1478        .get_channels           = nfp_net_get_channels,
1479        .set_channels           = nfp_net_set_channels,
1480        .get_link_ksettings     = nfp_net_get_link_ksettings,
1481        .set_link_ksettings     = nfp_net_set_link_ksettings,
1482        .get_fecparam           = nfp_port_get_fecparam,
1483        .set_fecparam           = nfp_port_set_fecparam,
1484};
1485
1486const struct ethtool_ops nfp_port_ethtool_ops = {
1487        .get_drvinfo            = nfp_app_get_drvinfo,
1488        .get_link               = ethtool_op_get_link,
1489        .get_strings            = nfp_port_get_strings,
1490        .get_ethtool_stats      = nfp_port_get_stats,
1491        .get_sset_count         = nfp_port_get_sset_count,
1492        .set_dump               = nfp_app_set_dump,
1493        .get_dump_flag          = nfp_app_get_dump_flag,
1494        .get_dump_data          = nfp_app_get_dump_data,
1495        .get_module_info        = nfp_port_get_module_info,
1496        .get_module_eeprom      = nfp_port_get_module_eeprom,
1497        .get_link_ksettings     = nfp_net_get_link_ksettings,
1498        .set_link_ksettings     = nfp_net_set_link_ksettings,
1499        .get_fecparam           = nfp_port_get_fecparam,
1500        .set_fecparam           = nfp_port_set_fecparam,
1501};
1502
1503void nfp_net_set_ethtool_ops(struct net_device *netdev)
1504{
1505        netdev->ethtool_ops = &nfp_net_ethtool_ops;
1506}
1507