root/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfp_net_get_nspinfo
  2. nfp_get_drvinfo
  3. nfp_net_get_drvinfo
  4. nfp_app_get_drvinfo
  5. nfp_net_set_fec_link_mode
  6. nfp_net_get_link_ksettings
  7. nfp_net_set_link_ksettings
  8. nfp_net_get_ringparam
  9. nfp_net_set_ring_size
  10. nfp_net_set_ringparam
  11. __printf
  12. nfp_vnic_get_sw_stats_count
  13. nfp_vnic_get_sw_stats_strings
  14. nfp_vnic_get_sw_stats
  15. nfp_vnic_get_hw_stats_count
  16. nfp_vnic_get_hw_stats_strings
  17. nfp_vnic_get_hw_stats
  18. nfp_mac_get_stats_count
  19. nfp_mac_get_stats_strings
  20. nfp_mac_get_stats
  21. nfp_net_get_strings
  22. nfp_net_get_stats
  23. nfp_net_get_sset_count
  24. nfp_port_get_strings
  25. nfp_port_get_stats
  26. nfp_port_get_sset_count
  27. nfp_port_fec_ethtool_to_nsp
  28. nfp_port_fec_nsp_to_ethtool
  29. nfp_port_get_fecparam
  30. nfp_port_set_fecparam
  31. ethtool_flow_to_nfp_flag
  32. nfp_net_get_rss_hash_opts
  33. nfp_net_get_rxnfc
  34. nfp_net_set_rss_hash_opt
  35. nfp_net_set_rxnfc
  36. nfp_net_get_rxfh_indir_size
  37. nfp_net_get_rxfh_key_size
  38. nfp_net_get_rxfh
  39. nfp_net_set_rxfh
  40. nfp_net_get_regs_len
  41. nfp_net_get_regs
  42. nfp_net_get_coalesce
  43. nfp_dump_nsp_diag
  44. nfp_app_set_dump
  45. nfp_app_get_dump_flag
  46. nfp_app_get_dump_data
  47. nfp_port_get_module_info
  48. nfp_port_get_module_eeprom
  49. nfp_net_set_coalesce
  50. nfp_net_get_channels
  51. nfp_net_set_num_rings
  52. nfp_net_set_channels
  53. nfp_net_set_ethtool_ops

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

/* [<][>][^][v][top][bottom][index][help] */