1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
3  *
4  * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
5  */
6 
7 #include <linux/ethtool.h>
8 
9 #include "sparx5_main_regs.h"
10 #include "sparx5_main.h"
11 #include "sparx5_port.h"
12 
13 /* Index of ANA_AC port counters */
14 #define SPX5_PORT_POLICER_DROPS 0
15 
16 /* Add a potentially wrapping 32 bit value to a 64 bit counter */
17 static void sparx5_update_counter(u64 *cnt, u32 val)
18 {
19 	if (val < (*cnt & U32_MAX))
20 		*cnt += (u64)1 << 32; /* value has wrapped */
21 	*cnt = (*cnt & ~(u64)U32_MAX) + val;
22 }
23 
24 enum sparx5_stats_entry {
25 	spx5_stats_rx_symbol_err_cnt = 0,
26 	spx5_stats_pmac_rx_symbol_err_cnt = 1,
27 	spx5_stats_tx_uc_cnt = 2,
28 	spx5_stats_pmac_tx_uc_cnt = 3,
29 	spx5_stats_tx_mc_cnt = 4,
30 	spx5_stats_tx_bc_cnt = 5,
31 	spx5_stats_tx_backoff1_cnt = 6,
32 	spx5_stats_tx_multi_coll_cnt = 7,
33 	spx5_stats_rx_uc_cnt = 8,
34 	spx5_stats_pmac_rx_uc_cnt = 9,
35 	spx5_stats_rx_mc_cnt = 10,
36 	spx5_stats_rx_bc_cnt = 11,
37 	spx5_stats_rx_crc_err_cnt = 12,
38 	spx5_stats_pmac_rx_crc_err_cnt = 13,
39 	spx5_stats_rx_alignment_lost_cnt = 14,
40 	spx5_stats_pmac_rx_alignment_lost_cnt = 15,
41 	spx5_stats_tx_ok_bytes_cnt = 16,
42 	spx5_stats_pmac_tx_ok_bytes_cnt = 17,
43 	spx5_stats_tx_defer_cnt = 18,
44 	spx5_stats_tx_late_coll_cnt = 19,
45 	spx5_stats_tx_xcoll_cnt = 20,
46 	spx5_stats_tx_csense_cnt = 21,
47 	spx5_stats_rx_ok_bytes_cnt = 22,
48 	spx5_stats_pmac_rx_ok_bytes_cnt = 23,
49 	spx5_stats_pmac_tx_mc_cnt = 24,
50 	spx5_stats_pmac_tx_bc_cnt = 25,
51 	spx5_stats_tx_xdefer_cnt = 26,
52 	spx5_stats_pmac_rx_mc_cnt = 27,
53 	spx5_stats_pmac_rx_bc_cnt = 28,
54 	spx5_stats_rx_in_range_len_err_cnt = 29,
55 	spx5_stats_pmac_rx_in_range_len_err_cnt = 30,
56 	spx5_stats_rx_out_of_range_len_err_cnt = 31,
57 	spx5_stats_pmac_rx_out_of_range_len_err_cnt = 32,
58 	spx5_stats_rx_oversize_cnt = 33,
59 	spx5_stats_pmac_rx_oversize_cnt = 34,
60 	spx5_stats_tx_pause_cnt = 35,
61 	spx5_stats_pmac_tx_pause_cnt = 36,
62 	spx5_stats_rx_pause_cnt = 37,
63 	spx5_stats_pmac_rx_pause_cnt = 38,
64 	spx5_stats_rx_unsup_opcode_cnt = 39,
65 	spx5_stats_pmac_rx_unsup_opcode_cnt = 40,
66 	spx5_stats_rx_undersize_cnt = 41,
67 	spx5_stats_pmac_rx_undersize_cnt = 42,
68 	spx5_stats_rx_fragments_cnt = 43,
69 	spx5_stats_pmac_rx_fragments_cnt = 44,
70 	spx5_stats_rx_jabbers_cnt = 45,
71 	spx5_stats_pmac_rx_jabbers_cnt = 46,
72 	spx5_stats_rx_size64_cnt = 47,
73 	spx5_stats_pmac_rx_size64_cnt = 48,
74 	spx5_stats_rx_size65to127_cnt = 49,
75 	spx5_stats_pmac_rx_size65to127_cnt = 50,
76 	spx5_stats_rx_size128to255_cnt = 51,
77 	spx5_stats_pmac_rx_size128to255_cnt = 52,
78 	spx5_stats_rx_size256to511_cnt = 53,
79 	spx5_stats_pmac_rx_size256to511_cnt = 54,
80 	spx5_stats_rx_size512to1023_cnt = 55,
81 	spx5_stats_pmac_rx_size512to1023_cnt = 56,
82 	spx5_stats_rx_size1024to1518_cnt = 57,
83 	spx5_stats_pmac_rx_size1024to1518_cnt = 58,
84 	spx5_stats_rx_size1519tomax_cnt = 59,
85 	spx5_stats_pmac_rx_size1519tomax_cnt = 60,
86 	spx5_stats_tx_size64_cnt = 61,
87 	spx5_stats_pmac_tx_size64_cnt = 62,
88 	spx5_stats_tx_size65to127_cnt = 63,
89 	spx5_stats_pmac_tx_size65to127_cnt = 64,
90 	spx5_stats_tx_size128to255_cnt = 65,
91 	spx5_stats_pmac_tx_size128to255_cnt = 66,
92 	spx5_stats_tx_size256to511_cnt = 67,
93 	spx5_stats_pmac_tx_size256to511_cnt = 68,
94 	spx5_stats_tx_size512to1023_cnt = 69,
95 	spx5_stats_pmac_tx_size512to1023_cnt = 70,
96 	spx5_stats_tx_size1024to1518_cnt = 71,
97 	spx5_stats_pmac_tx_size1024to1518_cnt = 72,
98 	spx5_stats_tx_size1519tomax_cnt = 73,
99 	spx5_stats_pmac_tx_size1519tomax_cnt = 74,
100 	spx5_stats_mm_rx_assembly_err_cnt = 75,
101 	spx5_stats_mm_rx_assembly_ok_cnt = 76,
102 	spx5_stats_mm_rx_merge_frag_cnt = 77,
103 	spx5_stats_mm_rx_smd_err_cnt = 78,
104 	spx5_stats_mm_tx_pfragment_cnt = 79,
105 	spx5_stats_rx_bad_bytes_cnt = 80,
106 	spx5_stats_pmac_rx_bad_bytes_cnt = 81,
107 	spx5_stats_rx_in_bytes_cnt = 82,
108 	spx5_stats_rx_ipg_shrink_cnt = 83,
109 	spx5_stats_rx_sync_lost_err_cnt = 84,
110 	spx5_stats_rx_tagged_frms_cnt = 85,
111 	spx5_stats_rx_untagged_frms_cnt = 86,
112 	spx5_stats_tx_out_bytes_cnt = 87,
113 	spx5_stats_tx_tagged_frms_cnt = 88,
114 	spx5_stats_tx_untagged_frms_cnt = 89,
115 	spx5_stats_rx_hih_cksm_err_cnt = 90,
116 	spx5_stats_pmac_rx_hih_cksm_err_cnt = 91,
117 	spx5_stats_rx_xgmii_prot_err_cnt = 92,
118 	spx5_stats_pmac_rx_xgmii_prot_err_cnt = 93,
119 	spx5_stats_ana_ac_port_stat_lsb_cnt = 94,
120 	spx5_stats_green_p0_rx_fwd = 95,
121 	spx5_stats_green_p0_rx_port_drop = 111,
122 	spx5_stats_green_p0_tx_port = 127,
123 	spx5_stats_rx_local_drop = 143,
124 	spx5_stats_tx_local_drop = 144,
125 	spx5_stats_count = 145,
126 };
127 
128 static const char *const sparx5_stats_layout[] = {
129 	"mm_rx_assembly_err_cnt",
130 	"mm_rx_assembly_ok_cnt",
131 	"mm_rx_merge_frag_cnt",
132 	"mm_rx_smd_err_cnt",
133 	"mm_tx_pfragment_cnt",
134 	"rx_bad_bytes_cnt",
135 	"pmac_rx_bad_bytes_cnt",
136 	"rx_in_bytes_cnt",
137 	"rx_ipg_shrink_cnt",
138 	"rx_sync_lost_err_cnt",
139 	"rx_tagged_frms_cnt",
140 	"rx_untagged_frms_cnt",
141 	"tx_out_bytes_cnt",
142 	"tx_tagged_frms_cnt",
143 	"tx_untagged_frms_cnt",
144 	"rx_hih_cksm_err_cnt",
145 	"pmac_rx_hih_cksm_err_cnt",
146 	"rx_xgmii_prot_err_cnt",
147 	"pmac_rx_xgmii_prot_err_cnt",
148 	"rx_port_policer_drop",
149 	"rx_fwd_green_p0",
150 	"rx_fwd_green_p1",
151 	"rx_fwd_green_p2",
152 	"rx_fwd_green_p3",
153 	"rx_fwd_green_p4",
154 	"rx_fwd_green_p5",
155 	"rx_fwd_green_p6",
156 	"rx_fwd_green_p7",
157 	"rx_fwd_yellow_p0",
158 	"rx_fwd_yellow_p1",
159 	"rx_fwd_yellow_p2",
160 	"rx_fwd_yellow_p3",
161 	"rx_fwd_yellow_p4",
162 	"rx_fwd_yellow_p5",
163 	"rx_fwd_yellow_p6",
164 	"rx_fwd_yellow_p7",
165 	"rx_port_drop_green_p0",
166 	"rx_port_drop_green_p1",
167 	"rx_port_drop_green_p2",
168 	"rx_port_drop_green_p3",
169 	"rx_port_drop_green_p4",
170 	"rx_port_drop_green_p5",
171 	"rx_port_drop_green_p6",
172 	"rx_port_drop_green_p7",
173 	"rx_port_drop_yellow_p0",
174 	"rx_port_drop_yellow_p1",
175 	"rx_port_drop_yellow_p2",
176 	"rx_port_drop_yellow_p3",
177 	"rx_port_drop_yellow_p4",
178 	"rx_port_drop_yellow_p5",
179 	"rx_port_drop_yellow_p6",
180 	"rx_port_drop_yellow_p7",
181 	"tx_port_green_p0",
182 	"tx_port_green_p1",
183 	"tx_port_green_p2",
184 	"tx_port_green_p3",
185 	"tx_port_green_p4",
186 	"tx_port_green_p5",
187 	"tx_port_green_p6",
188 	"tx_port_green_p7",
189 	"tx_port_yellow_p0",
190 	"tx_port_yellow_p1",
191 	"tx_port_yellow_p2",
192 	"tx_port_yellow_p3",
193 	"tx_port_yellow_p4",
194 	"tx_port_yellow_p5",
195 	"tx_port_yellow_p6",
196 	"tx_port_yellow_p7",
197 	"rx_local_drop",
198 	"tx_local_drop",
199 };
200 
201 static void sparx5_get_queue_sys_stats(struct sparx5 *sparx5, int portno)
202 {
203 	u64 *portstats;
204 	u64 *stats;
205 	u32 addr;
206 	int idx;
207 
208 	portstats = &sparx5->stats[portno * sparx5->num_stats];
209 	mutex_lock(&sparx5->queue_stats_lock);
210 	spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno), sparx5, XQS_STAT_CFG);
211 	addr = 0;
212 	stats = &portstats[spx5_stats_green_p0_rx_fwd];
213 	for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats)
214 		sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr)));
215 	addr = 16;
216 	stats = &portstats[spx5_stats_green_p0_rx_port_drop];
217 	for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats)
218 		sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr)));
219 	addr = 256;
220 	stats = &portstats[spx5_stats_green_p0_tx_port];
221 	for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats)
222 		sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr)));
223 	sparx5_update_counter(&portstats[spx5_stats_rx_local_drop],
224 			      spx5_rd(sparx5, XQS_CNT(32)));
225 	sparx5_update_counter(&portstats[spx5_stats_tx_local_drop],
226 			      spx5_rd(sparx5, XQS_CNT(272)));
227 	mutex_unlock(&sparx5->queue_stats_lock);
228 }
229 
230 static void sparx5_get_ana_ac_stats_stats(struct sparx5 *sparx5, int portno)
231 {
232 	u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
233 
234 	sparx5_update_counter(&portstats[spx5_stats_ana_ac_port_stat_lsb_cnt],
235 			      spx5_rd(sparx5, ANA_AC_PORT_STAT_LSB_CNT(portno,
236 								       SPX5_PORT_POLICER_DROPS)));
237 }
238 
239 static void sparx5_get_dev_phy_stats(u64 *portstats, void __iomem *inst, u32
240 				     tinst)
241 {
242 	sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err_cnt],
243 			      spx5_inst_rd(inst,
244 					   DEV5G_RX_SYMBOL_ERR_CNT(tinst)));
245 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err_cnt],
246 			      spx5_inst_rd(inst,
247 					   DEV5G_PMAC_RX_SYMBOL_ERR_CNT(tinst)));
248 }
249 
250 static void sparx5_get_dev_mac_stats(u64 *portstats, void __iomem *inst, u32
251 				     tinst)
252 {
253 	sparx5_update_counter(&portstats[spx5_stats_tx_uc_cnt],
254 			      spx5_inst_rd(inst, DEV5G_TX_UC_CNT(tinst)));
255 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_uc_cnt],
256 			      spx5_inst_rd(inst, DEV5G_PMAC_TX_UC_CNT(tinst)));
257 	sparx5_update_counter(&portstats[spx5_stats_tx_mc_cnt],
258 			      spx5_inst_rd(inst, DEV5G_TX_MC_CNT(tinst)));
259 	sparx5_update_counter(&portstats[spx5_stats_tx_bc_cnt],
260 			      spx5_inst_rd(inst, DEV5G_TX_BC_CNT(tinst)));
261 	sparx5_update_counter(&portstats[spx5_stats_rx_uc_cnt],
262 			      spx5_inst_rd(inst, DEV5G_RX_UC_CNT(tinst)));
263 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_uc_cnt],
264 			      spx5_inst_rd(inst, DEV5G_PMAC_RX_UC_CNT(tinst)));
265 	sparx5_update_counter(&portstats[spx5_stats_rx_mc_cnt],
266 			      spx5_inst_rd(inst, DEV5G_RX_MC_CNT(tinst)));
267 	sparx5_update_counter(&portstats[spx5_stats_rx_bc_cnt],
268 			      spx5_inst_rd(inst, DEV5G_RX_BC_CNT(tinst)));
269 	sparx5_update_counter(&portstats[spx5_stats_rx_crc_err_cnt],
270 			      spx5_inst_rd(inst, DEV5G_RX_CRC_ERR_CNT(tinst)));
271 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err_cnt],
272 			      spx5_inst_rd(inst,
273 					   DEV5G_PMAC_RX_CRC_ERR_CNT(tinst)));
274 	sparx5_update_counter(&portstats[spx5_stats_rx_alignment_lost_cnt],
275 			      spx5_inst_rd(inst,
276 					   DEV5G_RX_ALIGNMENT_LOST_CNT(tinst)));
277 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_alignment_lost_cnt],
278 			      spx5_inst_rd(inst,
279 					   DEV5G_PMAC_RX_ALIGNMENT_LOST_CNT(tinst)));
280 	sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes_cnt],
281 			      spx5_inst_rd(inst, DEV5G_TX_OK_BYTES_CNT(tinst)));
282 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes_cnt],
283 			      spx5_inst_rd(inst,
284 					   DEV5G_PMAC_TX_OK_BYTES_CNT(tinst)));
285 	sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes_cnt],
286 			      spx5_inst_rd(inst, DEV5G_RX_OK_BYTES_CNT(tinst)));
287 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes_cnt],
288 			      spx5_inst_rd(inst,
289 					   DEV5G_PMAC_RX_OK_BYTES_CNT(tinst)));
290 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_mc_cnt],
291 			      spx5_inst_rd(inst, DEV5G_PMAC_TX_MC_CNT(tinst)));
292 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_bc_cnt],
293 			      spx5_inst_rd(inst, DEV5G_PMAC_TX_BC_CNT(tinst)));
294 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_mc_cnt],
295 			      spx5_inst_rd(inst, DEV5G_PMAC_RX_MC_CNT(tinst)));
296 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bc_cnt],
297 			      spx5_inst_rd(inst, DEV5G_PMAC_RX_BC_CNT(tinst)));
298 	sparx5_update_counter(&portstats[spx5_stats_rx_in_range_len_err_cnt],
299 			      spx5_inst_rd(inst,
300 					   DEV5G_RX_IN_RANGE_LEN_ERR_CNT(tinst)));
301 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_in_range_len_err_cnt],
302 			      spx5_inst_rd(inst,
303 					   DEV5G_PMAC_RX_IN_RANGE_LEN_ERR_CNT(tinst)));
304 	sparx5_update_counter(&portstats[spx5_stats_rx_out_of_range_len_err_cnt],
305 			      spx5_inst_rd(inst,
306 					   DEV5G_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst)));
307 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt],
308 			      spx5_inst_rd(inst,
309 					   DEV5G_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst)));
310 	sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
311 			      spx5_inst_rd(inst, DEV5G_RX_OVERSIZE_CNT(tinst)));
312 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
313 			      spx5_inst_rd(inst,
314 					   DEV5G_PMAC_RX_OVERSIZE_CNT(tinst)));
315 }
316 
317 static void sparx5_get_dev_mac_ctrl_stats(u64 *portstats, void __iomem *inst,
318 					  u32 tinst)
319 {
320 	sparx5_update_counter(&portstats[spx5_stats_tx_pause_cnt],
321 			      spx5_inst_rd(inst, DEV5G_TX_PAUSE_CNT(tinst)));
322 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause_cnt],
323 			      spx5_inst_rd(inst,
324 					   DEV5G_PMAC_TX_PAUSE_CNT(tinst)));
325 	sparx5_update_counter(&portstats[spx5_stats_rx_pause_cnt],
326 			      spx5_inst_rd(inst, DEV5G_RX_PAUSE_CNT(tinst)));
327 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause_cnt],
328 			      spx5_inst_rd(inst,
329 					   DEV5G_PMAC_RX_PAUSE_CNT(tinst)));
330 	sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode_cnt],
331 			      spx5_inst_rd(inst,
332 					   DEV5G_RX_UNSUP_OPCODE_CNT(tinst)));
333 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode_cnt],
334 			      spx5_inst_rd(inst,
335 					   DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(tinst)));
336 }
337 
338 static void sparx5_get_dev_rmon_stats(u64 *portstats, void __iomem *inst, u32
339 				      tinst)
340 {
341 	sparx5_update_counter(&portstats[spx5_stats_rx_undersize_cnt],
342 			      spx5_inst_rd(inst,
343 					   DEV5G_RX_UNDERSIZE_CNT(tinst)));
344 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize_cnt],
345 			      spx5_inst_rd(inst,
346 					   DEV5G_PMAC_RX_UNDERSIZE_CNT(tinst)));
347 	sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
348 			      spx5_inst_rd(inst, DEV5G_RX_OVERSIZE_CNT(tinst)));
349 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
350 			      spx5_inst_rd(inst,
351 					   DEV5G_PMAC_RX_OVERSIZE_CNT(tinst)));
352 	sparx5_update_counter(&portstats[spx5_stats_rx_fragments_cnt],
353 			      spx5_inst_rd(inst,
354 					   DEV5G_RX_FRAGMENTS_CNT(tinst)));
355 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments_cnt],
356 			      spx5_inst_rd(inst,
357 					   DEV5G_PMAC_RX_FRAGMENTS_CNT(tinst)));
358 	sparx5_update_counter(&portstats[spx5_stats_rx_jabbers_cnt],
359 			      spx5_inst_rd(inst, DEV5G_RX_JABBERS_CNT(tinst)));
360 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers_cnt],
361 			      spx5_inst_rd(inst,
362 					   DEV5G_PMAC_RX_JABBERS_CNT(tinst)));
363 	sparx5_update_counter(&portstats[spx5_stats_rx_size64_cnt],
364 			      spx5_inst_rd(inst, DEV5G_RX_SIZE64_CNT(tinst)));
365 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64_cnt],
366 			      spx5_inst_rd(inst,
367 					   DEV5G_PMAC_RX_SIZE64_CNT(tinst)));
368 	sparx5_update_counter(&portstats[spx5_stats_rx_size65to127_cnt],
369 			      spx5_inst_rd(inst,
370 					   DEV5G_RX_SIZE65TO127_CNT(tinst)));
371 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65to127_cnt],
372 			      spx5_inst_rd(inst,
373 					   DEV5G_PMAC_RX_SIZE65TO127_CNT(tinst)));
374 	sparx5_update_counter(&portstats[spx5_stats_rx_size128to255_cnt],
375 			      spx5_inst_rd(inst,
376 					   DEV5G_RX_SIZE128TO255_CNT(tinst)));
377 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128to255_cnt],
378 			      spx5_inst_rd(inst,
379 					   DEV5G_PMAC_RX_SIZE128TO255_CNT(tinst)));
380 	sparx5_update_counter(&portstats[spx5_stats_rx_size256to511_cnt],
381 			      spx5_inst_rd(inst,
382 					   DEV5G_RX_SIZE256TO511_CNT(tinst)));
383 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256to511_cnt],
384 			      spx5_inst_rd(inst,
385 					   DEV5G_PMAC_RX_SIZE256TO511_CNT(tinst)));
386 	sparx5_update_counter(&portstats[spx5_stats_rx_size512to1023_cnt],
387 			      spx5_inst_rd(inst,
388 					   DEV5G_RX_SIZE512TO1023_CNT(tinst)));
389 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512to1023_cnt],
390 			      spx5_inst_rd(inst,
391 					   DEV5G_PMAC_RX_SIZE512TO1023_CNT(tinst)));
392 	sparx5_update_counter(&portstats[spx5_stats_rx_size1024to1518_cnt],
393 			      spx5_inst_rd(inst,
394 					   DEV5G_RX_SIZE1024TO1518_CNT(tinst)));
395 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024to1518_cnt],
396 			      spx5_inst_rd(inst,
397 					   DEV5G_PMAC_RX_SIZE1024TO1518_CNT(tinst)));
398 	sparx5_update_counter(&portstats[spx5_stats_rx_size1519tomax_cnt],
399 			      spx5_inst_rd(inst,
400 					   DEV5G_RX_SIZE1519TOMAX_CNT(tinst)));
401 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519tomax_cnt],
402 			      spx5_inst_rd(inst,
403 					   DEV5G_PMAC_RX_SIZE1519TOMAX_CNT(tinst)));
404 	sparx5_update_counter(&portstats[spx5_stats_tx_size64_cnt],
405 			      spx5_inst_rd(inst, DEV5G_TX_SIZE64_CNT(tinst)));
406 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64_cnt],
407 			      spx5_inst_rd(inst,
408 					   DEV5G_PMAC_TX_SIZE64_CNT(tinst)));
409 	sparx5_update_counter(&portstats[spx5_stats_tx_size65to127_cnt],
410 			      spx5_inst_rd(inst,
411 					   DEV5G_TX_SIZE65TO127_CNT(tinst)));
412 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65to127_cnt],
413 			      spx5_inst_rd(inst,
414 					   DEV5G_PMAC_TX_SIZE65TO127_CNT(tinst)));
415 	sparx5_update_counter(&portstats[spx5_stats_tx_size128to255_cnt],
416 			      spx5_inst_rd(inst,
417 					   DEV5G_TX_SIZE128TO255_CNT(tinst)));
418 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128to255_cnt],
419 			      spx5_inst_rd(inst,
420 					   DEV5G_PMAC_TX_SIZE128TO255_CNT(tinst)));
421 	sparx5_update_counter(&portstats[spx5_stats_tx_size256to511_cnt],
422 			      spx5_inst_rd(inst,
423 					   DEV5G_TX_SIZE256TO511_CNT(tinst)));
424 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256to511_cnt],
425 			      spx5_inst_rd(inst,
426 					   DEV5G_PMAC_TX_SIZE256TO511_CNT(tinst)));
427 	sparx5_update_counter(&portstats[spx5_stats_tx_size512to1023_cnt],
428 			      spx5_inst_rd(inst,
429 					   DEV5G_TX_SIZE512TO1023_CNT(tinst)));
430 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512to1023_cnt],
431 			      spx5_inst_rd(inst,
432 					   DEV5G_PMAC_TX_SIZE512TO1023_CNT(tinst)));
433 	sparx5_update_counter(&portstats[spx5_stats_tx_size1024to1518_cnt],
434 			      spx5_inst_rd(inst,
435 					   DEV5G_TX_SIZE1024TO1518_CNT(tinst)));
436 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024to1518_cnt],
437 			      spx5_inst_rd(inst,
438 					   DEV5G_PMAC_TX_SIZE1024TO1518_CNT(tinst)));
439 	sparx5_update_counter(&portstats[spx5_stats_tx_size1519tomax_cnt],
440 			      spx5_inst_rd(inst,
441 					   DEV5G_TX_SIZE1519TOMAX_CNT(tinst)));
442 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519tomax_cnt],
443 			      spx5_inst_rd(inst,
444 					   DEV5G_PMAC_TX_SIZE1519TOMAX_CNT(tinst)));
445 }
446 
447 static void sparx5_get_dev_misc_stats(u64 *portstats, void __iomem *inst, u32
448 				      tinst)
449 {
450 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_err_cnt],
451 			      spx5_inst_rd(inst,
452 					   DEV5G_MM_RX_ASSEMBLY_ERR_CNT(tinst)));
453 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_ok_cnt],
454 			      spx5_inst_rd(inst,
455 					   DEV5G_MM_RX_ASSEMBLY_OK_CNT(tinst)));
456 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_merge_frag_cnt],
457 			      spx5_inst_rd(inst,
458 					   DEV5G_MM_RX_MERGE_FRAG_CNT(tinst)));
459 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_smd_err_cnt],
460 			      spx5_inst_rd(inst,
461 					   DEV5G_MM_RX_SMD_ERR_CNT(tinst)));
462 	sparx5_update_counter(&portstats[spx5_stats_mm_tx_pfragment_cnt],
463 			      spx5_inst_rd(inst,
464 					   DEV5G_MM_TX_PFRAGMENT_CNT(tinst)));
465 	sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes_cnt],
466 			      spx5_inst_rd(inst,
467 					   DEV5G_RX_BAD_BYTES_CNT(tinst)));
468 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes_cnt],
469 			      spx5_inst_rd(inst,
470 					   DEV5G_PMAC_RX_BAD_BYTES_CNT(tinst)));
471 	sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes_cnt],
472 			      spx5_inst_rd(inst, DEV5G_RX_IN_BYTES_CNT(tinst)));
473 	sparx5_update_counter(&portstats[spx5_stats_rx_ipg_shrink_cnt],
474 			      spx5_inst_rd(inst,
475 					   DEV5G_RX_IPG_SHRINK_CNT(tinst)));
476 	sparx5_update_counter(&portstats[spx5_stats_rx_tagged_frms_cnt],
477 			      spx5_inst_rd(inst,
478 					   DEV5G_RX_TAGGED_FRMS_CNT(tinst)));
479 	sparx5_update_counter(&portstats[spx5_stats_rx_untagged_frms_cnt],
480 			      spx5_inst_rd(inst,
481 					   DEV5G_RX_UNTAGGED_FRMS_CNT(tinst)));
482 	sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes_cnt],
483 			      spx5_inst_rd(inst,
484 					   DEV5G_TX_OUT_BYTES_CNT(tinst)));
485 	sparx5_update_counter(&portstats[spx5_stats_tx_tagged_frms_cnt],
486 			      spx5_inst_rd(inst,
487 					   DEV5G_TX_TAGGED_FRMS_CNT(tinst)));
488 	sparx5_update_counter(&portstats[spx5_stats_tx_untagged_frms_cnt],
489 			      spx5_inst_rd(inst,
490 					   DEV5G_TX_UNTAGGED_FRMS_CNT(tinst)));
491 	sparx5_update_counter(&portstats[spx5_stats_rx_hih_cksm_err_cnt],
492 			      spx5_inst_rd(inst,
493 					   DEV5G_RX_HIH_CKSM_ERR_CNT(tinst)));
494 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_hih_cksm_err_cnt],
495 			      spx5_inst_rd(inst,
496 					   DEV5G_PMAC_RX_HIH_CKSM_ERR_CNT(tinst)));
497 	sparx5_update_counter(&portstats[spx5_stats_rx_xgmii_prot_err_cnt],
498 			      spx5_inst_rd(inst,
499 					   DEV5G_RX_XGMII_PROT_ERR_CNT(tinst)));
500 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_xgmii_prot_err_cnt],
501 			      spx5_inst_rd(inst,
502 					   DEV5G_PMAC_RX_XGMII_PROT_ERR_CNT(tinst)));
503 }
504 
505 static void sparx5_get_device_stats(struct sparx5 *sparx5, int portno)
506 {
507 	u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
508 	u32 tinst = sparx5_port_dev_index(portno);
509 	u32 dev = sparx5_to_high_dev(portno);
510 	void __iomem *inst;
511 
512 	inst = spx5_inst_get(sparx5, dev, tinst);
513 	sparx5_get_dev_phy_stats(portstats, inst, tinst);
514 	sparx5_get_dev_mac_stats(portstats, inst, tinst);
515 	sparx5_get_dev_mac_ctrl_stats(portstats, inst, tinst);
516 	sparx5_get_dev_rmon_stats(portstats, inst, tinst);
517 	sparx5_get_dev_misc_stats(portstats, inst, tinst);
518 }
519 
520 static void sparx5_get_asm_phy_stats(u64 *portstats, void __iomem *inst, int
521 				     portno)
522 {
523 	sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err_cnt],
524 			      spx5_inst_rd(inst,
525 					   ASM_RX_SYMBOL_ERR_CNT(portno)));
526 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err_cnt],
527 			      spx5_inst_rd(inst,
528 					   ASM_PMAC_RX_SYMBOL_ERR_CNT(portno)));
529 }
530 
531 static void sparx5_get_asm_mac_stats(u64 *portstats, void __iomem *inst, int
532 				     portno)
533 {
534 	sparx5_update_counter(&portstats[spx5_stats_tx_uc_cnt],
535 			      spx5_inst_rd(inst, ASM_TX_UC_CNT(portno)));
536 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_uc_cnt],
537 			      spx5_inst_rd(inst, ASM_PMAC_TX_UC_CNT(portno)));
538 	sparx5_update_counter(&portstats[spx5_stats_tx_mc_cnt],
539 			      spx5_inst_rd(inst, ASM_TX_MC_CNT(portno)));
540 	sparx5_update_counter(&portstats[spx5_stats_tx_bc_cnt],
541 			      spx5_inst_rd(inst, ASM_TX_BC_CNT(portno)));
542 	sparx5_update_counter(&portstats[spx5_stats_tx_backoff1_cnt],
543 			      spx5_inst_rd(inst, ASM_TX_BACKOFF1_CNT(portno)));
544 	sparx5_update_counter(&portstats[spx5_stats_tx_multi_coll_cnt],
545 			      spx5_inst_rd(inst,
546 					   ASM_TX_MULTI_COLL_CNT(portno)));
547 	sparx5_update_counter(&portstats[spx5_stats_rx_uc_cnt],
548 			      spx5_inst_rd(inst, ASM_RX_UC_CNT(portno)));
549 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_uc_cnt],
550 			      spx5_inst_rd(inst, ASM_PMAC_RX_UC_CNT(portno)));
551 	sparx5_update_counter(&portstats[spx5_stats_rx_mc_cnt],
552 			      spx5_inst_rd(inst, ASM_RX_MC_CNT(portno)));
553 	sparx5_update_counter(&portstats[spx5_stats_rx_bc_cnt],
554 			      spx5_inst_rd(inst, ASM_RX_BC_CNT(portno)));
555 	sparx5_update_counter(&portstats[spx5_stats_rx_crc_err_cnt],
556 			      spx5_inst_rd(inst, ASM_RX_CRC_ERR_CNT(portno)));
557 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err_cnt],
558 			      spx5_inst_rd(inst,
559 					   ASM_PMAC_RX_CRC_ERR_CNT(portno)));
560 	sparx5_update_counter(&portstats[spx5_stats_rx_alignment_lost_cnt],
561 			      spx5_inst_rd(inst,
562 					   ASM_RX_ALIGNMENT_LOST_CNT(portno)));
563 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_alignment_lost_cnt],
564 			      spx5_inst_rd(inst,
565 					   ASM_PMAC_RX_ALIGNMENT_LOST_CNT(portno)));
566 	sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes_cnt],
567 			      spx5_inst_rd(inst, ASM_TX_OK_BYTES_CNT(portno)));
568 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes_cnt],
569 			      spx5_inst_rd(inst,
570 					   ASM_PMAC_TX_OK_BYTES_CNT(portno)));
571 	sparx5_update_counter(&portstats[spx5_stats_tx_defer_cnt],
572 			      spx5_inst_rd(inst, ASM_TX_DEFER_CNT(portno)));
573 	sparx5_update_counter(&portstats[spx5_stats_tx_late_coll_cnt],
574 			      spx5_inst_rd(inst, ASM_TX_LATE_COLL_CNT(portno)));
575 	sparx5_update_counter(&portstats[spx5_stats_tx_xcoll_cnt],
576 			      spx5_inst_rd(inst, ASM_TX_XCOLL_CNT(portno)));
577 	sparx5_update_counter(&portstats[spx5_stats_tx_csense_cnt],
578 			      spx5_inst_rd(inst, ASM_TX_CSENSE_CNT(portno)));
579 	sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes_cnt],
580 			      spx5_inst_rd(inst, ASM_RX_OK_BYTES_CNT(portno)));
581 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes_cnt],
582 			      spx5_inst_rd(inst,
583 					   ASM_PMAC_RX_OK_BYTES_CNT(portno)));
584 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_mc_cnt],
585 			      spx5_inst_rd(inst, ASM_PMAC_TX_MC_CNT(portno)));
586 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_bc_cnt],
587 			      spx5_inst_rd(inst, ASM_PMAC_TX_BC_CNT(portno)));
588 	sparx5_update_counter(&portstats[spx5_stats_tx_xdefer_cnt],
589 			      spx5_inst_rd(inst, ASM_TX_XDEFER_CNT(portno)));
590 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_mc_cnt],
591 			      spx5_inst_rd(inst, ASM_PMAC_RX_MC_CNT(portno)));
592 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bc_cnt],
593 			      spx5_inst_rd(inst, ASM_PMAC_RX_BC_CNT(portno)));
594 	sparx5_update_counter(&portstats[spx5_stats_rx_in_range_len_err_cnt],
595 			      spx5_inst_rd(inst,
596 					   ASM_RX_IN_RANGE_LEN_ERR_CNT(portno)));
597 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_in_range_len_err_cnt],
598 			      spx5_inst_rd(inst,
599 					   ASM_PMAC_RX_IN_RANGE_LEN_ERR_CNT(portno)));
600 	sparx5_update_counter(&portstats[spx5_stats_rx_out_of_range_len_err_cnt],
601 			      spx5_inst_rd(inst,
602 					   ASM_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno)));
603 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt],
604 			      spx5_inst_rd(inst,
605 					   ASM_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno)));
606 	sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
607 			      spx5_inst_rd(inst, ASM_RX_OVERSIZE_CNT(portno)));
608 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
609 			      spx5_inst_rd(inst,
610 					   ASM_PMAC_RX_OVERSIZE_CNT(portno)));
611 }
612 
613 static void sparx5_get_asm_mac_ctrl_stats(u64 *portstats, void __iomem *inst,
614 					  int portno)
615 {
616 	sparx5_update_counter(&portstats[spx5_stats_tx_pause_cnt],
617 			      spx5_inst_rd(inst, ASM_TX_PAUSE_CNT(portno)));
618 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause_cnt],
619 			      spx5_inst_rd(inst,
620 					   ASM_PMAC_TX_PAUSE_CNT(portno)));
621 	sparx5_update_counter(&portstats[spx5_stats_rx_pause_cnt],
622 			      spx5_inst_rd(inst, ASM_RX_PAUSE_CNT(portno)));
623 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause_cnt],
624 			      spx5_inst_rd(inst,
625 					   ASM_PMAC_RX_PAUSE_CNT(portno)));
626 	sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode_cnt],
627 			      spx5_inst_rd(inst,
628 					   ASM_RX_UNSUP_OPCODE_CNT(portno)));
629 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode_cnt],
630 			      spx5_inst_rd(inst,
631 					   ASM_PMAC_RX_UNSUP_OPCODE_CNT(portno)));
632 }
633 
634 static void sparx5_get_asm_rmon_stats(u64 *portstats, void __iomem *inst, int
635 				      portno)
636 {
637 	sparx5_update_counter(&portstats[spx5_stats_rx_undersize_cnt],
638 			      spx5_inst_rd(inst, ASM_RX_UNDERSIZE_CNT(portno)));
639 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize_cnt],
640 			      spx5_inst_rd(inst,
641 					   ASM_PMAC_RX_UNDERSIZE_CNT(portno)));
642 	sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
643 			      spx5_inst_rd(inst, ASM_RX_OVERSIZE_CNT(portno)));
644 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
645 			      spx5_inst_rd(inst,
646 					   ASM_PMAC_RX_OVERSIZE_CNT(portno)));
647 	sparx5_update_counter(&portstats[spx5_stats_rx_fragments_cnt],
648 			      spx5_inst_rd(inst, ASM_RX_FRAGMENTS_CNT(portno)));
649 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments_cnt],
650 			      spx5_inst_rd(inst,
651 					   ASM_PMAC_RX_FRAGMENTS_CNT(portno)));
652 	sparx5_update_counter(&portstats[spx5_stats_rx_jabbers_cnt],
653 			      spx5_inst_rd(inst, ASM_RX_JABBERS_CNT(portno)));
654 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers_cnt],
655 			      spx5_inst_rd(inst,
656 					   ASM_PMAC_RX_JABBERS_CNT(portno)));
657 	sparx5_update_counter(&portstats[spx5_stats_rx_size64_cnt],
658 			      spx5_inst_rd(inst, ASM_RX_SIZE64_CNT(portno)));
659 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64_cnt],
660 			      spx5_inst_rd(inst,
661 					   ASM_PMAC_RX_SIZE64_CNT(portno)));
662 	sparx5_update_counter(&portstats[spx5_stats_rx_size65to127_cnt],
663 			      spx5_inst_rd(inst,
664 					   ASM_RX_SIZE65TO127_CNT(portno)));
665 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65to127_cnt],
666 			      spx5_inst_rd(inst,
667 					   ASM_PMAC_RX_SIZE65TO127_CNT(portno)));
668 	sparx5_update_counter(&portstats[spx5_stats_rx_size128to255_cnt],
669 			      spx5_inst_rd(inst,
670 					   ASM_RX_SIZE128TO255_CNT(portno)));
671 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128to255_cnt],
672 			      spx5_inst_rd(inst,
673 					   ASM_PMAC_RX_SIZE128TO255_CNT(portno)));
674 	sparx5_update_counter(&portstats[spx5_stats_rx_size256to511_cnt],
675 			      spx5_inst_rd(inst,
676 					   ASM_RX_SIZE256TO511_CNT(portno)));
677 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256to511_cnt],
678 			      spx5_inst_rd(inst,
679 					   ASM_PMAC_RX_SIZE256TO511_CNT(portno)));
680 	sparx5_update_counter(&portstats[spx5_stats_rx_size512to1023_cnt],
681 			      spx5_inst_rd(inst,
682 					   ASM_RX_SIZE512TO1023_CNT(portno)));
683 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512to1023_cnt],
684 			      spx5_inst_rd(inst,
685 					   ASM_PMAC_RX_SIZE512TO1023_CNT(portno)));
686 	sparx5_update_counter(&portstats[spx5_stats_rx_size1024to1518_cnt],
687 			      spx5_inst_rd(inst,
688 					   ASM_RX_SIZE1024TO1518_CNT(portno)));
689 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024to1518_cnt],
690 			      spx5_inst_rd(inst,
691 					   ASM_PMAC_RX_SIZE1024TO1518_CNT(portno)));
692 	sparx5_update_counter(&portstats[spx5_stats_rx_size1519tomax_cnt],
693 			      spx5_inst_rd(inst,
694 					   ASM_RX_SIZE1519TOMAX_CNT(portno)));
695 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519tomax_cnt],
696 			      spx5_inst_rd(inst,
697 					   ASM_PMAC_RX_SIZE1519TOMAX_CNT(portno)));
698 	sparx5_update_counter(&portstats[spx5_stats_tx_size64_cnt],
699 			      spx5_inst_rd(inst, ASM_TX_SIZE64_CNT(portno)));
700 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64_cnt],
701 			      spx5_inst_rd(inst,
702 					   ASM_PMAC_TX_SIZE64_CNT(portno)));
703 	sparx5_update_counter(&portstats[spx5_stats_tx_size65to127_cnt],
704 			      spx5_inst_rd(inst,
705 					   ASM_TX_SIZE65TO127_CNT(portno)));
706 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65to127_cnt],
707 			      spx5_inst_rd(inst,
708 					   ASM_PMAC_TX_SIZE65TO127_CNT(portno)));
709 	sparx5_update_counter(&portstats[spx5_stats_tx_size128to255_cnt],
710 			      spx5_inst_rd(inst,
711 					   ASM_TX_SIZE128TO255_CNT(portno)));
712 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128to255_cnt],
713 			      spx5_inst_rd(inst,
714 					   ASM_PMAC_TX_SIZE128TO255_CNT(portno)));
715 	sparx5_update_counter(&portstats[spx5_stats_tx_size256to511_cnt],
716 			      spx5_inst_rd(inst,
717 					   ASM_TX_SIZE256TO511_CNT(portno)));
718 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256to511_cnt],
719 			      spx5_inst_rd(inst,
720 					   ASM_PMAC_TX_SIZE256TO511_CNT(portno)));
721 	sparx5_update_counter(&portstats[spx5_stats_tx_size512to1023_cnt],
722 			      spx5_inst_rd(inst,
723 					   ASM_TX_SIZE512TO1023_CNT(portno)));
724 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512to1023_cnt],
725 			      spx5_inst_rd(inst,
726 					   ASM_PMAC_TX_SIZE512TO1023_CNT(portno)));
727 	sparx5_update_counter(&portstats[spx5_stats_tx_size1024to1518_cnt],
728 			      spx5_inst_rd(inst,
729 					   ASM_TX_SIZE1024TO1518_CNT(portno)));
730 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024to1518_cnt],
731 			      spx5_inst_rd(inst,
732 					   ASM_PMAC_TX_SIZE1024TO1518_CNT(portno)));
733 	sparx5_update_counter(&portstats[spx5_stats_tx_size1519tomax_cnt],
734 			      spx5_inst_rd(inst,
735 					   ASM_TX_SIZE1519TOMAX_CNT(portno)));
736 	sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519tomax_cnt],
737 			      spx5_inst_rd(inst,
738 					   ASM_PMAC_TX_SIZE1519TOMAX_CNT(portno)));
739 }
740 
741 static void sparx5_get_asm_misc_stats(u64 *portstats, void __iomem *inst, int
742 				      portno)
743 {
744 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_err_cnt],
745 			      spx5_inst_rd(inst,
746 					   ASM_MM_RX_ASSEMBLY_ERR_CNT(portno)));
747 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_ok_cnt],
748 			      spx5_inst_rd(inst,
749 					   ASM_MM_RX_ASSEMBLY_OK_CNT(portno)));
750 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_merge_frag_cnt],
751 			      spx5_inst_rd(inst,
752 					   ASM_MM_RX_MERGE_FRAG_CNT(portno)));
753 	sparx5_update_counter(&portstats[spx5_stats_mm_rx_smd_err_cnt],
754 			      spx5_inst_rd(inst,
755 					   ASM_MM_RX_SMD_ERR_CNT(portno)));
756 	sparx5_update_counter(&portstats[spx5_stats_mm_tx_pfragment_cnt],
757 			      spx5_inst_rd(inst,
758 					   ASM_MM_TX_PFRAGMENT_CNT(portno)));
759 	sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes_cnt],
760 			      spx5_inst_rd(inst, ASM_RX_BAD_BYTES_CNT(portno)));
761 	sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes_cnt],
762 			      spx5_inst_rd(inst,
763 					   ASM_PMAC_RX_BAD_BYTES_CNT(portno)));
764 	sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes_cnt],
765 			      spx5_inst_rd(inst, ASM_RX_IN_BYTES_CNT(portno)));
766 	sparx5_update_counter(&portstats[spx5_stats_rx_ipg_shrink_cnt],
767 			      spx5_inst_rd(inst,
768 					   ASM_RX_IPG_SHRINK_CNT(portno)));
769 	sparx5_update_counter(&portstats[spx5_stats_rx_sync_lost_err_cnt],
770 			      spx5_inst_rd(inst,
771 					   ASM_RX_SYNC_LOST_ERR_CNT(portno)));
772 	sparx5_update_counter(&portstats[spx5_stats_rx_tagged_frms_cnt],
773 			      spx5_inst_rd(inst,
774 					   ASM_RX_TAGGED_FRMS_CNT(portno)));
775 	sparx5_update_counter(&portstats[spx5_stats_rx_untagged_frms_cnt],
776 			      spx5_inst_rd(inst,
777 					   ASM_RX_UNTAGGED_FRMS_CNT(portno)));
778 	sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes_cnt],
779 			      spx5_inst_rd(inst, ASM_TX_OUT_BYTES_CNT(portno)));
780 	sparx5_update_counter(&portstats[spx5_stats_tx_tagged_frms_cnt],
781 			      spx5_inst_rd(inst,
782 					   ASM_TX_TAGGED_FRMS_CNT(portno)));
783 	sparx5_update_counter(&portstats[spx5_stats_tx_untagged_frms_cnt],
784 			      spx5_inst_rd(inst,
785 					   ASM_TX_UNTAGGED_FRMS_CNT(portno)));
786 }
787 
788 static void sparx5_get_asm_stats(struct sparx5 *sparx5, int portno)
789 {
790 	u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
791 	void __iomem *inst = spx5_inst_get(sparx5, TARGET_ASM, 0);
792 
793 	sparx5_get_asm_phy_stats(portstats, inst, portno);
794 	sparx5_get_asm_mac_stats(portstats, inst, portno);
795 	sparx5_get_asm_mac_ctrl_stats(portstats, inst, portno);
796 	sparx5_get_asm_rmon_stats(portstats, inst, portno);
797 	sparx5_get_asm_misc_stats(portstats, inst, portno);
798 }
799 
800 static const struct ethtool_rmon_hist_range sparx5_rmon_ranges[] = {
801 	{    0,    64 },
802 	{   65,   127 },
803 	{  128,   255 },
804 	{  256,   511 },
805 	{  512,  1023 },
806 	{ 1024,  1518 },
807 	{ 1519, 10239 },
808 	{}
809 };
810 
811 static void sparx5_get_eth_phy_stats(struct net_device *ndev,
812 				     struct ethtool_eth_phy_stats *phy_stats)
813 {
814 	struct sparx5_port *port = netdev_priv(ndev);
815 	struct sparx5 *sparx5 = port->sparx5;
816 	int portno = port->portno;
817 	void __iomem *inst;
818 	u64 *portstats;
819 
820 	portstats = &sparx5->stats[portno * sparx5->num_stats];
821 	if (sparx5_is_baser(port->conf.portmode)) {
822 		u32 tinst = sparx5_port_dev_index(portno);
823 		u32 dev = sparx5_to_high_dev(portno);
824 
825 		inst = spx5_inst_get(sparx5, dev, tinst);
826 		sparx5_get_dev_phy_stats(portstats, inst, tinst);
827 	} else {
828 		inst = spx5_inst_get(sparx5, TARGET_ASM, 0);
829 		sparx5_get_asm_phy_stats(portstats, inst, portno);
830 	}
831 	phy_stats->SymbolErrorDuringCarrier =
832 		portstats[spx5_stats_rx_symbol_err_cnt] +
833 		portstats[spx5_stats_pmac_rx_symbol_err_cnt];
834 }
835 
836 static void sparx5_get_eth_mac_stats(struct net_device *ndev,
837 				     struct ethtool_eth_mac_stats *mac_stats)
838 {
839 	struct sparx5_port *port = netdev_priv(ndev);
840 	struct sparx5 *sparx5 = port->sparx5;
841 	int portno = port->portno;
842 	void __iomem *inst;
843 	u64 *portstats;
844 
845 	portstats = &sparx5->stats[portno * sparx5->num_stats];
846 	if (sparx5_is_baser(port->conf.portmode)) {
847 		u32 tinst = sparx5_port_dev_index(portno);
848 		u32 dev = sparx5_to_high_dev(portno);
849 
850 		inst = spx5_inst_get(sparx5, dev, tinst);
851 		sparx5_get_dev_mac_stats(portstats, inst, tinst);
852 	} else {
853 		inst = spx5_inst_get(sparx5, TARGET_ASM, 0);
854 		sparx5_get_asm_mac_stats(portstats, inst, portno);
855 	}
856 	mac_stats->FramesTransmittedOK = portstats[spx5_stats_tx_uc_cnt] +
857 		portstats[spx5_stats_pmac_tx_uc_cnt] +
858 		portstats[spx5_stats_tx_mc_cnt] +
859 		portstats[spx5_stats_tx_bc_cnt];
860 	mac_stats->SingleCollisionFrames =
861 		portstats[spx5_stats_tx_backoff1_cnt];
862 	mac_stats->MultipleCollisionFrames =
863 		portstats[spx5_stats_tx_multi_coll_cnt];
864 	mac_stats->FramesReceivedOK = portstats[spx5_stats_rx_uc_cnt] +
865 		portstats[spx5_stats_pmac_rx_uc_cnt] +
866 		portstats[spx5_stats_rx_mc_cnt] +
867 		portstats[spx5_stats_rx_bc_cnt];
868 	mac_stats->FrameCheckSequenceErrors =
869 		portstats[spx5_stats_rx_crc_err_cnt] +
870 		portstats[spx5_stats_pmac_rx_crc_err_cnt];
871 	mac_stats->AlignmentErrors = portstats[spx5_stats_rx_alignment_lost_cnt]
872 		+ portstats[spx5_stats_pmac_rx_alignment_lost_cnt];
873 	mac_stats->OctetsTransmittedOK = portstats[spx5_stats_tx_ok_bytes_cnt] +
874 		portstats[spx5_stats_pmac_tx_ok_bytes_cnt];
875 	mac_stats->FramesWithDeferredXmissions =
876 		portstats[spx5_stats_tx_defer_cnt];
877 	mac_stats->LateCollisions =
878 		portstats[spx5_stats_tx_late_coll_cnt];
879 	mac_stats->FramesAbortedDueToXSColls =
880 		portstats[spx5_stats_tx_xcoll_cnt];
881 	mac_stats->CarrierSenseErrors = portstats[spx5_stats_tx_csense_cnt];
882 	mac_stats->OctetsReceivedOK = portstats[spx5_stats_rx_ok_bytes_cnt] +
883 		portstats[spx5_stats_pmac_rx_ok_bytes_cnt];
884 	mac_stats->MulticastFramesXmittedOK = portstats[spx5_stats_tx_mc_cnt] +
885 		portstats[spx5_stats_pmac_tx_mc_cnt];
886 	mac_stats->BroadcastFramesXmittedOK = portstats[spx5_stats_tx_bc_cnt] +
887 		portstats[spx5_stats_pmac_tx_bc_cnt];
888 	mac_stats->FramesWithExcessiveDeferral =
889 		portstats[spx5_stats_tx_xdefer_cnt];
890 	mac_stats->MulticastFramesReceivedOK = portstats[spx5_stats_rx_mc_cnt] +
891 		portstats[spx5_stats_pmac_rx_mc_cnt];
892 	mac_stats->BroadcastFramesReceivedOK = portstats[spx5_stats_rx_bc_cnt] +
893 		portstats[spx5_stats_pmac_rx_bc_cnt];
894 	mac_stats->InRangeLengthErrors =
895 		portstats[spx5_stats_rx_in_range_len_err_cnt] +
896 		portstats[spx5_stats_pmac_rx_in_range_len_err_cnt];
897 	mac_stats->OutOfRangeLengthField =
898 		portstats[spx5_stats_rx_out_of_range_len_err_cnt] +
899 		portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt];
900 	mac_stats->FrameTooLongErrors = portstats[spx5_stats_rx_oversize_cnt] +
901 		portstats[spx5_stats_pmac_rx_oversize_cnt];
902 }
903 
904 static void sparx5_get_eth_mac_ctrl_stats(struct net_device *ndev,
905 					  struct ethtool_eth_ctrl_stats *mac_ctrl_stats)
906 {
907 	struct sparx5_port *port = netdev_priv(ndev);
908 	struct sparx5 *sparx5 = port->sparx5;
909 	int portno = port->portno;
910 	void __iomem *inst;
911 	u64 *portstats;
912 
913 	portstats = &sparx5->stats[portno * sparx5->num_stats];
914 	if (sparx5_is_baser(port->conf.portmode)) {
915 		u32 tinst = sparx5_port_dev_index(portno);
916 		u32 dev = sparx5_to_high_dev(portno);
917 
918 		inst = spx5_inst_get(sparx5, dev, tinst);
919 		sparx5_get_dev_mac_ctrl_stats(portstats, inst, tinst);
920 	} else {
921 		inst = spx5_inst_get(sparx5, TARGET_ASM, 0);
922 		sparx5_get_asm_mac_ctrl_stats(portstats, inst, portno);
923 	}
924 	mac_ctrl_stats->MACControlFramesTransmitted =
925 		portstats[spx5_stats_tx_pause_cnt] +
926 		portstats[spx5_stats_pmac_tx_pause_cnt];
927 	mac_ctrl_stats->MACControlFramesReceived =
928 		portstats[spx5_stats_rx_pause_cnt] +
929 		portstats[spx5_stats_pmac_rx_pause_cnt];
930 	mac_ctrl_stats->UnsupportedOpcodesReceived =
931 		portstats[spx5_stats_rx_unsup_opcode_cnt] +
932 		portstats[spx5_stats_pmac_rx_unsup_opcode_cnt];
933 }
934 
935 static void sparx5_get_eth_rmon_stats(struct net_device *ndev,
936 				      struct ethtool_rmon_stats *rmon_stats,
937 				      const struct ethtool_rmon_hist_range **ranges)
938 {
939 	struct sparx5_port *port = netdev_priv(ndev);
940 	struct sparx5 *sparx5 = port->sparx5;
941 	int portno = port->portno;
942 	void __iomem *inst;
943 	u64 *portstats;
944 
945 	portstats = &sparx5->stats[portno * sparx5->num_stats];
946 	if (sparx5_is_baser(port->conf.portmode)) {
947 		u32 tinst = sparx5_port_dev_index(portno);
948 		u32 dev = sparx5_to_high_dev(portno);
949 
950 		inst = spx5_inst_get(sparx5, dev, tinst);
951 		sparx5_get_dev_rmon_stats(portstats, inst, tinst);
952 	} else {
953 		inst = spx5_inst_get(sparx5, TARGET_ASM, 0);
954 		sparx5_get_asm_rmon_stats(portstats, inst, portno);
955 	}
956 	rmon_stats->undersize_pkts = portstats[spx5_stats_rx_undersize_cnt] +
957 		portstats[spx5_stats_pmac_rx_undersize_cnt];
958 	rmon_stats->oversize_pkts = portstats[spx5_stats_rx_oversize_cnt] +
959 		portstats[spx5_stats_pmac_rx_oversize_cnt];
960 	rmon_stats->fragments = portstats[spx5_stats_rx_fragments_cnt] +
961 		portstats[spx5_stats_pmac_rx_fragments_cnt];
962 	rmon_stats->jabbers = portstats[spx5_stats_rx_jabbers_cnt] +
963 		portstats[spx5_stats_pmac_rx_jabbers_cnt];
964 	rmon_stats->hist[0] = portstats[spx5_stats_rx_size64_cnt] +
965 		portstats[spx5_stats_pmac_rx_size64_cnt];
966 	rmon_stats->hist[1] = portstats[spx5_stats_rx_size65to127_cnt] +
967 		portstats[spx5_stats_pmac_rx_size65to127_cnt];
968 	rmon_stats->hist[2] = portstats[spx5_stats_rx_size128to255_cnt] +
969 		portstats[spx5_stats_pmac_rx_size128to255_cnt];
970 	rmon_stats->hist[3] = portstats[spx5_stats_rx_size256to511_cnt] +
971 		portstats[spx5_stats_pmac_rx_size256to511_cnt];
972 	rmon_stats->hist[4] = portstats[spx5_stats_rx_size512to1023_cnt] +
973 		portstats[spx5_stats_pmac_rx_size512to1023_cnt];
974 	rmon_stats->hist[5] = portstats[spx5_stats_rx_size1024to1518_cnt] +
975 		portstats[spx5_stats_pmac_rx_size1024to1518_cnt];
976 	rmon_stats->hist[6] = portstats[spx5_stats_rx_size1519tomax_cnt] +
977 		portstats[spx5_stats_pmac_rx_size1519tomax_cnt];
978 	rmon_stats->hist_tx[0] = portstats[spx5_stats_tx_size64_cnt] +
979 		portstats[spx5_stats_pmac_tx_size64_cnt];
980 	rmon_stats->hist_tx[1] = portstats[spx5_stats_tx_size65to127_cnt] +
981 		portstats[spx5_stats_pmac_tx_size65to127_cnt];
982 	rmon_stats->hist_tx[2] = portstats[spx5_stats_tx_size128to255_cnt] +
983 		portstats[spx5_stats_pmac_tx_size128to255_cnt];
984 	rmon_stats->hist_tx[3] = portstats[spx5_stats_tx_size256to511_cnt] +
985 		portstats[spx5_stats_pmac_tx_size256to511_cnt];
986 	rmon_stats->hist_tx[4] = portstats[spx5_stats_tx_size512to1023_cnt] +
987 		portstats[spx5_stats_pmac_tx_size512to1023_cnt];
988 	rmon_stats->hist_tx[5] = portstats[spx5_stats_tx_size1024to1518_cnt] +
989 		portstats[spx5_stats_pmac_tx_size1024to1518_cnt];
990 	rmon_stats->hist_tx[6] = portstats[spx5_stats_tx_size1519tomax_cnt] +
991 		portstats[spx5_stats_pmac_tx_size1519tomax_cnt];
992 	*ranges = sparx5_rmon_ranges;
993 }
994 
995 static int sparx5_get_sset_count(struct net_device *ndev, int sset)
996 {
997 	struct sparx5_port *port = netdev_priv(ndev);
998 	struct sparx5  *sparx5 = port->sparx5;
999 
1000 	if (sset != ETH_SS_STATS)
1001 		return -EOPNOTSUPP;
1002 	return sparx5->num_ethtool_stats;
1003 }
1004 
1005 static void sparx5_get_sset_strings(struct net_device *ndev, u32 sset, u8 *data)
1006 {
1007 	struct sparx5_port *port = netdev_priv(ndev);
1008 	struct sparx5  *sparx5 = port->sparx5;
1009 	int idx;
1010 
1011 	if (sset != ETH_SS_STATS)
1012 		return;
1013 
1014 	for (idx = 0; idx < sparx5->num_ethtool_stats; idx++)
1015 		strncpy(data + idx * ETH_GSTRING_LEN,
1016 			sparx5->stats_layout[idx], ETH_GSTRING_LEN);
1017 }
1018 
1019 static void sparx5_get_sset_data(struct net_device *ndev,
1020 				 struct ethtool_stats *stats, u64 *data)
1021 {
1022 	struct sparx5_port *port = netdev_priv(ndev);
1023 	struct sparx5 *sparx5 = port->sparx5;
1024 	int portno = port->portno;
1025 	void __iomem *inst;
1026 	u64 *portstats;
1027 	int idx;
1028 
1029 	portstats = &sparx5->stats[portno * sparx5->num_stats];
1030 	if (sparx5_is_baser(port->conf.portmode)) {
1031 		u32 tinst = sparx5_port_dev_index(portno);
1032 		u32 dev = sparx5_to_high_dev(portno);
1033 
1034 		inst = spx5_inst_get(sparx5, dev, tinst);
1035 		sparx5_get_dev_misc_stats(portstats, inst, tinst);
1036 	} else {
1037 		inst = spx5_inst_get(sparx5, TARGET_ASM, 0);
1038 		sparx5_get_asm_misc_stats(portstats, inst, portno);
1039 	}
1040 	sparx5_get_ana_ac_stats_stats(sparx5, portno);
1041 	sparx5_get_queue_sys_stats(sparx5, portno);
1042 	/* Copy port counters to the ethtool buffer */
1043 	for (idx = spx5_stats_mm_rx_assembly_err_cnt;
1044 	     idx < spx5_stats_mm_rx_assembly_err_cnt +
1045 	     sparx5->num_ethtool_stats; idx++)
1046 		*data++ = portstats[idx];
1047 }
1048 
1049 void sparx5_get_stats64(struct net_device *ndev,
1050 			struct rtnl_link_stats64 *stats)
1051 {
1052 	struct sparx5_port *port = netdev_priv(ndev);
1053 	struct sparx5 *sparx5 = port->sparx5;
1054 	u64 *portstats;
1055 	int idx;
1056 
1057 	if (!sparx5->stats)
1058 		return; /* Not initialized yet */
1059 
1060 	portstats = &sparx5->stats[port->portno * sparx5->num_stats];
1061 
1062 	stats->rx_packets = portstats[spx5_stats_rx_uc_cnt] +
1063 		portstats[spx5_stats_pmac_rx_uc_cnt] +
1064 		portstats[spx5_stats_rx_mc_cnt] +
1065 		portstats[spx5_stats_rx_bc_cnt];
1066 	stats->tx_packets = portstats[spx5_stats_tx_uc_cnt] +
1067 		portstats[spx5_stats_pmac_tx_uc_cnt] +
1068 		portstats[spx5_stats_tx_mc_cnt] +
1069 		portstats[spx5_stats_tx_bc_cnt];
1070 	stats->rx_bytes = portstats[spx5_stats_rx_ok_bytes_cnt] +
1071 		portstats[spx5_stats_pmac_rx_ok_bytes_cnt];
1072 	stats->tx_bytes = portstats[spx5_stats_tx_ok_bytes_cnt] +
1073 		portstats[spx5_stats_pmac_tx_ok_bytes_cnt];
1074 	stats->rx_errors = portstats[spx5_stats_rx_in_range_len_err_cnt] +
1075 		portstats[spx5_stats_pmac_rx_in_range_len_err_cnt] +
1076 		portstats[spx5_stats_rx_out_of_range_len_err_cnt] +
1077 		portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt] +
1078 		portstats[spx5_stats_rx_oversize_cnt] +
1079 		portstats[spx5_stats_pmac_rx_oversize_cnt] +
1080 		portstats[spx5_stats_rx_crc_err_cnt] +
1081 		portstats[spx5_stats_pmac_rx_crc_err_cnt] +
1082 		portstats[spx5_stats_rx_alignment_lost_cnt] +
1083 		portstats[spx5_stats_pmac_rx_alignment_lost_cnt];
1084 	stats->tx_errors = portstats[spx5_stats_tx_xcoll_cnt] +
1085 		portstats[spx5_stats_tx_csense_cnt] +
1086 		portstats[spx5_stats_tx_late_coll_cnt];
1087 	stats->multicast = portstats[spx5_stats_rx_mc_cnt] +
1088 		portstats[spx5_stats_pmac_rx_mc_cnt];
1089 	stats->collisions = portstats[spx5_stats_tx_late_coll_cnt] +
1090 		portstats[spx5_stats_tx_xcoll_cnt] +
1091 		portstats[spx5_stats_tx_backoff1_cnt];
1092 	stats->rx_length_errors = portstats[spx5_stats_rx_in_range_len_err_cnt] +
1093 		portstats[spx5_stats_pmac_rx_in_range_len_err_cnt] +
1094 		portstats[spx5_stats_rx_out_of_range_len_err_cnt] +
1095 		portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt] +
1096 		portstats[spx5_stats_rx_oversize_cnt] +
1097 		portstats[spx5_stats_pmac_rx_oversize_cnt];
1098 	stats->rx_crc_errors = portstats[spx5_stats_rx_crc_err_cnt] +
1099 		portstats[spx5_stats_pmac_rx_crc_err_cnt];
1100 	stats->rx_frame_errors = portstats[spx5_stats_rx_alignment_lost_cnt] +
1101 		portstats[spx5_stats_pmac_rx_alignment_lost_cnt];
1102 	stats->tx_aborted_errors = portstats[spx5_stats_tx_xcoll_cnt];
1103 	stats->tx_carrier_errors = portstats[spx5_stats_tx_csense_cnt];
1104 	stats->tx_window_errors = portstats[spx5_stats_tx_late_coll_cnt];
1105 	stats->rx_dropped = portstats[spx5_stats_ana_ac_port_stat_lsb_cnt];
1106 	for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++stats)
1107 		stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop
1108 					       + idx];
1109 	stats->tx_dropped = portstats[spx5_stats_tx_local_drop];
1110 }
1111 
1112 static void sparx5_update_port_stats(struct sparx5 *sparx5, int portno)
1113 {
1114 	if (sparx5_is_baser(sparx5->ports[portno]->conf.portmode))
1115 		sparx5_get_device_stats(sparx5, portno);
1116 	else
1117 		sparx5_get_asm_stats(sparx5, portno);
1118 	sparx5_get_ana_ac_stats_stats(sparx5, portno);
1119 	sparx5_get_queue_sys_stats(sparx5, portno);
1120 }
1121 
1122 static void sparx5_update_stats(struct sparx5 *sparx5)
1123 {
1124 	int idx;
1125 
1126 	for (idx = 0; idx < SPX5_PORTS; idx++)
1127 		if (sparx5->ports[idx])
1128 			sparx5_update_port_stats(sparx5, idx);
1129 }
1130 
1131 static void sparx5_check_stats_work(struct work_struct *work)
1132 {
1133 	struct delayed_work *dwork = to_delayed_work(work);
1134 	struct sparx5 *sparx5 = container_of(dwork,
1135 					     struct sparx5,
1136 					     stats_work);
1137 
1138 	sparx5_update_stats(sparx5);
1139 
1140 	queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work,
1141 			   SPX5_STATS_CHECK_DELAY);
1142 }
1143 
1144 static int sparx5_get_link_settings(struct net_device *ndev,
1145 				    struct ethtool_link_ksettings *cmd)
1146 {
1147 	struct sparx5_port *port = netdev_priv(ndev);
1148 
1149 	return phylink_ethtool_ksettings_get(port->phylink, cmd);
1150 }
1151 
1152 static int sparx5_set_link_settings(struct net_device *ndev,
1153 				    const struct ethtool_link_ksettings *cmd)
1154 {
1155 	struct sparx5_port *port = netdev_priv(ndev);
1156 
1157 	return phylink_ethtool_ksettings_set(port->phylink, cmd);
1158 }
1159 
1160 static void sparx5_config_stats(struct sparx5 *sparx5)
1161 {
1162 	/* Enable global events for port policer drops */
1163 	spx5_rmw(ANA_AC_PORT_SGE_CFG_MASK_SET(0xf0f0),
1164 		 ANA_AC_PORT_SGE_CFG_MASK,
1165 		 sparx5,
1166 		 ANA_AC_PORT_SGE_CFG(SPX5_PORT_POLICER_DROPS));
1167 }
1168 
1169 static void sparx5_config_port_stats(struct sparx5 *sparx5, int portno)
1170 {
1171 	/* Clear Queue System counters */
1172 	spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno) |
1173 		XQS_STAT_CFG_STAT_CLEAR_SHOT_SET(3), sparx5,
1174 		XQS_STAT_CFG);
1175 
1176 	/* Use counter for port policer drop count */
1177 	spx5_rmw(ANA_AC_PORT_STAT_CFG_CFG_CNT_FRM_TYPE_SET(1) |
1178 		 ANA_AC_PORT_STAT_CFG_CFG_CNT_BYTE_SET(0) |
1179 		 ANA_AC_PORT_STAT_CFG_CFG_PRIO_MASK_SET(0xff),
1180 		 ANA_AC_PORT_STAT_CFG_CFG_CNT_FRM_TYPE |
1181 		 ANA_AC_PORT_STAT_CFG_CFG_CNT_BYTE |
1182 		 ANA_AC_PORT_STAT_CFG_CFG_PRIO_MASK,
1183 		 sparx5, ANA_AC_PORT_STAT_CFG(portno, SPX5_PORT_POLICER_DROPS));
1184 }
1185 
1186 const struct ethtool_ops sparx5_ethtool_ops = {
1187 	.get_sset_count         = sparx5_get_sset_count,
1188 	.get_strings            = sparx5_get_sset_strings,
1189 	.get_ethtool_stats      = sparx5_get_sset_data,
1190 	.get_link_ksettings	= sparx5_get_link_settings,
1191 	.set_link_ksettings	= sparx5_set_link_settings,
1192 	.get_link               = ethtool_op_get_link,
1193 	.get_eth_phy_stats      = sparx5_get_eth_phy_stats,
1194 	.get_eth_mac_stats      = sparx5_get_eth_mac_stats,
1195 	.get_eth_ctrl_stats     = sparx5_get_eth_mac_ctrl_stats,
1196 	.get_rmon_stats         = sparx5_get_eth_rmon_stats,
1197 };
1198 
1199 int sparx_stats_init(struct sparx5 *sparx5)
1200 {
1201 	char queue_name[32];
1202 	int portno;
1203 
1204 	sparx5->stats_layout = sparx5_stats_layout;
1205 	sparx5->num_stats = spx5_stats_count;
1206 	sparx5->num_ethtool_stats = ARRAY_SIZE(sparx5_stats_layout);
1207 	sparx5->stats = devm_kcalloc(sparx5->dev,
1208 				     SPX5_PORTS_ALL * sparx5->num_stats,
1209 				     sizeof(u64), GFP_KERNEL);
1210 	if (!sparx5->stats)
1211 		return -ENOMEM;
1212 
1213 	mutex_init(&sparx5->queue_stats_lock);
1214 	sparx5_config_stats(sparx5);
1215 	for (portno = 0; portno < SPX5_PORTS; portno++)
1216 		if (sparx5->ports[portno])
1217 			sparx5_config_port_stats(sparx5, portno);
1218 
1219 	snprintf(queue_name, sizeof(queue_name), "%s-stats",
1220 		 dev_name(sparx5->dev));
1221 	sparx5->stats_queue = create_singlethread_workqueue(queue_name);
1222 	INIT_DELAYED_WORK(&sparx5->stats_work, sparx5_check_stats_work);
1223 	queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work,
1224 			   SPX5_STATS_CHECK_DELAY);
1225 
1226 	return 0;
1227 }
1228