1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 4 #include <linux/ethtool.h> 5 #include <linux/netdevice.h> 6 #include <linux/pci.h> 7 8 #include "fbnic.h" 9 #include "fbnic_netdev.h" 10 #include "fbnic_tlv.h" 11 12 struct fbnic_stat { 13 u8 string[ETH_GSTRING_LEN]; 14 unsigned int size; 15 unsigned int offset; 16 }; 17 18 #define FBNIC_STAT_FIELDS(type, name, stat) { \ 19 .string = name, \ 20 .size = sizeof_field(struct type, stat), \ 21 .offset = offsetof(struct type, stat), \ 22 } 23 24 /* Hardware statistics not captured in rtnl_link_stats */ 25 #define FBNIC_HW_STAT(name, stat) \ 26 FBNIC_STAT_FIELDS(fbnic_hw_stats, name, stat) 27 28 static const struct fbnic_stat fbnic_gstrings_hw_stats[] = { 29 /* RPC */ 30 FBNIC_HW_STAT("rpc_unkn_etype", rpc.unkn_etype), 31 FBNIC_HW_STAT("rpc_unkn_ext_hdr", rpc.unkn_ext_hdr), 32 FBNIC_HW_STAT("rpc_ipv4_frag", rpc.ipv4_frag), 33 FBNIC_HW_STAT("rpc_ipv6_frag", rpc.ipv6_frag), 34 FBNIC_HW_STAT("rpc_ipv4_esp", rpc.ipv4_esp), 35 FBNIC_HW_STAT("rpc_ipv6_esp", rpc.ipv6_esp), 36 FBNIC_HW_STAT("rpc_tcp_opt_err", rpc.tcp_opt_err), 37 FBNIC_HW_STAT("rpc_out_of_hdr_err", rpc.out_of_hdr_err), 38 }; 39 40 #define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats) 41 #define FBNIC_HW_STATS_LEN FBNIC_HW_FIXED_STATS_LEN 42 43 static void 44 fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 45 { 46 struct fbnic_net *fbn = netdev_priv(netdev); 47 struct fbnic_dev *fbd = fbn->fbd; 48 49 fbnic_get_fw_ver_commit_str(fbd, drvinfo->fw_version, 50 sizeof(drvinfo->fw_version)); 51 } 52 53 static int fbnic_get_regs_len(struct net_device *netdev) 54 { 55 struct fbnic_net *fbn = netdev_priv(netdev); 56 57 return fbnic_csr_regs_len(fbn->fbd) * sizeof(u32); 58 } 59 60 static void fbnic_get_regs(struct net_device *netdev, 61 struct ethtool_regs *regs, void *data) 62 { 63 struct fbnic_net *fbn = netdev_priv(netdev); 64 65 fbnic_csr_get_regs(fbn->fbd, data, ®s->version); 66 } 67 68 static struct fbnic_net *fbnic_clone_create(struct fbnic_net *orig) 69 { 70 struct fbnic_net *clone; 71 72 clone = kmemdup(orig, sizeof(*orig), GFP_KERNEL); 73 if (!clone) 74 return NULL; 75 76 memset(clone->tx, 0, sizeof(clone->tx)); 77 memset(clone->rx, 0, sizeof(clone->rx)); 78 memset(clone->napi, 0, sizeof(clone->napi)); 79 return clone; 80 } 81 82 static void fbnic_clone_swap_cfg(struct fbnic_net *orig, 83 struct fbnic_net *clone) 84 { 85 swap(clone->rcq_size, orig->rcq_size); 86 swap(clone->hpq_size, orig->hpq_size); 87 swap(clone->ppq_size, orig->ppq_size); 88 swap(clone->txq_size, orig->txq_size); 89 swap(clone->num_rx_queues, orig->num_rx_queues); 90 swap(clone->num_tx_queues, orig->num_tx_queues); 91 swap(clone->num_napi, orig->num_napi); 92 } 93 94 static void fbnic_aggregate_vector_counters(struct fbnic_net *fbn, 95 struct fbnic_napi_vector *nv) 96 { 97 int i, j; 98 99 for (i = 0; i < nv->txt_count; i++) { 100 fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].sub0); 101 fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].sub1); 102 fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].cmpl); 103 } 104 105 for (j = 0; j < nv->rxt_count; j++, i++) { 106 fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].sub0); 107 fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].sub1); 108 fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].cmpl); 109 } 110 } 111 112 static void fbnic_clone_swap(struct fbnic_net *orig, 113 struct fbnic_net *clone) 114 { 115 struct fbnic_dev *fbd = orig->fbd; 116 unsigned int i; 117 118 for (i = 0; i < max(clone->num_napi, orig->num_napi); i++) 119 fbnic_synchronize_irq(fbd, FBNIC_NON_NAPI_VECTORS + i); 120 for (i = 0; i < orig->num_napi; i++) 121 fbnic_aggregate_vector_counters(orig, orig->napi[i]); 122 123 fbnic_clone_swap_cfg(orig, clone); 124 125 for (i = 0; i < ARRAY_SIZE(orig->napi); i++) 126 swap(clone->napi[i], orig->napi[i]); 127 for (i = 0; i < ARRAY_SIZE(orig->tx); i++) 128 swap(clone->tx[i], orig->tx[i]); 129 for (i = 0; i < ARRAY_SIZE(orig->rx); i++) 130 swap(clone->rx[i], orig->rx[i]); 131 } 132 133 static void fbnic_clone_free(struct fbnic_net *clone) 134 { 135 kfree(clone); 136 } 137 138 static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data) 139 { 140 int i; 141 142 switch (sset) { 143 case ETH_SS_STATS: 144 for (i = 0; i < FBNIC_HW_STATS_LEN; i++) 145 ethtool_puts(&data, fbnic_gstrings_hw_stats[i].string); 146 break; 147 } 148 } 149 150 static void fbnic_get_ethtool_stats(struct net_device *dev, 151 struct ethtool_stats *stats, u64 *data) 152 { 153 struct fbnic_net *fbn = netdev_priv(dev); 154 const struct fbnic_stat *stat; 155 int i; 156 157 fbnic_get_hw_stats(fbn->fbd); 158 159 for (i = 0; i < FBNIC_HW_STATS_LEN; i++) { 160 stat = &fbnic_gstrings_hw_stats[i]; 161 data[i] = *(u64 *)((u8 *)&fbn->fbd->hw_stats + stat->offset); 162 } 163 } 164 165 static int fbnic_get_sset_count(struct net_device *dev, int sset) 166 { 167 switch (sset) { 168 case ETH_SS_STATS: 169 return FBNIC_HW_STATS_LEN; 170 default: 171 return -EOPNOTSUPP; 172 } 173 } 174 175 static int fbnic_get_rss_hash_idx(u32 flow_type) 176 { 177 switch (flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) { 178 case TCP_V4_FLOW: 179 return FBNIC_TCP4_HASH_OPT; 180 case TCP_V6_FLOW: 181 return FBNIC_TCP6_HASH_OPT; 182 case UDP_V4_FLOW: 183 return FBNIC_UDP4_HASH_OPT; 184 case UDP_V6_FLOW: 185 return FBNIC_UDP6_HASH_OPT; 186 case AH_V4_FLOW: 187 case ESP_V4_FLOW: 188 case AH_ESP_V4_FLOW: 189 case SCTP_V4_FLOW: 190 case IPV4_FLOW: 191 case IPV4_USER_FLOW: 192 return FBNIC_IPV4_HASH_OPT; 193 case AH_V6_FLOW: 194 case ESP_V6_FLOW: 195 case AH_ESP_V6_FLOW: 196 case SCTP_V6_FLOW: 197 case IPV6_FLOW: 198 case IPV6_USER_FLOW: 199 return FBNIC_IPV6_HASH_OPT; 200 case ETHER_FLOW: 201 return FBNIC_ETHER_HASH_OPT; 202 } 203 204 return -1; 205 } 206 207 static int 208 fbnic_get_rss_hash_opts(struct fbnic_net *fbn, struct ethtool_rxnfc *cmd) 209 { 210 int hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); 211 212 if (hash_opt_idx < 0) 213 return -EINVAL; 214 215 /* Report options from rss_en table in fbn */ 216 cmd->data = fbn->rss_flow_hash[hash_opt_idx]; 217 218 return 0; 219 } 220 221 static int fbnic_get_rxnfc(struct net_device *netdev, 222 struct ethtool_rxnfc *cmd, u32 *rule_locs) 223 { 224 struct fbnic_net *fbn = netdev_priv(netdev); 225 int ret = -EOPNOTSUPP; 226 227 switch (cmd->cmd) { 228 case ETHTOOL_GRXRINGS: 229 cmd->data = fbn->num_rx_queues; 230 ret = 0; 231 break; 232 case ETHTOOL_GRXFH: 233 ret = fbnic_get_rss_hash_opts(fbn, cmd); 234 break; 235 } 236 237 return ret; 238 } 239 240 #define FBNIC_L2_HASH_OPTIONS \ 241 (RXH_L2DA | RXH_DISCARD) 242 #define FBNIC_L3_HASH_OPTIONS \ 243 (FBNIC_L2_HASH_OPTIONS | RXH_IP_SRC | RXH_IP_DST) 244 #define FBNIC_L4_HASH_OPTIONS \ 245 (FBNIC_L3_HASH_OPTIONS | RXH_L4_B_0_1 | RXH_L4_B_2_3) 246 247 static int 248 fbnic_set_rss_hash_opts(struct fbnic_net *fbn, const struct ethtool_rxnfc *cmd) 249 { 250 int hash_opt_idx; 251 252 /* Verify the type requested is correct */ 253 hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); 254 if (hash_opt_idx < 0) 255 return -EINVAL; 256 257 /* Verify the fields asked for can actually be assigned based on type */ 258 if (cmd->data & ~FBNIC_L4_HASH_OPTIONS || 259 (hash_opt_idx > FBNIC_L4_HASH_OPT && 260 cmd->data & ~FBNIC_L3_HASH_OPTIONS) || 261 (hash_opt_idx > FBNIC_IP_HASH_OPT && 262 cmd->data & ~FBNIC_L2_HASH_OPTIONS)) 263 return -EINVAL; 264 265 fbn->rss_flow_hash[hash_opt_idx] = cmd->data; 266 267 if (netif_running(fbn->netdev)) { 268 fbnic_rss_reinit(fbn->fbd, fbn); 269 fbnic_write_rules(fbn->fbd); 270 } 271 272 return 0; 273 } 274 275 static int fbnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) 276 { 277 struct fbnic_net *fbn = netdev_priv(netdev); 278 int ret = -EOPNOTSUPP; 279 280 switch (cmd->cmd) { 281 case ETHTOOL_SRXFH: 282 ret = fbnic_set_rss_hash_opts(fbn, cmd); 283 break; 284 } 285 286 return ret; 287 } 288 289 static u32 fbnic_get_rxfh_key_size(struct net_device *netdev) 290 { 291 return FBNIC_RPC_RSS_KEY_BYTE_LEN; 292 } 293 294 static u32 fbnic_get_rxfh_indir_size(struct net_device *netdev) 295 { 296 return FBNIC_RPC_RSS_TBL_SIZE; 297 } 298 299 static int 300 fbnic_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh) 301 { 302 struct fbnic_net *fbn = netdev_priv(netdev); 303 unsigned int i; 304 305 rxfh->hfunc = ETH_RSS_HASH_TOP; 306 307 if (rxfh->key) { 308 for (i = 0; i < FBNIC_RPC_RSS_KEY_BYTE_LEN; i++) { 309 u32 rss_key = fbn->rss_key[i / 4] << ((i % 4) * 8); 310 311 rxfh->key[i] = rss_key >> 24; 312 } 313 } 314 315 if (rxfh->indir) { 316 for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++) 317 rxfh->indir[i] = fbn->indir_tbl[0][i]; 318 } 319 320 return 0; 321 } 322 323 static unsigned int 324 fbnic_set_indir(struct fbnic_net *fbn, unsigned int idx, const u32 *indir) 325 { 326 unsigned int i, changes = 0; 327 328 for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++) { 329 if (fbn->indir_tbl[idx][i] == indir[i]) 330 continue; 331 332 fbn->indir_tbl[idx][i] = indir[i]; 333 changes++; 334 } 335 336 return changes; 337 } 338 339 static int 340 fbnic_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh, 341 struct netlink_ext_ack *extack) 342 { 343 struct fbnic_net *fbn = netdev_priv(netdev); 344 unsigned int i, changes = 0; 345 346 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && 347 rxfh->hfunc != ETH_RSS_HASH_TOP) 348 return -EINVAL; 349 350 if (rxfh->key) { 351 u32 rss_key = 0; 352 353 for (i = FBNIC_RPC_RSS_KEY_BYTE_LEN; i--;) { 354 rss_key >>= 8; 355 rss_key |= (u32)(rxfh->key[i]) << 24; 356 357 if (i % 4) 358 continue; 359 360 if (fbn->rss_key[i / 4] == rss_key) 361 continue; 362 363 fbn->rss_key[i / 4] = rss_key; 364 changes++; 365 } 366 } 367 368 if (rxfh->indir) 369 changes += fbnic_set_indir(fbn, 0, rxfh->indir); 370 371 if (changes && netif_running(netdev)) 372 fbnic_rss_reinit_hw(fbn->fbd, fbn); 373 374 return 0; 375 } 376 377 static void fbnic_get_channels(struct net_device *netdev, 378 struct ethtool_channels *ch) 379 { 380 struct fbnic_net *fbn = netdev_priv(netdev); 381 struct fbnic_dev *fbd = fbn->fbd; 382 383 ch->max_rx = fbd->max_num_queues; 384 ch->max_tx = fbd->max_num_queues; 385 ch->max_combined = min(ch->max_rx, ch->max_tx); 386 ch->max_other = FBNIC_NON_NAPI_VECTORS; 387 388 if (fbn->num_rx_queues > fbn->num_napi || 389 fbn->num_tx_queues > fbn->num_napi) 390 ch->combined_count = min(fbn->num_rx_queues, 391 fbn->num_tx_queues); 392 else 393 ch->combined_count = 394 fbn->num_rx_queues + fbn->num_tx_queues - fbn->num_napi; 395 ch->rx_count = fbn->num_rx_queues - ch->combined_count; 396 ch->tx_count = fbn->num_tx_queues - ch->combined_count; 397 ch->other_count = FBNIC_NON_NAPI_VECTORS; 398 } 399 400 static void fbnic_set_queues(struct fbnic_net *fbn, struct ethtool_channels *ch, 401 unsigned int max_napis) 402 { 403 fbn->num_rx_queues = ch->rx_count + ch->combined_count; 404 fbn->num_tx_queues = ch->tx_count + ch->combined_count; 405 fbn->num_napi = min(ch->rx_count + ch->tx_count + ch->combined_count, 406 max_napis); 407 } 408 409 static int fbnic_set_channels(struct net_device *netdev, 410 struct ethtool_channels *ch) 411 { 412 struct fbnic_net *fbn = netdev_priv(netdev); 413 unsigned int max_napis, standalone; 414 struct fbnic_dev *fbd = fbn->fbd; 415 struct fbnic_net *clone; 416 int err; 417 418 max_napis = fbd->num_irqs - FBNIC_NON_NAPI_VECTORS; 419 standalone = ch->rx_count + ch->tx_count; 420 421 /* Limits for standalone queues: 422 * - each queue has it's own NAPI (num_napi >= rx + tx + combined) 423 * - combining queues (combined not 0, rx or tx must be 0) 424 */ 425 if ((ch->rx_count && ch->tx_count && ch->combined_count) || 426 (standalone && standalone + ch->combined_count > max_napis) || 427 ch->rx_count + ch->combined_count > fbd->max_num_queues || 428 ch->tx_count + ch->combined_count > fbd->max_num_queues || 429 ch->other_count != FBNIC_NON_NAPI_VECTORS) 430 return -EINVAL; 431 432 if (!netif_running(netdev)) { 433 fbnic_set_queues(fbn, ch, max_napis); 434 fbnic_reset_indir_tbl(fbn); 435 return 0; 436 } 437 438 clone = fbnic_clone_create(fbn); 439 if (!clone) 440 return -ENOMEM; 441 442 fbnic_set_queues(clone, ch, max_napis); 443 444 err = fbnic_alloc_napi_vectors(clone); 445 if (err) 446 goto err_free_clone; 447 448 err = fbnic_alloc_resources(clone); 449 if (err) 450 goto err_free_napis; 451 452 fbnic_down_noidle(fbn); 453 err = fbnic_wait_all_queues_idle(fbn->fbd, true); 454 if (err) 455 goto err_start_stack; 456 457 err = fbnic_set_netif_queues(clone); 458 if (err) 459 goto err_start_stack; 460 461 /* Nothing can fail past this point */ 462 fbnic_flush(fbn); 463 464 fbnic_clone_swap(fbn, clone); 465 466 /* Reset RSS indirection table */ 467 fbnic_reset_indir_tbl(fbn); 468 469 fbnic_up(fbn); 470 471 fbnic_free_resources(clone); 472 fbnic_free_napi_vectors(clone); 473 fbnic_clone_free(clone); 474 475 return 0; 476 477 err_start_stack: 478 fbnic_flush(fbn); 479 fbnic_up(fbn); 480 fbnic_free_resources(clone); 481 err_free_napis: 482 fbnic_free_napi_vectors(clone); 483 err_free_clone: 484 fbnic_clone_free(clone); 485 return err; 486 } 487 488 static int 489 fbnic_get_ts_info(struct net_device *netdev, 490 struct kernel_ethtool_ts_info *tsinfo) 491 { 492 struct fbnic_net *fbn = netdev_priv(netdev); 493 494 tsinfo->phc_index = ptp_clock_index(fbn->fbd->ptp); 495 496 tsinfo->so_timestamping = 497 SOF_TIMESTAMPING_TX_SOFTWARE | 498 SOF_TIMESTAMPING_TX_HARDWARE | 499 SOF_TIMESTAMPING_RX_HARDWARE | 500 SOF_TIMESTAMPING_RAW_HARDWARE; 501 502 tsinfo->tx_types = 503 BIT(HWTSTAMP_TX_OFF) | 504 BIT(HWTSTAMP_TX_ON); 505 506 tsinfo->rx_filters = 507 BIT(HWTSTAMP_FILTER_NONE) | 508 BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | 509 BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | 510 BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | 511 BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | 512 BIT(HWTSTAMP_FILTER_ALL); 513 514 return 0; 515 } 516 517 static void fbnic_get_ts_stats(struct net_device *netdev, 518 struct ethtool_ts_stats *ts_stats) 519 { 520 struct fbnic_net *fbn = netdev_priv(netdev); 521 u64 ts_packets, ts_lost; 522 struct fbnic_ring *ring; 523 unsigned int start; 524 int i; 525 526 ts_stats->pkts = fbn->tx_stats.ts_packets; 527 ts_stats->lost = fbn->tx_stats.ts_lost; 528 for (i = 0; i < fbn->num_tx_queues; i++) { 529 ring = fbn->tx[i]; 530 do { 531 start = u64_stats_fetch_begin(&ring->stats.syncp); 532 ts_packets = ring->stats.ts_packets; 533 ts_lost = ring->stats.ts_lost; 534 } while (u64_stats_fetch_retry(&ring->stats.syncp, start)); 535 ts_stats->pkts += ts_packets; 536 ts_stats->lost += ts_lost; 537 } 538 } 539 540 static void fbnic_set_counter(u64 *stat, struct fbnic_stat_counter *counter) 541 { 542 if (counter->reported) 543 *stat = counter->value; 544 } 545 546 static void 547 fbnic_get_eth_mac_stats(struct net_device *netdev, 548 struct ethtool_eth_mac_stats *eth_mac_stats) 549 { 550 struct fbnic_net *fbn = netdev_priv(netdev); 551 struct fbnic_mac_stats *mac_stats; 552 struct fbnic_dev *fbd = fbn->fbd; 553 const struct fbnic_mac *mac; 554 555 mac_stats = &fbd->hw_stats.mac; 556 mac = fbd->mac; 557 558 mac->get_eth_mac_stats(fbd, false, &mac_stats->eth_mac); 559 560 fbnic_set_counter(ð_mac_stats->FramesTransmittedOK, 561 &mac_stats->eth_mac.FramesTransmittedOK); 562 fbnic_set_counter(ð_mac_stats->FramesReceivedOK, 563 &mac_stats->eth_mac.FramesReceivedOK); 564 fbnic_set_counter(ð_mac_stats->FrameCheckSequenceErrors, 565 &mac_stats->eth_mac.FrameCheckSequenceErrors); 566 fbnic_set_counter(ð_mac_stats->AlignmentErrors, 567 &mac_stats->eth_mac.AlignmentErrors); 568 fbnic_set_counter(ð_mac_stats->OctetsTransmittedOK, 569 &mac_stats->eth_mac.OctetsTransmittedOK); 570 fbnic_set_counter(ð_mac_stats->FramesLostDueToIntMACXmitError, 571 &mac_stats->eth_mac.FramesLostDueToIntMACXmitError); 572 fbnic_set_counter(ð_mac_stats->OctetsReceivedOK, 573 &mac_stats->eth_mac.OctetsReceivedOK); 574 fbnic_set_counter(ð_mac_stats->FramesLostDueToIntMACRcvError, 575 &mac_stats->eth_mac.FramesLostDueToIntMACRcvError); 576 fbnic_set_counter(ð_mac_stats->MulticastFramesXmittedOK, 577 &mac_stats->eth_mac.MulticastFramesXmittedOK); 578 fbnic_set_counter(ð_mac_stats->BroadcastFramesXmittedOK, 579 &mac_stats->eth_mac.BroadcastFramesXmittedOK); 580 fbnic_set_counter(ð_mac_stats->MulticastFramesReceivedOK, 581 &mac_stats->eth_mac.MulticastFramesReceivedOK); 582 fbnic_set_counter(ð_mac_stats->BroadcastFramesReceivedOK, 583 &mac_stats->eth_mac.BroadcastFramesReceivedOK); 584 fbnic_set_counter(ð_mac_stats->FrameTooLongErrors, 585 &mac_stats->eth_mac.FrameTooLongErrors); 586 } 587 588 static const struct ethtool_ops fbnic_ethtool_ops = { 589 .get_drvinfo = fbnic_get_drvinfo, 590 .get_regs_len = fbnic_get_regs_len, 591 .get_regs = fbnic_get_regs, 592 .get_strings = fbnic_get_strings, 593 .get_ethtool_stats = fbnic_get_ethtool_stats, 594 .get_sset_count = fbnic_get_sset_count, 595 .get_rxnfc = fbnic_get_rxnfc, 596 .set_rxnfc = fbnic_set_rxnfc, 597 .get_rxfh_key_size = fbnic_get_rxfh_key_size, 598 .get_rxfh_indir_size = fbnic_get_rxfh_indir_size, 599 .get_rxfh = fbnic_get_rxfh, 600 .set_rxfh = fbnic_set_rxfh, 601 .get_channels = fbnic_get_channels, 602 .set_channels = fbnic_set_channels, 603 .get_ts_info = fbnic_get_ts_info, 604 .get_ts_stats = fbnic_get_ts_stats, 605 .get_eth_mac_stats = fbnic_get_eth_mac_stats, 606 }; 607 608 void fbnic_set_ethtool_ops(struct net_device *dev) 609 { 610 dev->ethtool_ops = &fbnic_ethtool_ops; 611 } 612