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
fbnic_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * drvinfo)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
fbnic_get_regs_len(struct net_device * netdev)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
fbnic_get_regs(struct net_device * netdev,struct ethtool_regs * regs,void * data)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
fbnic_clone_create(struct fbnic_net * orig)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
fbnic_clone_swap_cfg(struct fbnic_net * orig,struct fbnic_net * clone)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
fbnic_aggregate_vector_counters(struct fbnic_net * fbn,struct fbnic_napi_vector * nv)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
fbnic_clone_swap(struct fbnic_net * orig,struct fbnic_net * clone)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
fbnic_clone_free(struct fbnic_net * clone)133 static void fbnic_clone_free(struct fbnic_net *clone)
134 {
135 kfree(clone);
136 }
137
fbnic_get_strings(struct net_device * dev,u32 sset,u8 * data)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
fbnic_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)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
fbnic_get_sset_count(struct net_device * dev,int sset)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
fbnic_get_rss_hash_idx(u32 flow_type)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
fbnic_get_rss_hash_opts(struct fbnic_net * fbn,struct ethtool_rxnfc * cmd)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
fbnic_get_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * cmd,u32 * rule_locs)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
fbnic_set_rss_hash_opts(struct fbnic_net * fbn,const struct ethtool_rxnfc * cmd)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
fbnic_set_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * cmd)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
fbnic_get_rxfh_key_size(struct net_device * netdev)289 static u32 fbnic_get_rxfh_key_size(struct net_device *netdev)
290 {
291 return FBNIC_RPC_RSS_KEY_BYTE_LEN;
292 }
293
fbnic_get_rxfh_indir_size(struct net_device * netdev)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
fbnic_get_rxfh(struct net_device * netdev,struct ethtool_rxfh_param * rxfh)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
fbnic_set_indir(struct fbnic_net * fbn,unsigned int idx,const u32 * indir)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
fbnic_set_rxfh(struct net_device * netdev,struct ethtool_rxfh_param * rxfh,struct netlink_ext_ack * extack)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
fbnic_get_channels(struct net_device * netdev,struct ethtool_channels * ch)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
fbnic_set_queues(struct fbnic_net * fbn,struct ethtool_channels * ch,unsigned int max_napis)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
fbnic_set_channels(struct net_device * netdev,struct ethtool_channels * ch)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
fbnic_get_ts_info(struct net_device * netdev,struct kernel_ethtool_ts_info * tsinfo)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
fbnic_get_ts_stats(struct net_device * netdev,struct ethtool_ts_stats * ts_stats)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
fbnic_set_counter(u64 * stat,struct fbnic_stat_counter * counter)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
fbnic_get_eth_mac_stats(struct net_device * netdev,struct ethtool_eth_mac_stats * eth_mac_stats)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
fbnic_set_ethtool_ops(struct net_device * dev)608 void fbnic_set_ethtool_ops(struct net_device *dev)
609 {
610 dev->ethtool_ops = &fbnic_ethtool_ops;
611 }
612