1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (c) 2024 Hisilicon Limited.
3
4 #include <linux/ethtool.h>
5 #include <linux/phy.h>
6 #include <linux/rtnetlink.h>
7 #include "hbg_common.h"
8 #include "hbg_err.h"
9 #include "hbg_ethtool.h"
10 #include "hbg_hw.h"
11
12 struct hbg_ethtool_stats {
13 char name[ETH_GSTRING_LEN];
14 unsigned long offset;
15 u32 reg; /* set to 0 if stats is not updated via dump reg */
16 };
17
18 #define HBG_STATS_I(stats) { #stats, HBG_STATS_FIELD_OFF(stats), 0}
19 #define HBG_STATS_REG_I(stats, reg) { #stats, HBG_STATS_FIELD_OFF(stats), reg}
20
21 static const struct hbg_ethtool_stats hbg_ethtool_stats_info[] = {
22 HBG_STATS_I(rx_desc_l2_err_cnt),
23 HBG_STATS_I(rx_desc_pkt_len_err_cnt),
24 HBG_STATS_I(rx_desc_l3_wrong_head_cnt),
25 HBG_STATS_I(rx_desc_l3_csum_err_cnt),
26 HBG_STATS_I(rx_desc_l3_len_err_cnt),
27 HBG_STATS_I(rx_desc_l3_zero_ttl_cnt),
28 HBG_STATS_I(rx_desc_l3_other_cnt),
29 HBG_STATS_I(rx_desc_l4_wrong_head_cnt),
30 HBG_STATS_I(rx_desc_l4_len_err_cnt),
31 HBG_STATS_I(rx_desc_l4_csum_err_cnt),
32 HBG_STATS_I(rx_desc_l4_zero_port_num_cnt),
33 HBG_STATS_I(rx_desc_l4_other_cnt),
34 HBG_STATS_I(rx_desc_ip_ver_err_cnt),
35 HBG_STATS_I(rx_desc_ipv4_pkt_cnt),
36 HBG_STATS_I(rx_desc_ipv6_pkt_cnt),
37 HBG_STATS_I(rx_desc_no_ip_pkt_cnt),
38 HBG_STATS_I(rx_desc_ip_pkt_cnt),
39 HBG_STATS_I(rx_desc_tcp_pkt_cnt),
40 HBG_STATS_I(rx_desc_udp_pkt_cnt),
41 HBG_STATS_I(rx_desc_vlan_pkt_cnt),
42 HBG_STATS_I(rx_desc_icmp_pkt_cnt),
43 HBG_STATS_I(rx_desc_arp_pkt_cnt),
44 HBG_STATS_I(rx_desc_rarp_pkt_cnt),
45 HBG_STATS_I(rx_desc_multicast_pkt_cnt),
46 HBG_STATS_I(rx_desc_broadcast_pkt_cnt),
47 HBG_STATS_I(rx_desc_ipsec_pkt_cnt),
48 HBG_STATS_I(rx_desc_ip_opt_pkt_cnt),
49 HBG_STATS_I(rx_desc_key_not_match_cnt),
50
51 HBG_STATS_REG_I(rx_octets_bad_cnt, HBG_REG_RX_OCTETS_BAD_ADDR),
52 HBG_STATS_REG_I(rx_octets_total_filt_cnt,
53 HBG_REG_RX_OCTETS_TOTAL_FILT_ADDR),
54 HBG_STATS_REG_I(rx_uc_pkt_cnt, HBG_REG_RX_UC_PKTS_ADDR),
55 HBG_STATS_REG_I(rx_vlan_pkt_cnt, HBG_REG_RX_TAGGED_ADDR),
56 HBG_STATS_REG_I(rx_filt_pkt_cnt, HBG_REG_RX_FILT_PKT_CNT_ADDR),
57 HBG_STATS_REG_I(rx_data_error_cnt, HBG_REG_RX_DATA_ERR_ADDR),
58 HBG_STATS_REG_I(rx_frame_long_err_cnt, HBG_REG_RX_LONG_ERRORS_ADDR),
59 HBG_STATS_REG_I(rx_jabber_err_cnt, HBG_REG_RX_JABBER_ERRORS_ADDR),
60 HBG_STATS_REG_I(rx_frame_very_long_err_cnt,
61 HBG_REG_RX_VERY_LONG_ERR_CNT_ADDR),
62 HBG_STATS_REG_I(rx_frame_runt_err_cnt, HBG_REG_RX_RUNT_ERR_CNT_ADDR),
63 HBG_STATS_REG_I(rx_frame_short_err_cnt, HBG_REG_RX_SHORT_ERR_CNT_ADDR),
64 HBG_STATS_REG_I(rx_overflow_cnt, HBG_REG_RX_OVER_FLOW_CNT_ADDR),
65 HBG_STATS_REG_I(rx_bufrq_err_cnt, HBG_REG_RX_BUFRQ_ERR_CNT_ADDR),
66 HBG_STATS_REG_I(rx_we_err_cnt, HBG_REG_RX_WE_ERR_CNT_ADDR),
67 HBG_STATS_REG_I(rx_overrun_cnt, HBG_REG_RX_OVERRUN_CNT_ADDR),
68 HBG_STATS_REG_I(rx_lengthfield_err_cnt,
69 HBG_REG_RX_LENGTHFIELD_ERR_CNT_ADDR),
70 HBG_STATS_REG_I(rx_fail_comma_cnt, HBG_REG_RX_FAIL_COMMA_CNT_ADDR),
71 HBG_STATS_I(rx_dma_err_cnt),
72 HBG_STATS_I(rx_fifo_less_empty_thrsld_cnt),
73
74 HBG_STATS_REG_I(tx_uc_pkt_cnt, HBG_REG_TX_UC_PKTS_ADDR),
75 HBG_STATS_REG_I(tx_vlan_pkt_cnt, HBG_REG_TX_TAGGED_ADDR),
76 HBG_STATS_REG_I(tx_octets_bad_cnt, HBG_REG_OCTETS_TRANSMITTED_BAD_ADDR),
77
78 HBG_STATS_REG_I(tx_underrun_err_cnt, HBG_REG_TX_UNDERRUN_ADDR),
79 HBG_STATS_REG_I(tx_add_cs_fail_cnt, HBG_REG_TX_CS_FAIL_CNT_ADDR),
80 HBG_STATS_REG_I(tx_bufrl_err_cnt, HBG_REG_TX_BUFRL_ERR_CNT_ADDR),
81 HBG_STATS_REG_I(tx_crc_err_cnt, HBG_REG_TX_CRC_ERROR_ADDR),
82 HBG_STATS_REG_I(tx_drop_cnt, HBG_REG_TX_DROP_CNT_ADDR),
83 HBG_STATS_REG_I(tx_excessive_length_drop_cnt,
84 HBG_REG_TX_EXCESSIVE_LENGTH_DROP_ADDR),
85 HBG_STATS_I(tx_dma_err_cnt),
86 HBG_STATS_I(tx_timeout_cnt),
87 };
88
89 static const struct hbg_ethtool_stats hbg_ethtool_rmon_stats_info[] = {
90 HBG_STATS_I(rx_desc_frag_cnt),
91 HBG_STATS_REG_I(rx_framesize_64, HBG_REG_RX_PKTS_64OCTETS_ADDR),
92 HBG_STATS_REG_I(rx_framesize_65_127,
93 HBG_REG_RX_PKTS_65TO127OCTETS_ADDR),
94 HBG_STATS_REG_I(rx_framesize_128_255,
95 HBG_REG_RX_PKTS_128TO255OCTETS_ADDR),
96 HBG_STATS_REG_I(rx_framesize_256_511,
97 HBG_REG_RX_PKTS_256TO511OCTETS_ADDR),
98 HBG_STATS_REG_I(rx_framesize_512_1023,
99 HBG_REG_RX_PKTS_512TO1023OCTETS_ADDR),
100 HBG_STATS_REG_I(rx_framesize_1024_1518,
101 HBG_REG_RX_PKTS_1024TO1518OCTETS_ADDR),
102 HBG_STATS_REG_I(rx_framesize_bt_1518,
103 HBG_REG_RX_PKTS_1519TOMAXOCTETS_ADDR),
104 HBG_STATS_REG_I(tx_framesize_64, HBG_REG_TX_PKTS_64OCTETS_ADDR),
105 HBG_STATS_REG_I(tx_framesize_65_127,
106 HBG_REG_TX_PKTS_65TO127OCTETS_ADDR),
107 HBG_STATS_REG_I(tx_framesize_128_255,
108 HBG_REG_TX_PKTS_128TO255OCTETS_ADDR),
109 HBG_STATS_REG_I(tx_framesize_256_511,
110 HBG_REG_TX_PKTS_256TO511OCTETS_ADDR),
111 HBG_STATS_REG_I(tx_framesize_512_1023,
112 HBG_REG_TX_PKTS_512TO1023OCTETS_ADDR),
113 HBG_STATS_REG_I(tx_framesize_1024_1518,
114 HBG_REG_TX_PKTS_1024TO1518OCTETS_ADDR),
115 HBG_STATS_REG_I(tx_framesize_bt_1518,
116 HBG_REG_TX_PKTS_1519TOMAXOCTETS_ADDR),
117 };
118
119 static const struct hbg_ethtool_stats hbg_ethtool_mac_stats_info[] = {
120 HBG_STATS_REG_I(rx_mc_pkt_cnt, HBG_REG_RX_MC_PKTS_ADDR),
121 HBG_STATS_REG_I(rx_bc_pkt_cnt, HBG_REG_RX_BC_PKTS_ADDR),
122 HBG_STATS_REG_I(rx_align_error_cnt, HBG_REG_RX_ALIGN_ERRORS_ADDR),
123 HBG_STATS_REG_I(rx_octets_total_ok_cnt,
124 HBG_REG_RX_OCTETS_TOTAL_OK_ADDR),
125 HBG_STATS_REG_I(rx_trans_pkt_cnt, HBG_REG_RX_TRANS_PKG_CNT_ADDR),
126 HBG_STATS_REG_I(rx_fcs_error_cnt, HBG_REG_RX_FCS_ERRORS_ADDR),
127 HBG_STATS_REG_I(tx_mc_pkt_cnt, HBG_REG_TX_MC_PKTS_ADDR),
128 HBG_STATS_REG_I(tx_bc_pkt_cnt, HBG_REG_TX_BC_PKTS_ADDR),
129 HBG_STATS_REG_I(tx_octets_total_ok_cnt,
130 HBG_REG_OCTETS_TRANSMITTED_OK_ADDR),
131 HBG_STATS_REG_I(tx_trans_pkt_cnt, HBG_REG_TX_TRANS_PKG_CNT_ADDR),
132 };
133
134 static const struct hbg_ethtool_stats hbg_ethtool_ctrl_stats_info[] = {
135 HBG_STATS_REG_I(rx_pause_macctl_frame_cnt,
136 HBG_REG_RX_PAUSE_MACCTL_FRAMCOUNTER_ADDR),
137 HBG_STATS_REG_I(tx_pause_frame_cnt, HBG_REG_TX_PAUSE_FRAMES_ADDR),
138 HBG_STATS_REG_I(rx_unknown_macctl_frame_cnt,
139 HBG_REG_RX_UNKNOWN_MACCTL_FRAMCOUNTER_ADDR),
140 };
141
142 enum hbg_reg_dump_type {
143 HBG_DUMP_REG_TYPE_SPEC = 0,
144 HBG_DUMP_REG_TYPE_MDIO,
145 HBG_DUMP_REG_TYPE_GMAC,
146 HBG_DUMP_REG_TYPE_PCU,
147 };
148
149 struct hbg_reg_info {
150 u32 type;
151 u32 offset;
152 u32 val;
153 };
154
155 #define HBG_DUMP_SPEC_I(offset) {HBG_DUMP_REG_TYPE_SPEC, offset, 0}
156 #define HBG_DUMP_MDIO_I(offset) {HBG_DUMP_REG_TYPE_MDIO, offset, 0}
157 #define HBG_DUMP_GMAC_I(offset) {HBG_DUMP_REG_TYPE_GMAC, offset, 0}
158 #define HBG_DUMP_PCU_I(offset) {HBG_DUMP_REG_TYPE_PCU, offset, 0}
159
160 static const struct hbg_reg_info hbg_dump_reg_infos[] = {
161 /* dev specs */
162 HBG_DUMP_SPEC_I(HBG_REG_SPEC_VALID_ADDR),
163 HBG_DUMP_SPEC_I(HBG_REG_EVENT_REQ_ADDR),
164 HBG_DUMP_SPEC_I(HBG_REG_MAC_ID_ADDR),
165 HBG_DUMP_SPEC_I(HBG_REG_PHY_ID_ADDR),
166 HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_ADDR),
167 HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_HIGH_ADDR),
168 HBG_DUMP_SPEC_I(HBG_REG_UC_MAC_NUM_ADDR),
169 HBG_DUMP_SPEC_I(HBG_REG_MDIO_FREQ_ADDR),
170 HBG_DUMP_SPEC_I(HBG_REG_MAX_MTU_ADDR),
171 HBG_DUMP_SPEC_I(HBG_REG_MIN_MTU_ADDR),
172 HBG_DUMP_SPEC_I(HBG_REG_TX_FIFO_NUM_ADDR),
173 HBG_DUMP_SPEC_I(HBG_REG_RX_FIFO_NUM_ADDR),
174 HBG_DUMP_SPEC_I(HBG_REG_VLAN_LAYERS_ADDR),
175
176 /* mdio */
177 HBG_DUMP_MDIO_I(HBG_REG_MDIO_COMMAND_ADDR),
178 HBG_DUMP_MDIO_I(HBG_REG_MDIO_ADDR_ADDR),
179 HBG_DUMP_MDIO_I(HBG_REG_MDIO_WDATA_ADDR),
180 HBG_DUMP_MDIO_I(HBG_REG_MDIO_RDATA_ADDR),
181 HBG_DUMP_MDIO_I(HBG_REG_MDIO_STA_ADDR),
182
183 /* gmac */
184 HBG_DUMP_GMAC_I(HBG_REG_DUPLEX_TYPE_ADDR),
185 HBG_DUMP_GMAC_I(HBG_REG_FD_FC_TYPE_ADDR),
186 HBG_DUMP_GMAC_I(HBG_REG_FC_TX_TIMER_ADDR),
187 HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_LOW_ADDR),
188 HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_HIGH_ADDR),
189 HBG_DUMP_GMAC_I(HBG_REG_MAX_FRAME_SIZE_ADDR),
190 HBG_DUMP_GMAC_I(HBG_REG_PORT_MODE_ADDR),
191 HBG_DUMP_GMAC_I(HBG_REG_PORT_ENABLE_ADDR),
192 HBG_DUMP_GMAC_I(HBG_REG_PAUSE_ENABLE_ADDR),
193 HBG_DUMP_GMAC_I(HBG_REG_AN_NEG_STATE_ADDR),
194 HBG_DUMP_GMAC_I(HBG_REG_TRANSMIT_CTRL_ADDR),
195 HBG_DUMP_GMAC_I(HBG_REG_REC_FILT_CTRL_ADDR),
196 HBG_DUMP_GMAC_I(HBG_REG_LINE_LOOP_BACK_ADDR),
197 HBG_DUMP_GMAC_I(HBG_REG_CF_CRC_STRIP_ADDR),
198 HBG_DUMP_GMAC_I(HBG_REG_MODE_CHANGE_EN_ADDR),
199 HBG_DUMP_GMAC_I(HBG_REG_LOOP_REG_ADDR),
200 HBG_DUMP_GMAC_I(HBG_REG_RECV_CTRL_ADDR),
201 HBG_DUMP_GMAC_I(HBG_REG_VLAN_CODE_ADDR),
202 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_0_ADDR),
203 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_0_ADDR),
204 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_1_ADDR),
205 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_1_ADDR),
206 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_2_ADDR),
207 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_2_ADDR),
208 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_3_ADDR),
209 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_3_ADDR),
210 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_4_ADDR),
211 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_4_ADDR),
212 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_5_ADDR),
213 HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_5_ADDR),
214
215 /* pcu */
216 HBG_DUMP_PCU_I(HBG_REG_TX_FIFO_THRSLD_ADDR),
217 HBG_DUMP_PCU_I(HBG_REG_RX_FIFO_THRSLD_ADDR),
218 HBG_DUMP_PCU_I(HBG_REG_CFG_FIFO_THRSLD_ADDR),
219 HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_MSK_ADDR),
220 HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_STAT_ADDR),
221 HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_CLR_ADDR),
222 HBG_DUMP_PCU_I(HBG_REG_TX_BUS_ERR_ADDR_ADDR),
223 HBG_DUMP_PCU_I(HBG_REG_RX_BUS_ERR_ADDR_ADDR),
224 HBG_DUMP_PCU_I(HBG_REG_MAX_FRAME_LEN_ADDR),
225 HBG_DUMP_PCU_I(HBG_REG_DEBUG_ST_MCH_ADDR),
226 HBG_DUMP_PCU_I(HBG_REG_FIFO_CURR_STATUS_ADDR),
227 HBG_DUMP_PCU_I(HBG_REG_FIFO_HIST_STATUS_ADDR),
228 HBG_DUMP_PCU_I(HBG_REG_CF_CFF_DATA_NUM_ADDR),
229 HBG_DUMP_PCU_I(HBG_REG_CF_TX_PAUSE_ADDR),
230 HBG_DUMP_PCU_I(HBG_REG_RX_CFF_ADDR_ADDR),
231 HBG_DUMP_PCU_I(HBG_REG_RX_BUF_SIZE_ADDR),
232 HBG_DUMP_PCU_I(HBG_REG_BUS_CTRL_ADDR),
233 HBG_DUMP_PCU_I(HBG_REG_RX_CTRL_ADDR),
234 HBG_DUMP_PCU_I(HBG_REG_RX_PKT_MODE_ADDR),
235 HBG_DUMP_PCU_I(HBG_REG_DBG_ST0_ADDR),
236 HBG_DUMP_PCU_I(HBG_REG_DBG_ST1_ADDR),
237 HBG_DUMP_PCU_I(HBG_REG_DBG_ST2_ADDR),
238 HBG_DUMP_PCU_I(HBG_REG_BUS_RST_EN_ADDR),
239 HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_MSK_ADDR),
240 HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_STAT_ADDR),
241 HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_CLR_ADDR),
242 HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_MSK_ADDR),
243 HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_STAT_ADDR),
244 HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_CLR_ADDR),
245 };
246
247 static const u32 hbg_dump_type_base_array[] = {
248 [HBG_DUMP_REG_TYPE_SPEC] = 0,
249 [HBG_DUMP_REG_TYPE_MDIO] = HBG_REG_MDIO_BASE,
250 [HBG_DUMP_REG_TYPE_GMAC] = HBG_REG_SGMII_BASE,
251 [HBG_DUMP_REG_TYPE_PCU] = HBG_REG_SGMII_BASE,
252 };
253
hbg_ethtool_get_regs_len(struct net_device * netdev)254 static int hbg_ethtool_get_regs_len(struct net_device *netdev)
255 {
256 return ARRAY_SIZE(hbg_dump_reg_infos) * sizeof(struct hbg_reg_info);
257 }
258
hbg_ethtool_get_regs(struct net_device * netdev,struct ethtool_regs * regs,void * data)259 static void hbg_ethtool_get_regs(struct net_device *netdev,
260 struct ethtool_regs *regs, void *data)
261 {
262 struct hbg_priv *priv = netdev_priv(netdev);
263 struct hbg_reg_info *info;
264 u32 i, offset = 0;
265
266 regs->version = 0;
267 for (i = 0; i < ARRAY_SIZE(hbg_dump_reg_infos); i++) {
268 info = data + offset;
269
270 *info = hbg_dump_reg_infos[i];
271 info->val = hbg_reg_read(priv, info->offset);
272 info->offset -= hbg_dump_type_base_array[info->type];
273
274 offset += sizeof(*info);
275 }
276 }
277
hbg_ethtool_get_pauseparam(struct net_device * net_dev,struct ethtool_pauseparam * param)278 static void hbg_ethtool_get_pauseparam(struct net_device *net_dev,
279 struct ethtool_pauseparam *param)
280 {
281 struct hbg_priv *priv = netdev_priv(net_dev);
282
283 param->autoneg = priv->mac.pause_autoneg;
284 hbg_hw_get_pause_enable(priv, ¶m->tx_pause, ¶m->rx_pause);
285 }
286
hbg_ethtool_set_pauseparam(struct net_device * net_dev,struct ethtool_pauseparam * param)287 static int hbg_ethtool_set_pauseparam(struct net_device *net_dev,
288 struct ethtool_pauseparam *param)
289 {
290 struct hbg_priv *priv = netdev_priv(net_dev);
291
292 priv->mac.pause_autoneg = param->autoneg;
293 phy_set_asym_pause(priv->mac.phydev, param->rx_pause, param->tx_pause);
294
295 if (!param->autoneg)
296 hbg_hw_set_pause_enable(priv, param->tx_pause, param->rx_pause);
297
298 priv->user_def.pause_param = *param;
299 return 0;
300 }
301
hbg_ethtool_reset(struct net_device * netdev,u32 * flags)302 static int hbg_ethtool_reset(struct net_device *netdev, u32 *flags)
303 {
304 struct hbg_priv *priv = netdev_priv(netdev);
305
306 if (*flags != ETH_RESET_DEDICATED)
307 return -EOPNOTSUPP;
308
309 *flags = 0;
310 return hbg_reset(priv);
311 }
312
hbg_update_stats_by_info(struct hbg_priv * priv,const struct hbg_ethtool_stats * info,u32 info_len)313 static void hbg_update_stats_by_info(struct hbg_priv *priv,
314 const struct hbg_ethtool_stats *info,
315 u32 info_len)
316 {
317 const struct hbg_ethtool_stats *stats;
318 u32 i;
319
320 if (test_bit(HBG_NIC_STATE_RESETTING, &priv->state))
321 return;
322
323 for (i = 0; i < info_len; i++) {
324 stats = &info[i];
325 if (!stats->reg)
326 continue;
327
328 HBG_STATS_U(&priv->stats, stats->offset,
329 hbg_reg_read(priv, stats->reg));
330 }
331 }
332
hbg_update_stats(struct hbg_priv * priv)333 void hbg_update_stats(struct hbg_priv *priv)
334 {
335 hbg_update_stats_by_info(priv, hbg_ethtool_stats_info,
336 ARRAY_SIZE(hbg_ethtool_stats_info));
337 hbg_update_stats_by_info(priv, hbg_ethtool_rmon_stats_info,
338 ARRAY_SIZE(hbg_ethtool_rmon_stats_info));
339 hbg_update_stats_by_info(priv, hbg_ethtool_mac_stats_info,
340 ARRAY_SIZE(hbg_ethtool_mac_stats_info));
341 hbg_update_stats_by_info(priv, hbg_ethtool_ctrl_stats_info,
342 ARRAY_SIZE(hbg_ethtool_ctrl_stats_info));
343 }
344
hbg_ethtool_get_sset_count(struct net_device * netdev,int stringset)345 static int hbg_ethtool_get_sset_count(struct net_device *netdev, int stringset)
346 {
347 if (stringset != ETH_SS_STATS)
348 return -EOPNOTSUPP;
349
350 return ARRAY_SIZE(hbg_ethtool_stats_info);
351 }
352
hbg_ethtool_get_strings(struct net_device * netdev,u32 stringset,u8 * data)353 static void hbg_ethtool_get_strings(struct net_device *netdev,
354 u32 stringset, u8 *data)
355 {
356 u32 i;
357
358 if (stringset != ETH_SS_STATS)
359 return;
360
361 for (i = 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++)
362 ethtool_puts(&data, hbg_ethtool_stats_info[i].name);
363 }
364
hbg_ethtool_get_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)365 static void hbg_ethtool_get_stats(struct net_device *netdev,
366 struct ethtool_stats *stats, u64 *data)
367 {
368 struct hbg_priv *priv = netdev_priv(netdev);
369 u32 i;
370
371 hbg_update_stats(priv);
372 for (i = 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++)
373 *data++ = HBG_STATS_R(&priv->stats,
374 hbg_ethtool_stats_info[i].offset);
375 }
376
hbg_ethtool_get_pause_stats(struct net_device * netdev,struct ethtool_pause_stats * epstats)377 static void hbg_ethtool_get_pause_stats(struct net_device *netdev,
378 struct ethtool_pause_stats *epstats)
379 {
380 struct hbg_priv *priv = netdev_priv(netdev);
381 struct hbg_stats *stats = &priv->stats;
382
383 hbg_update_stats(priv);
384 epstats->rx_pause_frames = stats->rx_pause_macctl_frame_cnt;
385 epstats->tx_pause_frames = stats->tx_pause_frame_cnt;
386 }
387
hbg_ethtool_get_eth_mac_stats(struct net_device * netdev,struct ethtool_eth_mac_stats * emstats)388 static void hbg_ethtool_get_eth_mac_stats(struct net_device *netdev,
389 struct ethtool_eth_mac_stats *emstats)
390 {
391 struct hbg_priv *priv = netdev_priv(netdev);
392 struct hbg_stats *stats = &priv->stats;
393
394 hbg_update_stats(priv);
395 emstats->FramesTransmittedOK = stats->tx_trans_pkt_cnt;
396 emstats->FramesReceivedOK = stats->rx_trans_pkt_cnt;
397 emstats->FrameCheckSequenceErrors = stats->rx_fcs_error_cnt;
398 emstats->AlignmentErrors = stats->rx_align_error_cnt;
399 emstats->OctetsTransmittedOK = stats->tx_octets_total_ok_cnt;
400 emstats->OctetsReceivedOK = stats->rx_octets_total_ok_cnt;
401
402 emstats->MulticastFramesXmittedOK = stats->tx_mc_pkt_cnt;
403 emstats->BroadcastFramesXmittedOK = stats->tx_bc_pkt_cnt;
404 emstats->MulticastFramesReceivedOK = stats->rx_mc_pkt_cnt;
405 emstats->BroadcastFramesReceivedOK = stats->rx_bc_pkt_cnt;
406 emstats->InRangeLengthErrors = stats->rx_fcs_error_cnt +
407 stats->rx_jabber_err_cnt +
408 stats->rx_unknown_macctl_frame_cnt +
409 stats->rx_bufrq_err_cnt +
410 stats->rx_we_err_cnt;
411 emstats->OutOfRangeLengthField = stats->rx_frame_short_err_cnt +
412 stats->rx_frame_runt_err_cnt +
413 stats->rx_lengthfield_err_cnt +
414 stats->rx_frame_long_err_cnt +
415 stats->rx_frame_very_long_err_cnt;
416 emstats->FrameTooLongErrors = stats->rx_frame_long_err_cnt +
417 stats->rx_frame_very_long_err_cnt;
418 }
419
420 static void
hbg_ethtool_get_eth_ctrl_stats(struct net_device * netdev,struct ethtool_eth_ctrl_stats * ecstats)421 hbg_ethtool_get_eth_ctrl_stats(struct net_device *netdev,
422 struct ethtool_eth_ctrl_stats *ecstats)
423 {
424 struct hbg_priv *priv = netdev_priv(netdev);
425 struct hbg_stats *s = &priv->stats;
426
427 hbg_update_stats(priv);
428 ecstats->MACControlFramesTransmitted = s->tx_pause_frame_cnt;
429 ecstats->MACControlFramesReceived = s->rx_pause_macctl_frame_cnt;
430 ecstats->UnsupportedOpcodesReceived = s->rx_unknown_macctl_frame_cnt;
431 }
432
433 static const struct ethtool_rmon_hist_range hbg_rmon_ranges[] = {
434 { 0, 64 },
435 { 65, 127 },
436 { 128, 255 },
437 { 256, 511 },
438 { 512, 1023 },
439 { 1024, 1518 },
440 { 1519, 4095 },
441 };
442
443 static void
hbg_ethtool_get_rmon_stats(struct net_device * netdev,struct ethtool_rmon_stats * rmon_stats,const struct ethtool_rmon_hist_range ** ranges)444 hbg_ethtool_get_rmon_stats(struct net_device *netdev,
445 struct ethtool_rmon_stats *rmon_stats,
446 const struct ethtool_rmon_hist_range **ranges)
447 {
448 struct hbg_priv *priv = netdev_priv(netdev);
449 struct hbg_stats *stats = &priv->stats;
450
451 hbg_update_stats(priv);
452 rmon_stats->undersize_pkts = stats->rx_frame_short_err_cnt +
453 stats->rx_frame_runt_err_cnt +
454 stats->rx_lengthfield_err_cnt;
455 rmon_stats->oversize_pkts = stats->rx_frame_long_err_cnt +
456 stats->rx_frame_very_long_err_cnt;
457 rmon_stats->fragments = stats->rx_desc_frag_cnt;
458 rmon_stats->hist[0] = stats->rx_framesize_64;
459 rmon_stats->hist[1] = stats->rx_framesize_65_127;
460 rmon_stats->hist[2] = stats->rx_framesize_128_255;
461 rmon_stats->hist[3] = stats->rx_framesize_256_511;
462 rmon_stats->hist[4] = stats->rx_framesize_512_1023;
463 rmon_stats->hist[5] = stats->rx_framesize_1024_1518;
464 rmon_stats->hist[6] = stats->rx_framesize_bt_1518;
465
466 rmon_stats->hist_tx[0] = stats->tx_framesize_64;
467 rmon_stats->hist_tx[1] = stats->tx_framesize_65_127;
468 rmon_stats->hist_tx[2] = stats->tx_framesize_128_255;
469 rmon_stats->hist_tx[3] = stats->tx_framesize_256_511;
470 rmon_stats->hist_tx[4] = stats->tx_framesize_512_1023;
471 rmon_stats->hist_tx[5] = stats->tx_framesize_1024_1518;
472 rmon_stats->hist_tx[6] = stats->tx_framesize_bt_1518;
473
474 *ranges = hbg_rmon_ranges;
475 }
476
477 static const struct ethtool_ops hbg_ethtool_ops = {
478 .get_link = ethtool_op_get_link,
479 .get_link_ksettings = phy_ethtool_get_link_ksettings,
480 .set_link_ksettings = phy_ethtool_set_link_ksettings,
481 .get_regs_len = hbg_ethtool_get_regs_len,
482 .get_regs = hbg_ethtool_get_regs,
483 .get_pauseparam = hbg_ethtool_get_pauseparam,
484 .set_pauseparam = hbg_ethtool_set_pauseparam,
485 .reset = hbg_ethtool_reset,
486 .nway_reset = phy_ethtool_nway_reset,
487 .get_sset_count = hbg_ethtool_get_sset_count,
488 .get_strings = hbg_ethtool_get_strings,
489 .get_ethtool_stats = hbg_ethtool_get_stats,
490 .get_pause_stats = hbg_ethtool_get_pause_stats,
491 .get_eth_mac_stats = hbg_ethtool_get_eth_mac_stats,
492 .get_eth_ctrl_stats = hbg_ethtool_get_eth_ctrl_stats,
493 .get_rmon_stats = hbg_ethtool_get_rmon_stats,
494 };
495
hbg_ethtool_set_ops(struct net_device * netdev)496 void hbg_ethtool_set_ops(struct net_device *netdev)
497 {
498 netdev->ethtool_ops = &hbg_ethtool_ops;
499 }
500