xref: /linux/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
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 	HBG_STATS_I(reset_fail_cnt),
88 };
89 
90 static const struct hbg_ethtool_stats hbg_ethtool_rmon_stats_info[] = {
91 	HBG_STATS_I(rx_desc_frag_cnt),
92 	HBG_STATS_REG_I(rx_framesize_64, HBG_REG_RX_PKTS_64OCTETS_ADDR),
93 	HBG_STATS_REG_I(rx_framesize_65_127,
94 			HBG_REG_RX_PKTS_65TO127OCTETS_ADDR),
95 	HBG_STATS_REG_I(rx_framesize_128_255,
96 			HBG_REG_RX_PKTS_128TO255OCTETS_ADDR),
97 	HBG_STATS_REG_I(rx_framesize_256_511,
98 			HBG_REG_RX_PKTS_256TO511OCTETS_ADDR),
99 	HBG_STATS_REG_I(rx_framesize_512_1023,
100 			HBG_REG_RX_PKTS_512TO1023OCTETS_ADDR),
101 	HBG_STATS_REG_I(rx_framesize_1024_1518,
102 			HBG_REG_RX_PKTS_1024TO1518OCTETS_ADDR),
103 	HBG_STATS_REG_I(rx_framesize_bt_1518,
104 			HBG_REG_RX_PKTS_1519TOMAXOCTETS_ADDR),
105 	HBG_STATS_REG_I(tx_framesize_64, HBG_REG_TX_PKTS_64OCTETS_ADDR),
106 	HBG_STATS_REG_I(tx_framesize_65_127,
107 			HBG_REG_TX_PKTS_65TO127OCTETS_ADDR),
108 	HBG_STATS_REG_I(tx_framesize_128_255,
109 			HBG_REG_TX_PKTS_128TO255OCTETS_ADDR),
110 	HBG_STATS_REG_I(tx_framesize_256_511,
111 			HBG_REG_TX_PKTS_256TO511OCTETS_ADDR),
112 	HBG_STATS_REG_I(tx_framesize_512_1023,
113 			HBG_REG_TX_PKTS_512TO1023OCTETS_ADDR),
114 	HBG_STATS_REG_I(tx_framesize_1024_1518,
115 			HBG_REG_TX_PKTS_1024TO1518OCTETS_ADDR),
116 	HBG_STATS_REG_I(tx_framesize_bt_1518,
117 			HBG_REG_TX_PKTS_1519TOMAXOCTETS_ADDR),
118 };
119 
120 static const struct hbg_ethtool_stats hbg_ethtool_mac_stats_info[] = {
121 	HBG_STATS_REG_I(rx_mc_pkt_cnt, HBG_REG_RX_MC_PKTS_ADDR),
122 	HBG_STATS_REG_I(rx_bc_pkt_cnt, HBG_REG_RX_BC_PKTS_ADDR),
123 	HBG_STATS_REG_I(rx_align_error_cnt, HBG_REG_RX_ALIGN_ERRORS_ADDR),
124 	HBG_STATS_REG_I(rx_octets_total_ok_cnt,
125 			HBG_REG_RX_OCTETS_TOTAL_OK_ADDR),
126 	HBG_STATS_REG_I(rx_trans_pkt_cnt, HBG_REG_RX_TRANS_PKG_CNT_ADDR),
127 	HBG_STATS_REG_I(rx_fcs_error_cnt, HBG_REG_RX_FCS_ERRORS_ADDR),
128 	HBG_STATS_REG_I(tx_mc_pkt_cnt, HBG_REG_TX_MC_PKTS_ADDR),
129 	HBG_STATS_REG_I(tx_bc_pkt_cnt, HBG_REG_TX_BC_PKTS_ADDR),
130 	HBG_STATS_REG_I(tx_octets_total_ok_cnt,
131 			HBG_REG_OCTETS_TRANSMITTED_OK_ADDR),
132 	HBG_STATS_REG_I(tx_trans_pkt_cnt, HBG_REG_TX_TRANS_PKG_CNT_ADDR),
133 };
134 
135 static const struct hbg_ethtool_stats hbg_ethtool_ctrl_stats_info[] = {
136 	HBG_STATS_REG_I(rx_pause_macctl_frame_cnt,
137 			HBG_REG_RX_PAUSE_MACCTL_FRAMCOUNTER_ADDR),
138 	HBG_STATS_REG_I(tx_pause_frame_cnt, HBG_REG_TX_PAUSE_FRAMES_ADDR),
139 	HBG_STATS_REG_I(rx_unknown_macctl_frame_cnt,
140 			HBG_REG_RX_UNKNOWN_MACCTL_FRAMCOUNTER_ADDR),
141 };
142 
143 enum hbg_reg_dump_type {
144 	HBG_DUMP_REG_TYPE_SPEC = 0,
145 	HBG_DUMP_REG_TYPE_MDIO,
146 	HBG_DUMP_REG_TYPE_GMAC,
147 	HBG_DUMP_REG_TYPE_PCU,
148 };
149 
150 struct hbg_reg_info {
151 	u32 type;
152 	u32 offset;
153 	u32 val;
154 };
155 
156 #define HBG_DUMP_SPEC_I(offset) {HBG_DUMP_REG_TYPE_SPEC, offset, 0}
157 #define HBG_DUMP_MDIO_I(offset) {HBG_DUMP_REG_TYPE_MDIO, offset, 0}
158 #define HBG_DUMP_GMAC_I(offset) {HBG_DUMP_REG_TYPE_GMAC, offset, 0}
159 #define HBG_DUMP_PCU_I(offset) {HBG_DUMP_REG_TYPE_PCU, offset, 0}
160 
161 static const struct hbg_reg_info hbg_dump_reg_infos[] = {
162 	/* dev specs */
163 	HBG_DUMP_SPEC_I(HBG_REG_SPEC_VALID_ADDR),
164 	HBG_DUMP_SPEC_I(HBG_REG_EVENT_REQ_ADDR),
165 	HBG_DUMP_SPEC_I(HBG_REG_MAC_ID_ADDR),
166 	HBG_DUMP_SPEC_I(HBG_REG_PHY_ID_ADDR),
167 	HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_ADDR),
168 	HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_HIGH_ADDR),
169 	HBG_DUMP_SPEC_I(HBG_REG_UC_MAC_NUM_ADDR),
170 	HBG_DUMP_SPEC_I(HBG_REG_MDIO_FREQ_ADDR),
171 	HBG_DUMP_SPEC_I(HBG_REG_MAX_MTU_ADDR),
172 	HBG_DUMP_SPEC_I(HBG_REG_MIN_MTU_ADDR),
173 	HBG_DUMP_SPEC_I(HBG_REG_TX_FIFO_NUM_ADDR),
174 	HBG_DUMP_SPEC_I(HBG_REG_RX_FIFO_NUM_ADDR),
175 	HBG_DUMP_SPEC_I(HBG_REG_VLAN_LAYERS_ADDR),
176 
177 	/* mdio */
178 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_COMMAND_ADDR),
179 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_ADDR_ADDR),
180 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_WDATA_ADDR),
181 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_RDATA_ADDR),
182 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_STA_ADDR),
183 
184 	/* gmac */
185 	HBG_DUMP_GMAC_I(HBG_REG_DUPLEX_TYPE_ADDR),
186 	HBG_DUMP_GMAC_I(HBG_REG_FD_FC_TYPE_ADDR),
187 	HBG_DUMP_GMAC_I(HBG_REG_FC_TX_TIMER_ADDR),
188 	HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_LOW_ADDR),
189 	HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_HIGH_ADDR),
190 	HBG_DUMP_GMAC_I(HBG_REG_MAX_FRAME_SIZE_ADDR),
191 	HBG_DUMP_GMAC_I(HBG_REG_PORT_MODE_ADDR),
192 	HBG_DUMP_GMAC_I(HBG_REG_PORT_ENABLE_ADDR),
193 	HBG_DUMP_GMAC_I(HBG_REG_PAUSE_ENABLE_ADDR),
194 	HBG_DUMP_GMAC_I(HBG_REG_AN_NEG_STATE_ADDR),
195 	HBG_DUMP_GMAC_I(HBG_REG_TRANSMIT_CTRL_ADDR),
196 	HBG_DUMP_GMAC_I(HBG_REG_REC_FILT_CTRL_ADDR),
197 	HBG_DUMP_GMAC_I(HBG_REG_LINE_LOOP_BACK_ADDR),
198 	HBG_DUMP_GMAC_I(HBG_REG_CF_CRC_STRIP_ADDR),
199 	HBG_DUMP_GMAC_I(HBG_REG_MODE_CHANGE_EN_ADDR),
200 	HBG_DUMP_GMAC_I(HBG_REG_LOOP_REG_ADDR),
201 	HBG_DUMP_GMAC_I(HBG_REG_RECV_CTRL_ADDR),
202 	HBG_DUMP_GMAC_I(HBG_REG_VLAN_CODE_ADDR),
203 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_0_ADDR),
204 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_0_ADDR),
205 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_1_ADDR),
206 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_1_ADDR),
207 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_2_ADDR),
208 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_2_ADDR),
209 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_3_ADDR),
210 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_3_ADDR),
211 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_4_ADDR),
212 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_4_ADDR),
213 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_5_ADDR),
214 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_5_ADDR),
215 
216 	/* pcu */
217 	HBG_DUMP_PCU_I(HBG_REG_TX_FIFO_THRSLD_ADDR),
218 	HBG_DUMP_PCU_I(HBG_REG_RX_FIFO_THRSLD_ADDR),
219 	HBG_DUMP_PCU_I(HBG_REG_CFG_FIFO_THRSLD_ADDR),
220 	HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_MSK_ADDR),
221 	HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_STAT_ADDR),
222 	HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_CLR_ADDR),
223 	HBG_DUMP_PCU_I(HBG_REG_TX_BUS_ERR_ADDR_ADDR),
224 	HBG_DUMP_PCU_I(HBG_REG_RX_BUS_ERR_ADDR_ADDR),
225 	HBG_DUMP_PCU_I(HBG_REG_MAX_FRAME_LEN_ADDR),
226 	HBG_DUMP_PCU_I(HBG_REG_DEBUG_ST_MCH_ADDR),
227 	HBG_DUMP_PCU_I(HBG_REG_FIFO_CURR_STATUS_ADDR),
228 	HBG_DUMP_PCU_I(HBG_REG_FIFO_HIST_STATUS_ADDR),
229 	HBG_DUMP_PCU_I(HBG_REG_CF_CFF_DATA_NUM_ADDR),
230 	HBG_DUMP_PCU_I(HBG_REG_CF_TX_PAUSE_ADDR),
231 	HBG_DUMP_PCU_I(HBG_REG_RX_CFF_ADDR_ADDR),
232 	HBG_DUMP_PCU_I(HBG_REG_RX_BUF_SIZE_ADDR),
233 	HBG_DUMP_PCU_I(HBG_REG_BUS_CTRL_ADDR),
234 	HBG_DUMP_PCU_I(HBG_REG_RX_CTRL_ADDR),
235 	HBG_DUMP_PCU_I(HBG_REG_RX_PKT_MODE_ADDR),
236 	HBG_DUMP_PCU_I(HBG_REG_DBG_ST0_ADDR),
237 	HBG_DUMP_PCU_I(HBG_REG_DBG_ST1_ADDR),
238 	HBG_DUMP_PCU_I(HBG_REG_DBG_ST2_ADDR),
239 	HBG_DUMP_PCU_I(HBG_REG_BUS_RST_EN_ADDR),
240 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_MSK_ADDR),
241 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_STAT_ADDR),
242 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_CLR_ADDR),
243 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_MSK_ADDR),
244 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_STAT_ADDR),
245 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_CLR_ADDR),
246 };
247 
248 static const u32 hbg_dump_type_base_array[] = {
249 	[HBG_DUMP_REG_TYPE_SPEC] = 0,
250 	[HBG_DUMP_REG_TYPE_MDIO] = HBG_REG_MDIO_BASE,
251 	[HBG_DUMP_REG_TYPE_GMAC] = HBG_REG_SGMII_BASE,
252 	[HBG_DUMP_REG_TYPE_PCU] = HBG_REG_SGMII_BASE,
253 };
254 
hbg_ethtool_get_regs_len(struct net_device * netdev)255 static int hbg_ethtool_get_regs_len(struct net_device *netdev)
256 {
257 	return ARRAY_SIZE(hbg_dump_reg_infos) * sizeof(struct hbg_reg_info);
258 }
259 
hbg_ethtool_get_regs(struct net_device * netdev,struct ethtool_regs * regs,void * data)260 static void hbg_ethtool_get_regs(struct net_device *netdev,
261 				 struct ethtool_regs *regs, void *data)
262 {
263 	struct hbg_priv *priv = netdev_priv(netdev);
264 	struct hbg_reg_info *info;
265 	u32 i, offset = 0;
266 
267 	regs->version = 0;
268 	for (i = 0; i < ARRAY_SIZE(hbg_dump_reg_infos); i++) {
269 		info = data + offset;
270 
271 		*info = hbg_dump_reg_infos[i];
272 		info->val = hbg_reg_read(priv, info->offset);
273 		info->offset -= hbg_dump_type_base_array[info->type];
274 
275 		offset += sizeof(*info);
276 	}
277 }
278 
hbg_ethtool_get_pauseparam(struct net_device * net_dev,struct ethtool_pauseparam * param)279 static void hbg_ethtool_get_pauseparam(struct net_device *net_dev,
280 				       struct ethtool_pauseparam *param)
281 {
282 	struct hbg_priv *priv = netdev_priv(net_dev);
283 
284 	param->autoneg = priv->mac.pause_autoneg;
285 	hbg_hw_get_pause_enable(priv, &param->tx_pause, &param->rx_pause);
286 }
287 
hbg_ethtool_set_pauseparam(struct net_device * net_dev,struct ethtool_pauseparam * param)288 static int hbg_ethtool_set_pauseparam(struct net_device *net_dev,
289 				      struct ethtool_pauseparam *param)
290 {
291 	struct hbg_priv *priv = netdev_priv(net_dev);
292 
293 	priv->mac.pause_autoneg = param->autoneg;
294 	phy_set_asym_pause(priv->mac.phydev, param->rx_pause, param->tx_pause);
295 
296 	if (!param->autoneg)
297 		hbg_hw_set_pause_enable(priv, param->tx_pause, param->rx_pause);
298 
299 	priv->user_def.pause_param = *param;
300 	return 0;
301 }
302 
hbg_ethtool_reset(struct net_device * netdev,u32 * flags)303 static int hbg_ethtool_reset(struct net_device *netdev, u32 *flags)
304 {
305 	struct hbg_priv *priv = netdev_priv(netdev);
306 
307 	if (*flags != ETH_RESET_DEDICATED)
308 		return -EOPNOTSUPP;
309 
310 	*flags = 0;
311 	return hbg_reset(priv);
312 }
313 
hbg_update_stats_by_info(struct hbg_priv * priv,const struct hbg_ethtool_stats * info,u32 info_len)314 static void hbg_update_stats_by_info(struct hbg_priv *priv,
315 				     const struct hbg_ethtool_stats *info,
316 				     u32 info_len)
317 {
318 	const struct hbg_ethtool_stats *stats;
319 	u32 i;
320 
321 	if (test_bit(HBG_NIC_STATE_RESETTING, &priv->state))
322 		return;
323 
324 	for (i = 0; i < info_len; i++) {
325 		stats = &info[i];
326 		if (!stats->reg)
327 			continue;
328 
329 		HBG_STATS_U(&priv->stats, stats->offset,
330 			    hbg_reg_read(priv, stats->reg));
331 	}
332 }
333 
hbg_update_stats(struct hbg_priv * priv)334 void hbg_update_stats(struct hbg_priv *priv)
335 {
336 	hbg_update_stats_by_info(priv, hbg_ethtool_stats_info,
337 				 ARRAY_SIZE(hbg_ethtool_stats_info));
338 	hbg_update_stats_by_info(priv, hbg_ethtool_rmon_stats_info,
339 				 ARRAY_SIZE(hbg_ethtool_rmon_stats_info));
340 	hbg_update_stats_by_info(priv, hbg_ethtool_mac_stats_info,
341 				 ARRAY_SIZE(hbg_ethtool_mac_stats_info));
342 	hbg_update_stats_by_info(priv, hbg_ethtool_ctrl_stats_info,
343 				 ARRAY_SIZE(hbg_ethtool_ctrl_stats_info));
344 }
345 
hbg_ethtool_get_sset_count(struct net_device * netdev,int stringset)346 static int hbg_ethtool_get_sset_count(struct net_device *netdev, int stringset)
347 {
348 	if (stringset != ETH_SS_STATS)
349 		return -EOPNOTSUPP;
350 
351 	return ARRAY_SIZE(hbg_ethtool_stats_info);
352 }
353 
hbg_ethtool_get_strings(struct net_device * netdev,u32 stringset,u8 * data)354 static void hbg_ethtool_get_strings(struct net_device *netdev,
355 				    u32 stringset, u8 *data)
356 {
357 	u32 i;
358 
359 	if (stringset != ETH_SS_STATS)
360 		return;
361 
362 	for (i = 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++)
363 		ethtool_puts(&data, hbg_ethtool_stats_info[i].name);
364 }
365 
hbg_ethtool_get_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)366 static void hbg_ethtool_get_stats(struct net_device *netdev,
367 				  struct ethtool_stats *stats, u64 *data)
368 {
369 	struct hbg_priv *priv = netdev_priv(netdev);
370 	u32 i;
371 
372 	hbg_update_stats(priv);
373 	for (i = 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++)
374 		*data++ = HBG_STATS_R(&priv->stats,
375 				      hbg_ethtool_stats_info[i].offset);
376 }
377 
hbg_ethtool_get_pause_stats(struct net_device * netdev,struct ethtool_pause_stats * epstats)378 static void hbg_ethtool_get_pause_stats(struct net_device *netdev,
379 					struct ethtool_pause_stats *epstats)
380 {
381 	struct hbg_priv *priv = netdev_priv(netdev);
382 	struct hbg_stats *stats = &priv->stats;
383 
384 	hbg_update_stats(priv);
385 	epstats->rx_pause_frames = stats->rx_pause_macctl_frame_cnt;
386 	epstats->tx_pause_frames = stats->tx_pause_frame_cnt;
387 }
388 
hbg_ethtool_get_eth_mac_stats(struct net_device * netdev,struct ethtool_eth_mac_stats * emstats)389 static void hbg_ethtool_get_eth_mac_stats(struct net_device *netdev,
390 					  struct ethtool_eth_mac_stats *emstats)
391 {
392 	struct hbg_priv *priv = netdev_priv(netdev);
393 	struct hbg_stats *stats = &priv->stats;
394 
395 	hbg_update_stats(priv);
396 	emstats->FramesTransmittedOK = stats->tx_trans_pkt_cnt;
397 	emstats->FramesReceivedOK = stats->rx_trans_pkt_cnt;
398 	emstats->FrameCheckSequenceErrors = stats->rx_fcs_error_cnt;
399 	emstats->AlignmentErrors = stats->rx_align_error_cnt;
400 	emstats->OctetsTransmittedOK = stats->tx_octets_total_ok_cnt;
401 	emstats->OctetsReceivedOK = stats->rx_octets_total_ok_cnt;
402 
403 	emstats->MulticastFramesXmittedOK = stats->tx_mc_pkt_cnt;
404 	emstats->BroadcastFramesXmittedOK = stats->tx_bc_pkt_cnt;
405 	emstats->MulticastFramesReceivedOK = stats->rx_mc_pkt_cnt;
406 	emstats->BroadcastFramesReceivedOK = stats->rx_bc_pkt_cnt;
407 	emstats->InRangeLengthErrors = stats->rx_fcs_error_cnt +
408 				       stats->rx_jabber_err_cnt +
409 				       stats->rx_unknown_macctl_frame_cnt +
410 				       stats->rx_bufrq_err_cnt +
411 				       stats->rx_we_err_cnt;
412 	emstats->OutOfRangeLengthField = stats->rx_frame_short_err_cnt +
413 					 stats->rx_frame_runt_err_cnt +
414 					 stats->rx_lengthfield_err_cnt +
415 					 stats->rx_frame_long_err_cnt +
416 					 stats->rx_frame_very_long_err_cnt;
417 	emstats->FrameTooLongErrors = stats->rx_frame_long_err_cnt +
418 				      stats->rx_frame_very_long_err_cnt;
419 }
420 
421 static void
hbg_ethtool_get_eth_ctrl_stats(struct net_device * netdev,struct ethtool_eth_ctrl_stats * ecstats)422 hbg_ethtool_get_eth_ctrl_stats(struct net_device *netdev,
423 			       struct ethtool_eth_ctrl_stats *ecstats)
424 {
425 	struct hbg_priv *priv = netdev_priv(netdev);
426 	struct hbg_stats *s = &priv->stats;
427 
428 	hbg_update_stats(priv);
429 	ecstats->MACControlFramesTransmitted = s->tx_pause_frame_cnt;
430 	ecstats->MACControlFramesReceived = s->rx_pause_macctl_frame_cnt;
431 	ecstats->UnsupportedOpcodesReceived = s->rx_unknown_macctl_frame_cnt;
432 }
433 
434 static const struct ethtool_rmon_hist_range hbg_rmon_ranges[] = {
435 	{    0,    64 },
436 	{   65,   127 },
437 	{  128,   255 },
438 	{  256,   511 },
439 	{  512,  1023 },
440 	{ 1024,  1518 },
441 	{ 1519,  4095 },
442 };
443 
444 static void
hbg_ethtool_get_rmon_stats(struct net_device * netdev,struct ethtool_rmon_stats * rmon_stats,const struct ethtool_rmon_hist_range ** ranges)445 hbg_ethtool_get_rmon_stats(struct net_device *netdev,
446 			   struct ethtool_rmon_stats *rmon_stats,
447 			   const struct ethtool_rmon_hist_range **ranges)
448 {
449 	struct hbg_priv *priv = netdev_priv(netdev);
450 	struct hbg_stats *stats = &priv->stats;
451 
452 	hbg_update_stats(priv);
453 	rmon_stats->undersize_pkts = stats->rx_frame_short_err_cnt +
454 				     stats->rx_frame_runt_err_cnt +
455 				     stats->rx_lengthfield_err_cnt;
456 	rmon_stats->oversize_pkts = stats->rx_frame_long_err_cnt +
457 				    stats->rx_frame_very_long_err_cnt;
458 	rmon_stats->fragments = stats->rx_desc_frag_cnt;
459 	rmon_stats->hist[0] = stats->rx_framesize_64;
460 	rmon_stats->hist[1] = stats->rx_framesize_65_127;
461 	rmon_stats->hist[2] = stats->rx_framesize_128_255;
462 	rmon_stats->hist[3] = stats->rx_framesize_256_511;
463 	rmon_stats->hist[4] = stats->rx_framesize_512_1023;
464 	rmon_stats->hist[5] = stats->rx_framesize_1024_1518;
465 	rmon_stats->hist[6] = stats->rx_framesize_bt_1518;
466 
467 	rmon_stats->hist_tx[0] = stats->tx_framesize_64;
468 	rmon_stats->hist_tx[1] = stats->tx_framesize_65_127;
469 	rmon_stats->hist_tx[2] = stats->tx_framesize_128_255;
470 	rmon_stats->hist_tx[3] = stats->tx_framesize_256_511;
471 	rmon_stats->hist_tx[4] = stats->tx_framesize_512_1023;
472 	rmon_stats->hist_tx[5] = stats->tx_framesize_1024_1518;
473 	rmon_stats->hist_tx[6] = stats->tx_framesize_bt_1518;
474 
475 	*ranges = hbg_rmon_ranges;
476 }
477 
478 static const struct ethtool_ops hbg_ethtool_ops = {
479 	.get_link		= ethtool_op_get_link,
480 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
481 	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
482 	.get_regs_len		= hbg_ethtool_get_regs_len,
483 	.get_regs		= hbg_ethtool_get_regs,
484 	.get_pauseparam         = hbg_ethtool_get_pauseparam,
485 	.set_pauseparam         = hbg_ethtool_set_pauseparam,
486 	.reset			= hbg_ethtool_reset,
487 	.nway_reset		= phy_ethtool_nway_reset,
488 	.get_sset_count		= hbg_ethtool_get_sset_count,
489 	.get_strings		= hbg_ethtool_get_strings,
490 	.get_ethtool_stats	= hbg_ethtool_get_stats,
491 	.get_pause_stats	= hbg_ethtool_get_pause_stats,
492 	.get_eth_mac_stats	= hbg_ethtool_get_eth_mac_stats,
493 	.get_eth_ctrl_stats	= hbg_ethtool_get_eth_ctrl_stats,
494 	.get_rmon_stats		= hbg_ethtool_get_rmon_stats,
495 };
496 
hbg_ethtool_set_ops(struct net_device * netdev)497 void hbg_ethtool_set_ops(struct net_device *netdev)
498 {
499 	netdev->ethtool_ops = &hbg_ethtool_ops;
500 }
501