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 51 #include "nfpcore/nfp.h" 52 #include "nfpcore/nfp_nsp.h" 53 #include "nfp_app.h" 54 #include "nfp_net_ctrl.h" 55 #include "nfp_net.h" 56 #include "nfp_port.h" 57 58 enum nfp_dump_diag { 59 NFP_DUMP_NSP_DIAG = 0, 60 }; 61 62 /* Support for stats. Returns netdev, driver, and device stats */ 63 enum { NETDEV_ET_STATS, NFP_NET_DRV_ET_STATS, NFP_NET_DEV_ET_STATS }; 64 struct _nfp_net_et_stats { 65 char name[ETH_GSTRING_LEN]; 66 int type; 67 int sz; 68 int off; 69 }; 70 71 #define NN_ET_NETDEV_STAT(m) NETDEV_ET_STATS, \ 72 FIELD_SIZEOF(struct net_device_stats, m), \ 73 offsetof(struct net_device_stats, m) 74 /* For stats in the control BAR (other than Q stats) */ 75 #define NN_ET_DEV_STAT(m) NFP_NET_DEV_ET_STATS, \ 76 sizeof(u64), \ 77 (m) 78 static const struct _nfp_net_et_stats nfp_net_et_stats[] = { 79 /* netdev stats */ 80 {"rx_packets", NN_ET_NETDEV_STAT(rx_packets)}, 81 {"tx_packets", NN_ET_NETDEV_STAT(tx_packets)}, 82 {"rx_bytes", NN_ET_NETDEV_STAT(rx_bytes)}, 83 {"tx_bytes", NN_ET_NETDEV_STAT(tx_bytes)}, 84 {"rx_errors", NN_ET_NETDEV_STAT(rx_errors)}, 85 {"tx_errors", NN_ET_NETDEV_STAT(tx_errors)}, 86 {"rx_dropped", NN_ET_NETDEV_STAT(rx_dropped)}, 87 {"tx_dropped", NN_ET_NETDEV_STAT(tx_dropped)}, 88 {"multicast", NN_ET_NETDEV_STAT(multicast)}, 89 {"collisions", NN_ET_NETDEV_STAT(collisions)}, 90 {"rx_over_errors", NN_ET_NETDEV_STAT(rx_over_errors)}, 91 {"rx_crc_errors", NN_ET_NETDEV_STAT(rx_crc_errors)}, 92 {"rx_frame_errors", NN_ET_NETDEV_STAT(rx_frame_errors)}, 93 {"rx_fifo_errors", NN_ET_NETDEV_STAT(rx_fifo_errors)}, 94 {"rx_missed_errors", NN_ET_NETDEV_STAT(rx_missed_errors)}, 95 {"tx_aborted_errors", NN_ET_NETDEV_STAT(tx_aborted_errors)}, 96 {"tx_carrier_errors", NN_ET_NETDEV_STAT(tx_carrier_errors)}, 97 {"tx_fifo_errors", NN_ET_NETDEV_STAT(tx_fifo_errors)}, 98 /* Stats from the device */ 99 {"dev_rx_discards", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_DISCARDS)}, 100 {"dev_rx_errors", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_ERRORS)}, 101 {"dev_rx_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_OCTETS)}, 102 {"dev_rx_uc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_UC_OCTETS)}, 103 {"dev_rx_mc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_MC_OCTETS)}, 104 {"dev_rx_bc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_BC_OCTETS)}, 105 {"dev_rx_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_FRAMES)}, 106 {"dev_rx_mc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_MC_FRAMES)}, 107 {"dev_rx_bc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_BC_FRAMES)}, 108 109 {"dev_tx_discards", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_DISCARDS)}, 110 {"dev_tx_errors", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_ERRORS)}, 111 {"dev_tx_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_OCTETS)}, 112 {"dev_tx_uc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_UC_OCTETS)}, 113 {"dev_tx_mc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_MC_OCTETS)}, 114 {"dev_tx_bc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_BC_OCTETS)}, 115 {"dev_tx_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_FRAMES)}, 116 {"dev_tx_mc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_MC_FRAMES)}, 117 {"dev_tx_bc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_BC_FRAMES)}, 118 119 {"bpf_pass_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP0_FRAMES)}, 120 {"bpf_pass_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP0_BYTES)}, 121 /* see comments in outro functions in nfp_bpf_jit.c to find out 122 * how different BPF modes use app-specific counters 123 */ 124 {"bpf_app1_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP1_FRAMES)}, 125 {"bpf_app1_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP1_BYTES)}, 126 {"bpf_app2_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP2_FRAMES)}, 127 {"bpf_app2_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP2_BYTES)}, 128 {"bpf_app3_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP3_FRAMES)}, 129 {"bpf_app3_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP3_BYTES)}, 130 }; 131 132 #define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats) 133 #define NN_ET_RVEC_STATS_LEN (nn->dp.num_r_vecs * 3) 134 #define NN_ET_RVEC_GATHER_STATS 7 135 #define NN_ET_QUEUE_STATS_LEN ((nn->dp.num_tx_rings + nn->dp.num_rx_rings) * 2) 136 #define NN_ET_STATS_LEN (NN_ET_GLOBAL_STATS_LEN + NN_ET_RVEC_GATHER_STATS + \ 137 NN_ET_RVEC_STATS_LEN + NN_ET_QUEUE_STATS_LEN) 138 139 static void nfp_net_get_nspinfo(struct nfp_app *app, char *version) 140 { 141 struct nfp_nsp *nsp; 142 143 if (!app) 144 return; 145 146 nsp = nfp_nsp_open(app->cpp); 147 if (IS_ERR(nsp)) 148 return; 149 150 snprintf(version, ETHTOOL_FWVERS_LEN, "sp:%hu.%hu", 151 nfp_nsp_get_abi_ver_major(nsp), 152 nfp_nsp_get_abi_ver_minor(nsp)); 153 154 nfp_nsp_close(nsp); 155 } 156 157 static void nfp_net_get_drvinfo(struct net_device *netdev, 158 struct ethtool_drvinfo *drvinfo) 159 { 160 char nsp_version[ETHTOOL_FWVERS_LEN] = {}; 161 struct nfp_net *nn = netdev_priv(netdev); 162 163 strlcpy(drvinfo->driver, nn->pdev->driver->name, 164 sizeof(drvinfo->driver)); 165 strlcpy(drvinfo->version, nfp_driver_version, sizeof(drvinfo->version)); 166 167 nfp_net_get_nspinfo(nn->app, nsp_version); 168 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 169 "%d.%d.%d.%d %s %s %s", 170 nn->fw_ver.resv, nn->fw_ver.class, 171 nn->fw_ver.major, nn->fw_ver.minor, nsp_version, 172 nfp_app_mip_name(nn->app), nfp_app_name(nn->app)); 173 strlcpy(drvinfo->bus_info, pci_name(nn->pdev), 174 sizeof(drvinfo->bus_info)); 175 176 drvinfo->n_stats = NN_ET_STATS_LEN; 177 drvinfo->regdump_len = NFP_NET_CFG_BAR_SZ; 178 } 179 180 /** 181 * nfp_net_get_link_ksettings - Get Link Speed settings 182 * @netdev: network interface device structure 183 * @cmd: ethtool command 184 * 185 * Reports speed settings based on info in the BAR provided by the fw. 186 */ 187 static int 188 nfp_net_get_link_ksettings(struct net_device *netdev, 189 struct ethtool_link_ksettings *cmd) 190 { 191 static const u32 ls_to_ethtool[] = { 192 [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0, 193 [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = SPEED_UNKNOWN, 194 [NFP_NET_CFG_STS_LINK_RATE_1G] = SPEED_1000, 195 [NFP_NET_CFG_STS_LINK_RATE_10G] = SPEED_10000, 196 [NFP_NET_CFG_STS_LINK_RATE_25G] = SPEED_25000, 197 [NFP_NET_CFG_STS_LINK_RATE_40G] = SPEED_40000, 198 [NFP_NET_CFG_STS_LINK_RATE_50G] = SPEED_50000, 199 [NFP_NET_CFG_STS_LINK_RATE_100G] = SPEED_100000, 200 }; 201 struct nfp_eth_table_port *eth_port; 202 struct nfp_port *port; 203 struct nfp_net *nn; 204 u32 sts, ls; 205 206 /* Init to unknowns */ 207 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); 208 cmd->base.port = PORT_OTHER; 209 cmd->base.speed = SPEED_UNKNOWN; 210 cmd->base.duplex = DUPLEX_UNKNOWN; 211 212 port = nfp_port_from_netdev(netdev); 213 eth_port = nfp_port_get_eth_port(port); 214 if (eth_port) 215 cmd->base.autoneg = eth_port->aneg != NFP_ANEG_DISABLED ? 216 AUTONEG_ENABLE : AUTONEG_DISABLE; 217 218 if (!netif_carrier_ok(netdev)) 219 return 0; 220 221 /* Use link speed from ETH table if available, otherwise try the BAR */ 222 if (eth_port) { 223 cmd->base.port = eth_port->port_type; 224 cmd->base.speed = eth_port->speed; 225 cmd->base.duplex = DUPLEX_FULL; 226 return 0; 227 } 228 229 if (!nfp_netdev_is_nfp_net(netdev)) 230 return -EOPNOTSUPP; 231 nn = netdev_priv(netdev); 232 233 sts = nn_readl(nn, NFP_NET_CFG_STS); 234 235 ls = FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts); 236 if (ls == NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED) 237 return -EOPNOTSUPP; 238 239 if (ls == NFP_NET_CFG_STS_LINK_RATE_UNKNOWN || 240 ls >= ARRAY_SIZE(ls_to_ethtool)) 241 return 0; 242 243 cmd->base.speed = ls_to_ethtool[sts]; 244 cmd->base.duplex = DUPLEX_FULL; 245 246 return 0; 247 } 248 249 static int 250 nfp_net_set_link_ksettings(struct net_device *netdev, 251 const struct ethtool_link_ksettings *cmd) 252 { 253 struct nfp_eth_table_port *eth_port; 254 struct nfp_port *port; 255 struct nfp_nsp *nsp; 256 int err; 257 258 port = nfp_port_from_netdev(netdev); 259 eth_port = __nfp_port_get_eth_port(port); 260 if (!eth_port) 261 return -EOPNOTSUPP; 262 263 if (netif_running(netdev)) { 264 netdev_warn(netdev, "Changing settings not allowed on an active interface. It may cause the port to be disabled until reboot.\n"); 265 return -EBUSY; 266 } 267 268 nsp = nfp_eth_config_start(port->app->cpp, eth_port->index); 269 if (IS_ERR(nsp)) 270 return PTR_ERR(nsp); 271 272 err = __nfp_eth_set_aneg(nsp, cmd->base.autoneg == AUTONEG_ENABLE ? 273 NFP_ANEG_AUTO : NFP_ANEG_DISABLED); 274 if (err) 275 goto err_bad_set; 276 if (cmd->base.speed != SPEED_UNKNOWN) { 277 u32 speed = cmd->base.speed / eth_port->lanes; 278 279 err = __nfp_eth_set_speed(nsp, speed); 280 if (err) 281 goto err_bad_set; 282 } 283 284 err = nfp_eth_config_commit_end(nsp); 285 if (err > 0) 286 return 0; /* no change */ 287 288 nfp_net_refresh_port_table(port); 289 290 return err; 291 292 err_bad_set: 293 nfp_eth_config_cleanup_end(nsp); 294 return err; 295 } 296 297 static void nfp_net_get_ringparam(struct net_device *netdev, 298 struct ethtool_ringparam *ring) 299 { 300 struct nfp_net *nn = netdev_priv(netdev); 301 302 ring->rx_max_pending = NFP_NET_MAX_RX_DESCS; 303 ring->tx_max_pending = NFP_NET_MAX_TX_DESCS; 304 ring->rx_pending = nn->dp.rxd_cnt; 305 ring->tx_pending = nn->dp.txd_cnt; 306 } 307 308 static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) 309 { 310 struct nfp_net_dp *dp; 311 312 dp = nfp_net_clone_dp(nn); 313 if (!dp) 314 return -ENOMEM; 315 316 dp->rxd_cnt = rxd_cnt; 317 dp->txd_cnt = txd_cnt; 318 319 return nfp_net_ring_reconfig(nn, dp, NULL); 320 } 321 322 static int nfp_net_set_ringparam(struct net_device *netdev, 323 struct ethtool_ringparam *ring) 324 { 325 struct nfp_net *nn = netdev_priv(netdev); 326 u32 rxd_cnt, txd_cnt; 327 328 /* We don't have separate queues/rings for small/large frames. */ 329 if (ring->rx_mini_pending || ring->rx_jumbo_pending) 330 return -EINVAL; 331 332 /* Round up to supported values */ 333 rxd_cnt = roundup_pow_of_two(ring->rx_pending); 334 txd_cnt = roundup_pow_of_two(ring->tx_pending); 335 336 if (rxd_cnt < NFP_NET_MIN_RX_DESCS || rxd_cnt > NFP_NET_MAX_RX_DESCS || 337 txd_cnt < NFP_NET_MIN_TX_DESCS || txd_cnt > NFP_NET_MAX_TX_DESCS) 338 return -EINVAL; 339 340 if (nn->dp.rxd_cnt == rxd_cnt && nn->dp.txd_cnt == txd_cnt) 341 return 0; 342 343 nn_dbg(nn, "Change ring size: RxQ %u->%u, TxQ %u->%u\n", 344 nn->dp.rxd_cnt, rxd_cnt, nn->dp.txd_cnt, txd_cnt); 345 346 return nfp_net_set_ring_size(nn, rxd_cnt, txd_cnt); 347 } 348 349 static void nfp_net_get_strings(struct net_device *netdev, 350 u32 stringset, u8 *data) 351 { 352 struct nfp_net *nn = netdev_priv(netdev); 353 u8 *p = data; 354 int i; 355 356 switch (stringset) { 357 case ETH_SS_STATS: 358 for (i = 0; i < NN_ET_GLOBAL_STATS_LEN; i++) { 359 memcpy(p, nfp_net_et_stats[i].name, ETH_GSTRING_LEN); 360 p += ETH_GSTRING_LEN; 361 } 362 for (i = 0; i < nn->dp.num_r_vecs; i++) { 363 sprintf(p, "rvec_%u_rx_pkts", i); 364 p += ETH_GSTRING_LEN; 365 sprintf(p, "rvec_%u_tx_pkts", i); 366 p += ETH_GSTRING_LEN; 367 sprintf(p, "rvec_%u_tx_busy", i); 368 p += ETH_GSTRING_LEN; 369 } 370 strncpy(p, "hw_rx_csum_ok", ETH_GSTRING_LEN); 371 p += ETH_GSTRING_LEN; 372 strncpy(p, "hw_rx_csum_inner_ok", ETH_GSTRING_LEN); 373 p += ETH_GSTRING_LEN; 374 strncpy(p, "hw_rx_csum_err", ETH_GSTRING_LEN); 375 p += ETH_GSTRING_LEN; 376 strncpy(p, "hw_tx_csum", ETH_GSTRING_LEN); 377 p += ETH_GSTRING_LEN; 378 strncpy(p, "hw_tx_inner_csum", ETH_GSTRING_LEN); 379 p += ETH_GSTRING_LEN; 380 strncpy(p, "tx_gather", ETH_GSTRING_LEN); 381 p += ETH_GSTRING_LEN; 382 strncpy(p, "tx_lso", ETH_GSTRING_LEN); 383 p += ETH_GSTRING_LEN; 384 for (i = 0; i < nn->dp.num_tx_rings; i++) { 385 sprintf(p, "txq_%u_pkts", i); 386 p += ETH_GSTRING_LEN; 387 sprintf(p, "txq_%u_bytes", i); 388 p += ETH_GSTRING_LEN; 389 } 390 for (i = 0; i < nn->dp.num_rx_rings; i++) { 391 sprintf(p, "rxq_%u_pkts", i); 392 p += ETH_GSTRING_LEN; 393 sprintf(p, "rxq_%u_bytes", i); 394 p += ETH_GSTRING_LEN; 395 } 396 break; 397 } 398 } 399 400 static void nfp_net_get_stats(struct net_device *netdev, 401 struct ethtool_stats *stats, u64 *data) 402 { 403 u64 gathered_stats[NN_ET_RVEC_GATHER_STATS] = {}; 404 struct nfp_net *nn = netdev_priv(netdev); 405 struct rtnl_link_stats64 *netdev_stats; 406 struct rtnl_link_stats64 temp = {}; 407 u64 tmp[NN_ET_RVEC_GATHER_STATS]; 408 u8 __iomem *io_p; 409 int i, j, k; 410 u8 *p; 411 412 netdev_stats = dev_get_stats(netdev, &temp); 413 414 for (i = 0; i < NN_ET_GLOBAL_STATS_LEN; i++) { 415 switch (nfp_net_et_stats[i].type) { 416 case NETDEV_ET_STATS: 417 p = (char *)netdev_stats + nfp_net_et_stats[i].off; 418 data[i] = nfp_net_et_stats[i].sz == sizeof(u64) ? 419 *(u64 *)p : *(u32 *)p; 420 break; 421 422 case NFP_NET_DEV_ET_STATS: 423 io_p = nn->dp.ctrl_bar + nfp_net_et_stats[i].off; 424 data[i] = readq(io_p); 425 break; 426 } 427 } 428 for (j = 0; j < nn->dp.num_r_vecs; j++) { 429 unsigned int start; 430 431 do { 432 start = u64_stats_fetch_begin(&nn->r_vecs[j].rx_sync); 433 data[i++] = nn->r_vecs[j].rx_pkts; 434 tmp[0] = nn->r_vecs[j].hw_csum_rx_ok; 435 tmp[1] = nn->r_vecs[j].hw_csum_rx_inner_ok; 436 tmp[2] = nn->r_vecs[j].hw_csum_rx_error; 437 } while (u64_stats_fetch_retry(&nn->r_vecs[j].rx_sync, start)); 438 439 do { 440 start = u64_stats_fetch_begin(&nn->r_vecs[j].tx_sync); 441 data[i++] = nn->r_vecs[j].tx_pkts; 442 data[i++] = nn->r_vecs[j].tx_busy; 443 tmp[3] = nn->r_vecs[j].hw_csum_tx; 444 tmp[4] = nn->r_vecs[j].hw_csum_tx_inner; 445 tmp[5] = nn->r_vecs[j].tx_gather; 446 tmp[6] = nn->r_vecs[j].tx_lso; 447 } while (u64_stats_fetch_retry(&nn->r_vecs[j].tx_sync, start)); 448 449 for (k = 0; k < NN_ET_RVEC_GATHER_STATS; k++) 450 gathered_stats[k] += tmp[k]; 451 } 452 for (j = 0; j < NN_ET_RVEC_GATHER_STATS; j++) 453 data[i++] = gathered_stats[j]; 454 for (j = 0; j < nn->dp.num_tx_rings; j++) { 455 io_p = nn->dp.ctrl_bar + NFP_NET_CFG_TXR_STATS(j); 456 data[i++] = readq(io_p); 457 io_p = nn->dp.ctrl_bar + NFP_NET_CFG_TXR_STATS(j) + 8; 458 data[i++] = readq(io_p); 459 } 460 for (j = 0; j < nn->dp.num_rx_rings; j++) { 461 io_p = nn->dp.ctrl_bar + NFP_NET_CFG_RXR_STATS(j); 462 data[i++] = readq(io_p); 463 io_p = nn->dp.ctrl_bar + NFP_NET_CFG_RXR_STATS(j) + 8; 464 data[i++] = readq(io_p); 465 } 466 } 467 468 static int nfp_net_get_sset_count(struct net_device *netdev, int sset) 469 { 470 struct nfp_net *nn = netdev_priv(netdev); 471 472 switch (sset) { 473 case ETH_SS_STATS: 474 return NN_ET_STATS_LEN; 475 default: 476 return -EOPNOTSUPP; 477 } 478 } 479 480 /* RX network flow classification (RSS, filters, etc) 481 */ 482 static u32 ethtool_flow_to_nfp_flag(u32 flow_type) 483 { 484 static const u32 xlate_ethtool_to_nfp[IPV6_FLOW + 1] = { 485 [TCP_V4_FLOW] = NFP_NET_CFG_RSS_IPV4_TCP, 486 [TCP_V6_FLOW] = NFP_NET_CFG_RSS_IPV6_TCP, 487 [UDP_V4_FLOW] = NFP_NET_CFG_RSS_IPV4_UDP, 488 [UDP_V6_FLOW] = NFP_NET_CFG_RSS_IPV6_UDP, 489 [IPV4_FLOW] = NFP_NET_CFG_RSS_IPV4, 490 [IPV6_FLOW] = NFP_NET_CFG_RSS_IPV6, 491 }; 492 493 if (flow_type >= ARRAY_SIZE(xlate_ethtool_to_nfp)) 494 return 0; 495 496 return xlate_ethtool_to_nfp[flow_type]; 497 } 498 499 static int nfp_net_get_rss_hash_opts(struct nfp_net *nn, 500 struct ethtool_rxnfc *cmd) 501 { 502 u32 nfp_rss_flag; 503 504 cmd->data = 0; 505 506 if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)) 507 return -EOPNOTSUPP; 508 509 nfp_rss_flag = ethtool_flow_to_nfp_flag(cmd->flow_type); 510 if (!nfp_rss_flag) 511 return -EINVAL; 512 513 cmd->data |= RXH_IP_SRC | RXH_IP_DST; 514 if (nn->rss_cfg & nfp_rss_flag) 515 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 516 517 return 0; 518 } 519 520 static int nfp_net_get_rxnfc(struct net_device *netdev, 521 struct ethtool_rxnfc *cmd, u32 *rule_locs) 522 { 523 struct nfp_net *nn = netdev_priv(netdev); 524 525 switch (cmd->cmd) { 526 case ETHTOOL_GRXRINGS: 527 cmd->data = nn->dp.num_rx_rings; 528 return 0; 529 case ETHTOOL_GRXFH: 530 return nfp_net_get_rss_hash_opts(nn, cmd); 531 default: 532 return -EOPNOTSUPP; 533 } 534 } 535 536 static int nfp_net_set_rss_hash_opt(struct nfp_net *nn, 537 struct ethtool_rxnfc *nfc) 538 { 539 u32 new_rss_cfg = nn->rss_cfg; 540 u32 nfp_rss_flag; 541 int err; 542 543 if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)) 544 return -EOPNOTSUPP; 545 546 /* RSS only supports IP SA/DA and L4 src/dst ports */ 547 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | 548 RXH_L4_B_0_1 | RXH_L4_B_2_3)) 549 return -EINVAL; 550 551 /* We need at least the IP SA/DA fields for hashing */ 552 if (!(nfc->data & RXH_IP_SRC) || 553 !(nfc->data & RXH_IP_DST)) 554 return -EINVAL; 555 556 nfp_rss_flag = ethtool_flow_to_nfp_flag(nfc->flow_type); 557 if (!nfp_rss_flag) 558 return -EINVAL; 559 560 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 561 case 0: 562 new_rss_cfg &= ~nfp_rss_flag; 563 break; 564 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 565 new_rss_cfg |= nfp_rss_flag; 566 break; 567 default: 568 return -EINVAL; 569 } 570 571 new_rss_cfg |= FIELD_PREP(NFP_NET_CFG_RSS_HFUNC, nn->rss_hfunc); 572 new_rss_cfg |= NFP_NET_CFG_RSS_MASK; 573 574 if (new_rss_cfg == nn->rss_cfg) 575 return 0; 576 577 writel(new_rss_cfg, nn->dp.ctrl_bar + NFP_NET_CFG_RSS_CTRL); 578 err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_RSS); 579 if (err) 580 return err; 581 582 nn->rss_cfg = new_rss_cfg; 583 584 nn_dbg(nn, "Changed RSS config to 0x%x\n", nn->rss_cfg); 585 return 0; 586 } 587 588 static int nfp_net_set_rxnfc(struct net_device *netdev, 589 struct ethtool_rxnfc *cmd) 590 { 591 struct nfp_net *nn = netdev_priv(netdev); 592 593 switch (cmd->cmd) { 594 case ETHTOOL_SRXFH: 595 return nfp_net_set_rss_hash_opt(nn, cmd); 596 default: 597 return -EOPNOTSUPP; 598 } 599 } 600 601 static u32 nfp_net_get_rxfh_indir_size(struct net_device *netdev) 602 { 603 struct nfp_net *nn = netdev_priv(netdev); 604 605 if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)) 606 return 0; 607 608 return ARRAY_SIZE(nn->rss_itbl); 609 } 610 611 static u32 nfp_net_get_rxfh_key_size(struct net_device *netdev) 612 { 613 struct nfp_net *nn = netdev_priv(netdev); 614 615 if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)) 616 return -EOPNOTSUPP; 617 618 return nfp_net_rss_key_sz(nn); 619 } 620 621 static int nfp_net_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 622 u8 *hfunc) 623 { 624 struct nfp_net *nn = netdev_priv(netdev); 625 int i; 626 627 if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)) 628 return -EOPNOTSUPP; 629 630 if (indir) 631 for (i = 0; i < ARRAY_SIZE(nn->rss_itbl); i++) 632 indir[i] = nn->rss_itbl[i]; 633 if (key) 634 memcpy(key, nn->rss_key, nfp_net_rss_key_sz(nn)); 635 if (hfunc) { 636 *hfunc = nn->rss_hfunc; 637 if (*hfunc >= 1 << ETH_RSS_HASH_FUNCS_COUNT) 638 *hfunc = ETH_RSS_HASH_UNKNOWN; 639 } 640 641 return 0; 642 } 643 644 static int nfp_net_set_rxfh(struct net_device *netdev, 645 const u32 *indir, const u8 *key, 646 const u8 hfunc) 647 { 648 struct nfp_net *nn = netdev_priv(netdev); 649 int i; 650 651 if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY) || 652 !(hfunc == ETH_RSS_HASH_NO_CHANGE || hfunc == nn->rss_hfunc)) 653 return -EOPNOTSUPP; 654 655 if (!key && !indir) 656 return 0; 657 658 if (key) { 659 memcpy(nn->rss_key, key, nfp_net_rss_key_sz(nn)); 660 nfp_net_rss_write_key(nn); 661 } 662 if (indir) { 663 for (i = 0; i < ARRAY_SIZE(nn->rss_itbl); i++) 664 nn->rss_itbl[i] = indir[i]; 665 666 nfp_net_rss_write_itbl(nn); 667 } 668 669 return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_RSS); 670 } 671 672 /* Dump BAR registers 673 */ 674 static int nfp_net_get_regs_len(struct net_device *netdev) 675 { 676 return NFP_NET_CFG_BAR_SZ; 677 } 678 679 static void nfp_net_get_regs(struct net_device *netdev, 680 struct ethtool_regs *regs, void *p) 681 { 682 struct nfp_net *nn = netdev_priv(netdev); 683 u32 *regs_buf = p; 684 int i; 685 686 regs->version = nn_readl(nn, NFP_NET_CFG_VERSION); 687 688 for (i = 0; i < NFP_NET_CFG_BAR_SZ / sizeof(u32); i++) 689 regs_buf[i] = readl(nn->dp.ctrl_bar + (i * sizeof(u32))); 690 } 691 692 static int nfp_net_get_coalesce(struct net_device *netdev, 693 struct ethtool_coalesce *ec) 694 { 695 struct nfp_net *nn = netdev_priv(netdev); 696 697 if (!(nn->cap & NFP_NET_CFG_CTRL_IRQMOD)) 698 return -EINVAL; 699 700 ec->rx_coalesce_usecs = nn->rx_coalesce_usecs; 701 ec->rx_max_coalesced_frames = nn->rx_coalesce_max_frames; 702 ec->tx_coalesce_usecs = nn->tx_coalesce_usecs; 703 ec->tx_max_coalesced_frames = nn->tx_coalesce_max_frames; 704 705 return 0; 706 } 707 708 /* Other debug dumps 709 */ 710 static int 711 nfp_dump_nsp_diag(struct nfp_net *nn, struct ethtool_dump *dump, void *buffer) 712 { 713 struct nfp_resource *res; 714 int ret; 715 716 if (!nn->app) 717 return -EOPNOTSUPP; 718 719 dump->version = 1; 720 dump->flag = NFP_DUMP_NSP_DIAG; 721 722 res = nfp_resource_acquire(nn->app->cpp, NFP_RESOURCE_NSP_DIAG); 723 if (IS_ERR(res)) 724 return PTR_ERR(res); 725 726 if (buffer) { 727 if (dump->len != nfp_resource_size(res)) { 728 ret = -EINVAL; 729 goto exit_release; 730 } 731 732 ret = nfp_cpp_read(nn->app->cpp, nfp_resource_cpp_id(res), 733 nfp_resource_address(res), 734 buffer, dump->len); 735 if (ret != dump->len) 736 ret = ret < 0 ? ret : -EIO; 737 else 738 ret = 0; 739 } else { 740 dump->len = nfp_resource_size(res); 741 ret = 0; 742 } 743 exit_release: 744 nfp_resource_release(res); 745 746 return ret; 747 } 748 749 static int nfp_net_set_dump(struct net_device *netdev, struct ethtool_dump *val) 750 { 751 struct nfp_net *nn = netdev_priv(netdev); 752 753 if (!nn->app) 754 return -EOPNOTSUPP; 755 756 if (val->flag != NFP_DUMP_NSP_DIAG) 757 return -EINVAL; 758 759 nn->ethtool_dump_flag = val->flag; 760 761 return 0; 762 } 763 764 static int 765 nfp_net_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) 766 { 767 return nfp_dump_nsp_diag(netdev_priv(netdev), dump, NULL); 768 } 769 770 static int 771 nfp_net_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, 772 void *buffer) 773 { 774 return nfp_dump_nsp_diag(netdev_priv(netdev), dump, buffer); 775 } 776 777 static int nfp_net_set_coalesce(struct net_device *netdev, 778 struct ethtool_coalesce *ec) 779 { 780 struct nfp_net *nn = netdev_priv(netdev); 781 unsigned int factor; 782 783 if (ec->rx_coalesce_usecs_irq || 784 ec->rx_max_coalesced_frames_irq || 785 ec->tx_coalesce_usecs_irq || 786 ec->tx_max_coalesced_frames_irq || 787 ec->stats_block_coalesce_usecs || 788 ec->use_adaptive_rx_coalesce || 789 ec->use_adaptive_tx_coalesce || 790 ec->pkt_rate_low || 791 ec->rx_coalesce_usecs_low || 792 ec->rx_max_coalesced_frames_low || 793 ec->tx_coalesce_usecs_low || 794 ec->tx_max_coalesced_frames_low || 795 ec->pkt_rate_high || 796 ec->rx_coalesce_usecs_high || 797 ec->rx_max_coalesced_frames_high || 798 ec->tx_coalesce_usecs_high || 799 ec->tx_max_coalesced_frames_high || 800 ec->rate_sample_interval) 801 return -EOPNOTSUPP; 802 803 /* Compute factor used to convert coalesce '_usecs' parameters to 804 * ME timestamp ticks. There are 16 ME clock cycles for each timestamp 805 * count. 806 */ 807 factor = nn->me_freq_mhz / 16; 808 809 /* Each pair of (usecs, max_frames) fields specifies that interrupts 810 * should be coalesced until 811 * (usecs > 0 && time_since_first_completion >= usecs) || 812 * (max_frames > 0 && completed_frames >= max_frames) 813 * 814 * It is illegal to set both usecs and max_frames to zero as this would 815 * cause interrupts to never be generated. To disable coalescing, set 816 * usecs = 0 and max_frames = 1. 817 * 818 * Some implementations ignore the value of max_frames and use the 819 * condition time_since_first_completion >= usecs 820 */ 821 822 if (!(nn->cap & NFP_NET_CFG_CTRL_IRQMOD)) 823 return -EINVAL; 824 825 /* ensure valid configuration */ 826 if (!ec->rx_coalesce_usecs && !ec->rx_max_coalesced_frames) 827 return -EINVAL; 828 829 if (!ec->tx_coalesce_usecs && !ec->tx_max_coalesced_frames) 830 return -EINVAL; 831 832 if (ec->rx_coalesce_usecs * factor >= ((1 << 16) - 1)) 833 return -EINVAL; 834 835 if (ec->tx_coalesce_usecs * factor >= ((1 << 16) - 1)) 836 return -EINVAL; 837 838 if (ec->rx_max_coalesced_frames >= ((1 << 16) - 1)) 839 return -EINVAL; 840 841 if (ec->tx_max_coalesced_frames >= ((1 << 16) - 1)) 842 return -EINVAL; 843 844 /* configuration is valid */ 845 nn->rx_coalesce_usecs = ec->rx_coalesce_usecs; 846 nn->rx_coalesce_max_frames = ec->rx_max_coalesced_frames; 847 nn->tx_coalesce_usecs = ec->tx_coalesce_usecs; 848 nn->tx_coalesce_max_frames = ec->tx_max_coalesced_frames; 849 850 /* write configuration to device */ 851 nfp_net_coalesce_write_cfg(nn); 852 return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); 853 } 854 855 static void nfp_net_get_channels(struct net_device *netdev, 856 struct ethtool_channels *channel) 857 { 858 struct nfp_net *nn = netdev_priv(netdev); 859 unsigned int num_tx_rings; 860 861 num_tx_rings = nn->dp.num_tx_rings; 862 if (nn->dp.xdp_prog) 863 num_tx_rings -= nn->dp.num_rx_rings; 864 865 channel->max_rx = min(nn->max_rx_rings, nn->max_r_vecs); 866 channel->max_tx = min(nn->max_tx_rings, nn->max_r_vecs); 867 channel->max_combined = min(channel->max_rx, channel->max_tx); 868 channel->max_other = NFP_NET_NON_Q_VECTORS; 869 channel->combined_count = min(nn->dp.num_rx_rings, num_tx_rings); 870 channel->rx_count = nn->dp.num_rx_rings - channel->combined_count; 871 channel->tx_count = num_tx_rings - channel->combined_count; 872 channel->other_count = NFP_NET_NON_Q_VECTORS; 873 } 874 875 static int nfp_net_set_num_rings(struct nfp_net *nn, unsigned int total_rx, 876 unsigned int total_tx) 877 { 878 struct nfp_net_dp *dp; 879 880 dp = nfp_net_clone_dp(nn); 881 if (!dp) 882 return -ENOMEM; 883 884 dp->num_rx_rings = total_rx; 885 dp->num_tx_rings = total_tx; 886 /* nfp_net_check_config() will catch num_tx_rings > nn->max_tx_rings */ 887 if (dp->xdp_prog) 888 dp->num_tx_rings += total_rx; 889 890 return nfp_net_ring_reconfig(nn, dp, NULL); 891 } 892 893 static int nfp_net_set_channels(struct net_device *netdev, 894 struct ethtool_channels *channel) 895 { 896 struct nfp_net *nn = netdev_priv(netdev); 897 unsigned int total_rx, total_tx; 898 899 /* Reject unsupported */ 900 if (!channel->combined_count || 901 channel->other_count != NFP_NET_NON_Q_VECTORS || 902 (channel->rx_count && channel->tx_count)) 903 return -EINVAL; 904 905 total_rx = channel->combined_count + channel->rx_count; 906 total_tx = channel->combined_count + channel->tx_count; 907 908 if (total_rx > min(nn->max_rx_rings, nn->max_r_vecs) || 909 total_tx > min(nn->max_tx_rings, nn->max_r_vecs)) 910 return -EINVAL; 911 912 return nfp_net_set_num_rings(nn, total_rx, total_tx); 913 } 914 915 static const struct ethtool_ops nfp_net_ethtool_ops = { 916 .get_drvinfo = nfp_net_get_drvinfo, 917 .get_link = ethtool_op_get_link, 918 .get_ringparam = nfp_net_get_ringparam, 919 .set_ringparam = nfp_net_set_ringparam, 920 .get_strings = nfp_net_get_strings, 921 .get_ethtool_stats = nfp_net_get_stats, 922 .get_sset_count = nfp_net_get_sset_count, 923 .get_rxnfc = nfp_net_get_rxnfc, 924 .set_rxnfc = nfp_net_set_rxnfc, 925 .get_rxfh_indir_size = nfp_net_get_rxfh_indir_size, 926 .get_rxfh_key_size = nfp_net_get_rxfh_key_size, 927 .get_rxfh = nfp_net_get_rxfh, 928 .set_rxfh = nfp_net_set_rxfh, 929 .get_regs_len = nfp_net_get_regs_len, 930 .get_regs = nfp_net_get_regs, 931 .set_dump = nfp_net_set_dump, 932 .get_dump_flag = nfp_net_get_dump_flag, 933 .get_dump_data = nfp_net_get_dump_data, 934 .get_coalesce = nfp_net_get_coalesce, 935 .set_coalesce = nfp_net_set_coalesce, 936 .get_channels = nfp_net_get_channels, 937 .set_channels = nfp_net_set_channels, 938 .get_link_ksettings = nfp_net_get_link_ksettings, 939 .set_link_ksettings = nfp_net_set_link_ksettings, 940 }; 941 942 void nfp_net_set_ethtool_ops(struct net_device *netdev) 943 { 944 netdev->ethtool_ops = &nfp_net_ethtool_ops; 945 } 946