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