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