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