1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
4 #include <linux/ethtool.h>
5 #include <linux/netdevice.h>
9 #include "fbnic_netdev.h"
10 #include "fbnic_tlv.h"
13 u8 string
[ETH_GSTRING_LEN
];
18 #define FBNIC_STAT_FIELDS(type, name, stat) { \
20 .size = sizeof_field(struct type, stat), \
21 .offset = offsetof(struct type, stat), \
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)
28 static const struct fbnic_stat fbnic_gstrings_hw_stats
[] = {
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
),
40 #define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats)
41 #define FBNIC_HW_STATS_LEN FBNIC_HW_FIXED_STATS_LEN
44 fbnic_get_ts_info(struct net_device
*netdev
,
45 struct kernel_ethtool_ts_info
*tsinfo
)
47 struct fbnic_net
*fbn
= netdev_priv(netdev
);
49 tsinfo
->phc_index
= ptp_clock_index(fbn
->fbd
->ptp
);
51 tsinfo
->so_timestamping
=
52 SOF_TIMESTAMPING_TX_SOFTWARE
|
53 SOF_TIMESTAMPING_TX_HARDWARE
|
54 SOF_TIMESTAMPING_RX_HARDWARE
|
55 SOF_TIMESTAMPING_RAW_HARDWARE
;
58 BIT(HWTSTAMP_TX_OFF
) |
62 BIT(HWTSTAMP_FILTER_NONE
) |
63 BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT
) |
64 BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT
) |
65 BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT
) |
66 BIT(HWTSTAMP_FILTER_PTP_V2_EVENT
) |
67 BIT(HWTSTAMP_FILTER_ALL
);
73 fbnic_get_drvinfo(struct net_device
*netdev
, struct ethtool_drvinfo
*drvinfo
)
75 struct fbnic_net
*fbn
= netdev_priv(netdev
);
76 struct fbnic_dev
*fbd
= fbn
->fbd
;
78 fbnic_get_fw_ver_commit_str(fbd
, drvinfo
->fw_version
,
79 sizeof(drvinfo
->fw_version
));
82 static void fbnic_set_counter(u64
*stat
, struct fbnic_stat_counter
*counter
)
84 if (counter
->reported
)
85 *stat
= counter
->value
;
88 static void fbnic_get_strings(struct net_device
*dev
, u32 sset
, u8
*data
)
94 for (i
= 0; i
< FBNIC_HW_STATS_LEN
; i
++)
95 ethtool_puts(&data
, fbnic_gstrings_hw_stats
[i
].string
);
100 static int fbnic_get_sset_count(struct net_device
*dev
, int sset
)
104 return FBNIC_HW_STATS_LEN
;
110 static void fbnic_get_ethtool_stats(struct net_device
*dev
,
111 struct ethtool_stats
*stats
, u64
*data
)
113 struct fbnic_net
*fbn
= netdev_priv(dev
);
114 const struct fbnic_stat
*stat
;
117 fbnic_get_hw_stats(fbn
->fbd
);
119 for (i
= 0; i
< FBNIC_HW_STATS_LEN
; i
++) {
120 stat
= &fbnic_gstrings_hw_stats
[i
];
121 data
[i
] = *(u64
*)((u8
*)&fbn
->fbd
->hw_stats
+ stat
->offset
);
126 fbnic_get_eth_mac_stats(struct net_device
*netdev
,
127 struct ethtool_eth_mac_stats
*eth_mac_stats
)
129 struct fbnic_net
*fbn
= netdev_priv(netdev
);
130 struct fbnic_mac_stats
*mac_stats
;
131 struct fbnic_dev
*fbd
= fbn
->fbd
;
132 const struct fbnic_mac
*mac
;
134 mac_stats
= &fbd
->hw_stats
.mac
;
137 mac
->get_eth_mac_stats(fbd
, false, &mac_stats
->eth_mac
);
139 fbnic_set_counter(ð_mac_stats
->FramesTransmittedOK
,
140 &mac_stats
->eth_mac
.FramesTransmittedOK
);
141 fbnic_set_counter(ð_mac_stats
->FramesReceivedOK
,
142 &mac_stats
->eth_mac
.FramesReceivedOK
);
143 fbnic_set_counter(ð_mac_stats
->FrameCheckSequenceErrors
,
144 &mac_stats
->eth_mac
.FrameCheckSequenceErrors
);
145 fbnic_set_counter(ð_mac_stats
->AlignmentErrors
,
146 &mac_stats
->eth_mac
.AlignmentErrors
);
147 fbnic_set_counter(ð_mac_stats
->OctetsTransmittedOK
,
148 &mac_stats
->eth_mac
.OctetsTransmittedOK
);
149 fbnic_set_counter(ð_mac_stats
->FramesLostDueToIntMACXmitError
,
150 &mac_stats
->eth_mac
.FramesLostDueToIntMACXmitError
);
151 fbnic_set_counter(ð_mac_stats
->OctetsReceivedOK
,
152 &mac_stats
->eth_mac
.OctetsReceivedOK
);
153 fbnic_set_counter(ð_mac_stats
->FramesLostDueToIntMACRcvError
,
154 &mac_stats
->eth_mac
.FramesLostDueToIntMACRcvError
);
155 fbnic_set_counter(ð_mac_stats
->MulticastFramesXmittedOK
,
156 &mac_stats
->eth_mac
.MulticastFramesXmittedOK
);
157 fbnic_set_counter(ð_mac_stats
->BroadcastFramesXmittedOK
,
158 &mac_stats
->eth_mac
.BroadcastFramesXmittedOK
);
159 fbnic_set_counter(ð_mac_stats
->MulticastFramesReceivedOK
,
160 &mac_stats
->eth_mac
.MulticastFramesReceivedOK
);
161 fbnic_set_counter(ð_mac_stats
->BroadcastFramesReceivedOK
,
162 &mac_stats
->eth_mac
.BroadcastFramesReceivedOK
);
163 fbnic_set_counter(ð_mac_stats
->FrameTooLongErrors
,
164 &mac_stats
->eth_mac
.FrameTooLongErrors
);
167 static void fbnic_get_ts_stats(struct net_device
*netdev
,
168 struct ethtool_ts_stats
*ts_stats
)
170 struct fbnic_net
*fbn
= netdev_priv(netdev
);
171 u64 ts_packets
, ts_lost
;
172 struct fbnic_ring
*ring
;
176 ts_stats
->pkts
= fbn
->tx_stats
.ts_packets
;
177 ts_stats
->lost
= fbn
->tx_stats
.ts_lost
;
178 for (i
= 0; i
< fbn
->num_tx_queues
; i
++) {
181 start
= u64_stats_fetch_begin(&ring
->stats
.syncp
);
182 ts_packets
= ring
->stats
.ts_packets
;
183 ts_lost
= ring
->stats
.ts_lost
;
184 } while (u64_stats_fetch_retry(&ring
->stats
.syncp
, start
));
185 ts_stats
->pkts
+= ts_packets
;
186 ts_stats
->lost
+= ts_lost
;
190 static void fbnic_get_regs(struct net_device
*netdev
,
191 struct ethtool_regs
*regs
, void *data
)
193 struct fbnic_net
*fbn
= netdev_priv(netdev
);
195 fbnic_csr_get_regs(fbn
->fbd
, data
, ®s
->version
);
198 static int fbnic_get_regs_len(struct net_device
*netdev
)
200 struct fbnic_net
*fbn
= netdev_priv(netdev
);
202 return fbnic_csr_regs_len(fbn
->fbd
) * sizeof(u32
);
205 static const struct ethtool_ops fbnic_ethtool_ops
= {
206 .get_drvinfo
= fbnic_get_drvinfo
,
207 .get_regs_len
= fbnic_get_regs_len
,
208 .get_regs
= fbnic_get_regs
,
209 .get_strings
= fbnic_get_strings
,
210 .get_ethtool_stats
= fbnic_get_ethtool_stats
,
211 .get_sset_count
= fbnic_get_sset_count
,
212 .get_ts_info
= fbnic_get_ts_info
,
213 .get_ts_stats
= fbnic_get_ts_stats
,
214 .get_eth_mac_stats
= fbnic_get_eth_mac_stats
,
217 void fbnic_set_ethtool_ops(struct net_device
*dev
)
219 dev
->ethtool_ops
= &fbnic_ethtool_ops
;