1  // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2  /* Statistics for Ocelot switch family
3   *
4   * Copyright (c) 2017 Microsemi Corporation
5   * Copyright 2022 NXP
6   */
7  #include <linux/ethtool_netlink.h>
8  #include <linux/spinlock.h>
9  #include <linux/mutex.h>
10  #include <linux/workqueue.h>
11  #include "ocelot.h"
12  
13  enum ocelot_stat {
14  	OCELOT_STAT_RX_OCTETS,
15  	OCELOT_STAT_RX_UNICAST,
16  	OCELOT_STAT_RX_MULTICAST,
17  	OCELOT_STAT_RX_BROADCAST,
18  	OCELOT_STAT_RX_SHORTS,
19  	OCELOT_STAT_RX_FRAGMENTS,
20  	OCELOT_STAT_RX_JABBERS,
21  	OCELOT_STAT_RX_CRC_ALIGN_ERRS,
22  	OCELOT_STAT_RX_SYM_ERRS,
23  	OCELOT_STAT_RX_64,
24  	OCELOT_STAT_RX_65_127,
25  	OCELOT_STAT_RX_128_255,
26  	OCELOT_STAT_RX_256_511,
27  	OCELOT_STAT_RX_512_1023,
28  	OCELOT_STAT_RX_1024_1526,
29  	OCELOT_STAT_RX_1527_MAX,
30  	OCELOT_STAT_RX_PAUSE,
31  	OCELOT_STAT_RX_CONTROL,
32  	OCELOT_STAT_RX_LONGS,
33  	OCELOT_STAT_RX_CLASSIFIED_DROPS,
34  	OCELOT_STAT_RX_RED_PRIO_0,
35  	OCELOT_STAT_RX_RED_PRIO_1,
36  	OCELOT_STAT_RX_RED_PRIO_2,
37  	OCELOT_STAT_RX_RED_PRIO_3,
38  	OCELOT_STAT_RX_RED_PRIO_4,
39  	OCELOT_STAT_RX_RED_PRIO_5,
40  	OCELOT_STAT_RX_RED_PRIO_6,
41  	OCELOT_STAT_RX_RED_PRIO_7,
42  	OCELOT_STAT_RX_YELLOW_PRIO_0,
43  	OCELOT_STAT_RX_YELLOW_PRIO_1,
44  	OCELOT_STAT_RX_YELLOW_PRIO_2,
45  	OCELOT_STAT_RX_YELLOW_PRIO_3,
46  	OCELOT_STAT_RX_YELLOW_PRIO_4,
47  	OCELOT_STAT_RX_YELLOW_PRIO_5,
48  	OCELOT_STAT_RX_YELLOW_PRIO_6,
49  	OCELOT_STAT_RX_YELLOW_PRIO_7,
50  	OCELOT_STAT_RX_GREEN_PRIO_0,
51  	OCELOT_STAT_RX_GREEN_PRIO_1,
52  	OCELOT_STAT_RX_GREEN_PRIO_2,
53  	OCELOT_STAT_RX_GREEN_PRIO_3,
54  	OCELOT_STAT_RX_GREEN_PRIO_4,
55  	OCELOT_STAT_RX_GREEN_PRIO_5,
56  	OCELOT_STAT_RX_GREEN_PRIO_6,
57  	OCELOT_STAT_RX_GREEN_PRIO_7,
58  	OCELOT_STAT_RX_ASSEMBLY_ERRS,
59  	OCELOT_STAT_RX_SMD_ERRS,
60  	OCELOT_STAT_RX_ASSEMBLY_OK,
61  	OCELOT_STAT_RX_MERGE_FRAGMENTS,
62  	OCELOT_STAT_RX_PMAC_OCTETS,
63  	OCELOT_STAT_RX_PMAC_UNICAST,
64  	OCELOT_STAT_RX_PMAC_MULTICAST,
65  	OCELOT_STAT_RX_PMAC_BROADCAST,
66  	OCELOT_STAT_RX_PMAC_SHORTS,
67  	OCELOT_STAT_RX_PMAC_FRAGMENTS,
68  	OCELOT_STAT_RX_PMAC_JABBERS,
69  	OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS,
70  	OCELOT_STAT_RX_PMAC_SYM_ERRS,
71  	OCELOT_STAT_RX_PMAC_64,
72  	OCELOT_STAT_RX_PMAC_65_127,
73  	OCELOT_STAT_RX_PMAC_128_255,
74  	OCELOT_STAT_RX_PMAC_256_511,
75  	OCELOT_STAT_RX_PMAC_512_1023,
76  	OCELOT_STAT_RX_PMAC_1024_1526,
77  	OCELOT_STAT_RX_PMAC_1527_MAX,
78  	OCELOT_STAT_RX_PMAC_PAUSE,
79  	OCELOT_STAT_RX_PMAC_CONTROL,
80  	OCELOT_STAT_RX_PMAC_LONGS,
81  	OCELOT_STAT_TX_OCTETS,
82  	OCELOT_STAT_TX_UNICAST,
83  	OCELOT_STAT_TX_MULTICAST,
84  	OCELOT_STAT_TX_BROADCAST,
85  	OCELOT_STAT_TX_COLLISION,
86  	OCELOT_STAT_TX_DROPS,
87  	OCELOT_STAT_TX_PAUSE,
88  	OCELOT_STAT_TX_64,
89  	OCELOT_STAT_TX_65_127,
90  	OCELOT_STAT_TX_128_255,
91  	OCELOT_STAT_TX_256_511,
92  	OCELOT_STAT_TX_512_1023,
93  	OCELOT_STAT_TX_1024_1526,
94  	OCELOT_STAT_TX_1527_MAX,
95  	OCELOT_STAT_TX_YELLOW_PRIO_0,
96  	OCELOT_STAT_TX_YELLOW_PRIO_1,
97  	OCELOT_STAT_TX_YELLOW_PRIO_2,
98  	OCELOT_STAT_TX_YELLOW_PRIO_3,
99  	OCELOT_STAT_TX_YELLOW_PRIO_4,
100  	OCELOT_STAT_TX_YELLOW_PRIO_5,
101  	OCELOT_STAT_TX_YELLOW_PRIO_6,
102  	OCELOT_STAT_TX_YELLOW_PRIO_7,
103  	OCELOT_STAT_TX_GREEN_PRIO_0,
104  	OCELOT_STAT_TX_GREEN_PRIO_1,
105  	OCELOT_STAT_TX_GREEN_PRIO_2,
106  	OCELOT_STAT_TX_GREEN_PRIO_3,
107  	OCELOT_STAT_TX_GREEN_PRIO_4,
108  	OCELOT_STAT_TX_GREEN_PRIO_5,
109  	OCELOT_STAT_TX_GREEN_PRIO_6,
110  	OCELOT_STAT_TX_GREEN_PRIO_7,
111  	OCELOT_STAT_TX_AGED,
112  	OCELOT_STAT_TX_MM_HOLD,
113  	OCELOT_STAT_TX_MERGE_FRAGMENTS,
114  	OCELOT_STAT_TX_PMAC_OCTETS,
115  	OCELOT_STAT_TX_PMAC_UNICAST,
116  	OCELOT_STAT_TX_PMAC_MULTICAST,
117  	OCELOT_STAT_TX_PMAC_BROADCAST,
118  	OCELOT_STAT_TX_PMAC_PAUSE,
119  	OCELOT_STAT_TX_PMAC_64,
120  	OCELOT_STAT_TX_PMAC_65_127,
121  	OCELOT_STAT_TX_PMAC_128_255,
122  	OCELOT_STAT_TX_PMAC_256_511,
123  	OCELOT_STAT_TX_PMAC_512_1023,
124  	OCELOT_STAT_TX_PMAC_1024_1526,
125  	OCELOT_STAT_TX_PMAC_1527_MAX,
126  	OCELOT_STAT_DROP_LOCAL,
127  	OCELOT_STAT_DROP_TAIL,
128  	OCELOT_STAT_DROP_YELLOW_PRIO_0,
129  	OCELOT_STAT_DROP_YELLOW_PRIO_1,
130  	OCELOT_STAT_DROP_YELLOW_PRIO_2,
131  	OCELOT_STAT_DROP_YELLOW_PRIO_3,
132  	OCELOT_STAT_DROP_YELLOW_PRIO_4,
133  	OCELOT_STAT_DROP_YELLOW_PRIO_5,
134  	OCELOT_STAT_DROP_YELLOW_PRIO_6,
135  	OCELOT_STAT_DROP_YELLOW_PRIO_7,
136  	OCELOT_STAT_DROP_GREEN_PRIO_0,
137  	OCELOT_STAT_DROP_GREEN_PRIO_1,
138  	OCELOT_STAT_DROP_GREEN_PRIO_2,
139  	OCELOT_STAT_DROP_GREEN_PRIO_3,
140  	OCELOT_STAT_DROP_GREEN_PRIO_4,
141  	OCELOT_STAT_DROP_GREEN_PRIO_5,
142  	OCELOT_STAT_DROP_GREEN_PRIO_6,
143  	OCELOT_STAT_DROP_GREEN_PRIO_7,
144  	OCELOT_NUM_STATS,
145  };
146  
147  struct ocelot_stat_layout {
148  	enum ocelot_reg reg;
149  	char name[ETH_GSTRING_LEN];
150  };
151  
152  /* 32-bit counter checked for wraparound by ocelot_port_update_stats()
153   * and copied to ocelot->stats.
154   */
155  #define OCELOT_STAT(kind) \
156  	[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind }
157  /* Same as above, except also exported to ethtool -S. Standard counters should
158   * only be exposed to more specific interfaces rather than by their string name.
159   */
160  #define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \
161  	[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name }
162  
163  #define OCELOT_COMMON_STATS \
164  	OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \
165  	OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \
166  	OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \
167  	OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \
168  	OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \
169  	OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \
170  	OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \
171  	OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \
172  	OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \
173  	OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \
174  	OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \
175  	OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \
176  	OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \
177  	OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \
178  	OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \
179  	OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \
180  	OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \
181  	OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \
182  	OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \
183  	OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \
184  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \
185  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \
186  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \
187  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \
188  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \
189  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \
190  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \
191  	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \
192  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \
193  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \
194  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \
195  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \
196  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \
197  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \
198  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \
199  	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \
200  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \
201  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \
202  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \
203  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \
204  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \
205  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \
206  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \
207  	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \
208  	OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \
209  	OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \
210  	OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \
211  	OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \
212  	OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \
213  	OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \
214  	OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \
215  	OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \
216  	OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \
217  	OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \
218  	OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \
219  	OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \
220  	OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \
221  	OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \
222  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \
223  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \
224  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \
225  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \
226  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \
227  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \
228  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \
229  	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \
230  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \
231  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \
232  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \
233  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \
234  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \
235  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \
236  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \
237  	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \
238  	OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \
239  	OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \
240  	OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \
241  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \
242  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \
243  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \
244  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \
245  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \
246  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \
247  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \
248  	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \
249  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \
250  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \
251  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \
252  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \
253  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \
254  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \
255  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \
256  	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7")
257  
258  struct ocelot_stats_region {
259  	struct list_head node;
260  	enum ocelot_reg base;
261  	enum ocelot_stat first_stat;
262  	int count;
263  	u32 *buf;
264  };
265  
266  static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
267  	OCELOT_COMMON_STATS,
268  };
269  
270  static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS] = {
271  	OCELOT_COMMON_STATS,
272  	OCELOT_STAT(RX_ASSEMBLY_ERRS),
273  	OCELOT_STAT(RX_SMD_ERRS),
274  	OCELOT_STAT(RX_ASSEMBLY_OK),
275  	OCELOT_STAT(RX_MERGE_FRAGMENTS),
276  	OCELOT_STAT(TX_MERGE_FRAGMENTS),
277  	OCELOT_STAT(TX_MM_HOLD),
278  	OCELOT_STAT(RX_PMAC_OCTETS),
279  	OCELOT_STAT(RX_PMAC_UNICAST),
280  	OCELOT_STAT(RX_PMAC_MULTICAST),
281  	OCELOT_STAT(RX_PMAC_BROADCAST),
282  	OCELOT_STAT(RX_PMAC_SHORTS),
283  	OCELOT_STAT(RX_PMAC_FRAGMENTS),
284  	OCELOT_STAT(RX_PMAC_JABBERS),
285  	OCELOT_STAT(RX_PMAC_CRC_ALIGN_ERRS),
286  	OCELOT_STAT(RX_PMAC_SYM_ERRS),
287  	OCELOT_STAT(RX_PMAC_64),
288  	OCELOT_STAT(RX_PMAC_65_127),
289  	OCELOT_STAT(RX_PMAC_128_255),
290  	OCELOT_STAT(RX_PMAC_256_511),
291  	OCELOT_STAT(RX_PMAC_512_1023),
292  	OCELOT_STAT(RX_PMAC_1024_1526),
293  	OCELOT_STAT(RX_PMAC_1527_MAX),
294  	OCELOT_STAT(RX_PMAC_PAUSE),
295  	OCELOT_STAT(RX_PMAC_CONTROL),
296  	OCELOT_STAT(RX_PMAC_LONGS),
297  	OCELOT_STAT(TX_PMAC_OCTETS),
298  	OCELOT_STAT(TX_PMAC_UNICAST),
299  	OCELOT_STAT(TX_PMAC_MULTICAST),
300  	OCELOT_STAT(TX_PMAC_BROADCAST),
301  	OCELOT_STAT(TX_PMAC_PAUSE),
302  	OCELOT_STAT(TX_PMAC_64),
303  	OCELOT_STAT(TX_PMAC_65_127),
304  	OCELOT_STAT(TX_PMAC_128_255),
305  	OCELOT_STAT(TX_PMAC_256_511),
306  	OCELOT_STAT(TX_PMAC_512_1023),
307  	OCELOT_STAT(TX_PMAC_1024_1526),
308  	OCELOT_STAT(TX_PMAC_1527_MAX),
309  };
310  
311  static const struct ocelot_stat_layout *
ocelot_get_stats_layout(struct ocelot * ocelot)312  ocelot_get_stats_layout(struct ocelot *ocelot)
313  {
314  	if (ocelot->mm_supported)
315  		return ocelot_mm_stats_layout;
316  
317  	return ocelot_stats_layout;
318  }
319  
320  /* Read the counters from hardware and keep them in region->buf.
321   * Caller must hold &ocelot->stat_view_lock.
322   */
ocelot_port_update_stats(struct ocelot * ocelot,int port)323  static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
324  {
325  	struct ocelot_stats_region *region;
326  	int err;
327  
328  	/* Configure the port to read the stats from */
329  	ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG);
330  
331  	list_for_each_entry(region, &ocelot->stats_regions, node) {
332  		err = ocelot_bulk_read(ocelot, region->base, region->buf,
333  				       region->count);
334  		if (err)
335  			return err;
336  	}
337  
338  	return 0;
339  }
340  
341  /* Transfer the counters from region->buf to ocelot->stats.
342   * Caller must hold &ocelot->stat_view_lock and &ocelot->stats_lock.
343   */
ocelot_port_transfer_stats(struct ocelot * ocelot,int port)344  static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
345  {
346  	struct ocelot_stats_region *region;
347  	int j;
348  
349  	list_for_each_entry(region, &ocelot->stats_regions, node) {
350  		unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat;
351  
352  		for (j = 0; j < region->count; j++) {
353  			u64 *stat = &ocelot->stats[idx + j];
354  			u64 val = region->buf[j];
355  
356  			if (val < (*stat & U32_MAX))
357  				*stat += (u64)1 << 32;
358  
359  			*stat = (*stat & ~(u64)U32_MAX) + val;
360  		}
361  	}
362  }
363  
ocelot_check_stats_work(struct work_struct * work)364  static void ocelot_check_stats_work(struct work_struct *work)
365  {
366  	struct delayed_work *del_work = to_delayed_work(work);
367  	struct ocelot *ocelot = container_of(del_work, struct ocelot,
368  					     stats_work);
369  	int port, err;
370  
371  	mutex_lock(&ocelot->stat_view_lock);
372  
373  	for (port = 0; port < ocelot->num_phys_ports; port++) {
374  		err = ocelot_port_update_stats(ocelot, port);
375  		if (err)
376  			break;
377  
378  		spin_lock(&ocelot->stats_lock);
379  		ocelot_port_transfer_stats(ocelot, port);
380  		spin_unlock(&ocelot->stats_lock);
381  	}
382  
383  	if (!err && ocelot->ops->update_stats)
384  		ocelot->ops->update_stats(ocelot);
385  
386  	mutex_unlock(&ocelot->stat_view_lock);
387  
388  	if (err)
389  		dev_err(ocelot->dev, "Error %d updating ethtool stats\n",  err);
390  
391  	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
392  			   OCELOT_STATS_CHECK_DELAY);
393  }
394  
ocelot_get_strings(struct ocelot * ocelot,int port,u32 sset,u8 * data)395  void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
396  {
397  	const struct ocelot_stat_layout *layout;
398  	enum ocelot_stat i;
399  
400  	if (sset != ETH_SS_STATS)
401  		return;
402  
403  	layout = ocelot_get_stats_layout(ocelot);
404  
405  	for (i = 0; i < OCELOT_NUM_STATS; i++) {
406  		if (layout[i].name[0] == '\0')
407  			continue;
408  
409  		memcpy(data, layout[i].name, ETH_GSTRING_LEN);
410  		data += ETH_GSTRING_LEN;
411  	}
412  }
413  EXPORT_SYMBOL(ocelot_get_strings);
414  
415  /* Update ocelot->stats for the given port and run the given callback */
ocelot_port_stats_run(struct ocelot * ocelot,int port,void * priv,void (* cb)(struct ocelot * ocelot,int port,void * priv))416  static void ocelot_port_stats_run(struct ocelot *ocelot, int port, void *priv,
417  				  void (*cb)(struct ocelot *ocelot, int port,
418  					     void *priv))
419  {
420  	int err;
421  
422  	mutex_lock(&ocelot->stat_view_lock);
423  
424  	err = ocelot_port_update_stats(ocelot, port);
425  	if (err) {
426  		dev_err(ocelot->dev, "Failed to update port %d stats: %pe\n",
427  			port, ERR_PTR(err));
428  		goto out_unlock;
429  	}
430  
431  	spin_lock(&ocelot->stats_lock);
432  
433  	ocelot_port_transfer_stats(ocelot, port);
434  	cb(ocelot, port, priv);
435  
436  	spin_unlock(&ocelot->stats_lock);
437  
438  out_unlock:
439  	mutex_unlock(&ocelot->stat_view_lock);
440  }
441  
ocelot_get_sset_count(struct ocelot * ocelot,int port,int sset)442  int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
443  {
444  	const struct ocelot_stat_layout *layout;
445  	enum ocelot_stat i;
446  	int num_stats = 0;
447  
448  	if (sset != ETH_SS_STATS)
449  		return -EOPNOTSUPP;
450  
451  	layout = ocelot_get_stats_layout(ocelot);
452  
453  	for (i = 0; i < OCELOT_NUM_STATS; i++)
454  		if (layout[i].name[0] != '\0')
455  			num_stats++;
456  
457  	return num_stats;
458  }
459  EXPORT_SYMBOL(ocelot_get_sset_count);
460  
ocelot_port_ethtool_stats_cb(struct ocelot * ocelot,int port,void * priv)461  static void ocelot_port_ethtool_stats_cb(struct ocelot *ocelot, int port,
462  					 void *priv)
463  {
464  	const struct ocelot_stat_layout *layout;
465  	enum ocelot_stat i;
466  	u64 *data = priv;
467  
468  	layout = ocelot_get_stats_layout(ocelot);
469  
470  	/* Copy all supported counters */
471  	for (i = 0; i < OCELOT_NUM_STATS; i++) {
472  		int index = port * OCELOT_NUM_STATS + i;
473  
474  		if (layout[i].name[0] == '\0')
475  			continue;
476  
477  		*data++ = ocelot->stats[index];
478  	}
479  }
480  
ocelot_get_ethtool_stats(struct ocelot * ocelot,int port,u64 * data)481  void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
482  {
483  	ocelot_port_stats_run(ocelot, port, data, ocelot_port_ethtool_stats_cb);
484  }
485  EXPORT_SYMBOL(ocelot_get_ethtool_stats);
486  
ocelot_port_pause_stats_cb(struct ocelot * ocelot,int port,void * priv)487  static void ocelot_port_pause_stats_cb(struct ocelot *ocelot, int port, void *priv)
488  {
489  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
490  	struct ethtool_pause_stats *pause_stats = priv;
491  
492  	pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PAUSE];
493  	pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PAUSE];
494  }
495  
ocelot_port_pmac_pause_stats_cb(struct ocelot * ocelot,int port,void * priv)496  static void ocelot_port_pmac_pause_stats_cb(struct ocelot *ocelot, int port,
497  					    void *priv)
498  {
499  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
500  	struct ethtool_pause_stats *pause_stats = priv;
501  
502  	pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PMAC_PAUSE];
503  	pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PMAC_PAUSE];
504  }
505  
ocelot_port_mm_stats_cb(struct ocelot * ocelot,int port,void * priv)506  static void ocelot_port_mm_stats_cb(struct ocelot *ocelot, int port,
507  				    void *priv)
508  {
509  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
510  	struct ethtool_mm_stats *stats = priv;
511  
512  	stats->MACMergeFrameAssErrorCount = s[OCELOT_STAT_RX_ASSEMBLY_ERRS];
513  	stats->MACMergeFrameSmdErrorCount = s[OCELOT_STAT_RX_SMD_ERRS];
514  	stats->MACMergeFrameAssOkCount = s[OCELOT_STAT_RX_ASSEMBLY_OK];
515  	stats->MACMergeFragCountRx = s[OCELOT_STAT_RX_MERGE_FRAGMENTS];
516  	stats->MACMergeFragCountTx = s[OCELOT_STAT_TX_MERGE_FRAGMENTS];
517  	stats->MACMergeHoldCount = s[OCELOT_STAT_TX_MM_HOLD];
518  }
519  
ocelot_port_get_pause_stats(struct ocelot * ocelot,int port,struct ethtool_pause_stats * pause_stats)520  void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port,
521  				 struct ethtool_pause_stats *pause_stats)
522  {
523  	struct net_device *dev;
524  
525  	switch (pause_stats->src) {
526  	case ETHTOOL_MAC_STATS_SRC_EMAC:
527  		ocelot_port_stats_run(ocelot, port, pause_stats,
528  				      ocelot_port_pause_stats_cb);
529  		break;
530  	case ETHTOOL_MAC_STATS_SRC_PMAC:
531  		if (ocelot->mm_supported)
532  			ocelot_port_stats_run(ocelot, port, pause_stats,
533  					      ocelot_port_pmac_pause_stats_cb);
534  		break;
535  	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
536  		dev = ocelot->ops->port_to_netdev(ocelot, port);
537  		ethtool_aggregate_pause_stats(dev, pause_stats);
538  		break;
539  	}
540  }
541  EXPORT_SYMBOL_GPL(ocelot_port_get_pause_stats);
542  
ocelot_port_get_mm_stats(struct ocelot * ocelot,int port,struct ethtool_mm_stats * stats)543  void ocelot_port_get_mm_stats(struct ocelot *ocelot, int port,
544  			      struct ethtool_mm_stats *stats)
545  {
546  	if (!ocelot->mm_supported)
547  		return;
548  
549  	ocelot_port_stats_run(ocelot, port, stats, ocelot_port_mm_stats_cb);
550  }
551  EXPORT_SYMBOL_GPL(ocelot_port_get_mm_stats);
552  
553  static const struct ethtool_rmon_hist_range ocelot_rmon_ranges[] = {
554  	{   64,    64 },
555  	{   65,   127 },
556  	{  128,   255 },
557  	{  256,   511 },
558  	{  512,  1023 },
559  	{ 1024,  1526 },
560  	{ 1527, 65535 },
561  	{},
562  };
563  
ocelot_port_rmon_stats_cb(struct ocelot * ocelot,int port,void * priv)564  static void ocelot_port_rmon_stats_cb(struct ocelot *ocelot, int port, void *priv)
565  {
566  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
567  	struct ethtool_rmon_stats *rmon_stats = priv;
568  
569  	rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_SHORTS];
570  	rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_LONGS];
571  	rmon_stats->fragments = s[OCELOT_STAT_RX_FRAGMENTS];
572  	rmon_stats->jabbers = s[OCELOT_STAT_RX_JABBERS];
573  
574  	rmon_stats->hist[0] = s[OCELOT_STAT_RX_64];
575  	rmon_stats->hist[1] = s[OCELOT_STAT_RX_65_127];
576  	rmon_stats->hist[2] = s[OCELOT_STAT_RX_128_255];
577  	rmon_stats->hist[3] = s[OCELOT_STAT_RX_256_511];
578  	rmon_stats->hist[4] = s[OCELOT_STAT_RX_512_1023];
579  	rmon_stats->hist[5] = s[OCELOT_STAT_RX_1024_1526];
580  	rmon_stats->hist[6] = s[OCELOT_STAT_RX_1527_MAX];
581  
582  	rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_64];
583  	rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_65_127];
584  	rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_128_255];
585  	rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_256_511];
586  	rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_512_1023];
587  	rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_1024_1526];
588  	rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_1527_MAX];
589  }
590  
ocelot_port_pmac_rmon_stats_cb(struct ocelot * ocelot,int port,void * priv)591  static void ocelot_port_pmac_rmon_stats_cb(struct ocelot *ocelot, int port,
592  					   void *priv)
593  {
594  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
595  	struct ethtool_rmon_stats *rmon_stats = priv;
596  
597  	rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_PMAC_SHORTS];
598  	rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_PMAC_LONGS];
599  	rmon_stats->fragments = s[OCELOT_STAT_RX_PMAC_FRAGMENTS];
600  	rmon_stats->jabbers = s[OCELOT_STAT_RX_PMAC_JABBERS];
601  
602  	rmon_stats->hist[0] = s[OCELOT_STAT_RX_PMAC_64];
603  	rmon_stats->hist[1] = s[OCELOT_STAT_RX_PMAC_65_127];
604  	rmon_stats->hist[2] = s[OCELOT_STAT_RX_PMAC_128_255];
605  	rmon_stats->hist[3] = s[OCELOT_STAT_RX_PMAC_256_511];
606  	rmon_stats->hist[4] = s[OCELOT_STAT_RX_PMAC_512_1023];
607  	rmon_stats->hist[5] = s[OCELOT_STAT_RX_PMAC_1024_1526];
608  	rmon_stats->hist[6] = s[OCELOT_STAT_RX_PMAC_1527_MAX];
609  
610  	rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_PMAC_64];
611  	rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_PMAC_65_127];
612  	rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_PMAC_128_255];
613  	rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_PMAC_256_511];
614  	rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_PMAC_512_1023];
615  	rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_PMAC_1024_1526];
616  	rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_PMAC_1527_MAX];
617  }
618  
ocelot_port_get_rmon_stats(struct ocelot * ocelot,int port,struct ethtool_rmon_stats * rmon_stats,const struct ethtool_rmon_hist_range ** ranges)619  void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port,
620  				struct ethtool_rmon_stats *rmon_stats,
621  				const struct ethtool_rmon_hist_range **ranges)
622  {
623  	struct net_device *dev;
624  
625  	*ranges = ocelot_rmon_ranges;
626  
627  	switch (rmon_stats->src) {
628  	case ETHTOOL_MAC_STATS_SRC_EMAC:
629  		ocelot_port_stats_run(ocelot, port, rmon_stats,
630  				      ocelot_port_rmon_stats_cb);
631  		break;
632  	case ETHTOOL_MAC_STATS_SRC_PMAC:
633  		if (ocelot->mm_supported)
634  			ocelot_port_stats_run(ocelot, port, rmon_stats,
635  					      ocelot_port_pmac_rmon_stats_cb);
636  		break;
637  	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
638  		dev = ocelot->ops->port_to_netdev(ocelot, port);
639  		ethtool_aggregate_rmon_stats(dev, rmon_stats);
640  		break;
641  	}
642  }
643  EXPORT_SYMBOL_GPL(ocelot_port_get_rmon_stats);
644  
ocelot_port_ctrl_stats_cb(struct ocelot * ocelot,int port,void * priv)645  static void ocelot_port_ctrl_stats_cb(struct ocelot *ocelot, int port, void *priv)
646  {
647  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
648  	struct ethtool_eth_ctrl_stats *ctrl_stats = priv;
649  
650  	ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_CONTROL];
651  }
652  
ocelot_port_pmac_ctrl_stats_cb(struct ocelot * ocelot,int port,void * priv)653  static void ocelot_port_pmac_ctrl_stats_cb(struct ocelot *ocelot, int port,
654  					   void *priv)
655  {
656  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
657  	struct ethtool_eth_ctrl_stats *ctrl_stats = priv;
658  
659  	ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_PMAC_CONTROL];
660  }
661  
ocelot_port_get_eth_ctrl_stats(struct ocelot * ocelot,int port,struct ethtool_eth_ctrl_stats * ctrl_stats)662  void ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port,
663  				    struct ethtool_eth_ctrl_stats *ctrl_stats)
664  {
665  	struct net_device *dev;
666  
667  	switch (ctrl_stats->src) {
668  	case ETHTOOL_MAC_STATS_SRC_EMAC:
669  		ocelot_port_stats_run(ocelot, port, ctrl_stats,
670  				      ocelot_port_ctrl_stats_cb);
671  		break;
672  	case ETHTOOL_MAC_STATS_SRC_PMAC:
673  		if (ocelot->mm_supported)
674  			ocelot_port_stats_run(ocelot, port, ctrl_stats,
675  					      ocelot_port_pmac_ctrl_stats_cb);
676  		break;
677  	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
678  		dev = ocelot->ops->port_to_netdev(ocelot, port);
679  		ethtool_aggregate_ctrl_stats(dev, ctrl_stats);
680  		break;
681  	}
682  }
683  EXPORT_SYMBOL_GPL(ocelot_port_get_eth_ctrl_stats);
684  
ocelot_port_mac_stats_cb(struct ocelot * ocelot,int port,void * priv)685  static void ocelot_port_mac_stats_cb(struct ocelot *ocelot, int port, void *priv)
686  {
687  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
688  	struct ethtool_eth_mac_stats *mac_stats = priv;
689  
690  	mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_OCTETS];
691  	mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_64] +
692  					 s[OCELOT_STAT_TX_65_127] +
693  					 s[OCELOT_STAT_TX_128_255] +
694  					 s[OCELOT_STAT_TX_256_511] +
695  					 s[OCELOT_STAT_TX_512_1023] +
696  					 s[OCELOT_STAT_TX_1024_1526] +
697  					 s[OCELOT_STAT_TX_1527_MAX];
698  	mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_OCTETS];
699  	mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_GREEN_PRIO_0] +
700  				      s[OCELOT_STAT_RX_GREEN_PRIO_1] +
701  				      s[OCELOT_STAT_RX_GREEN_PRIO_2] +
702  				      s[OCELOT_STAT_RX_GREEN_PRIO_3] +
703  				      s[OCELOT_STAT_RX_GREEN_PRIO_4] +
704  				      s[OCELOT_STAT_RX_GREEN_PRIO_5] +
705  				      s[OCELOT_STAT_RX_GREEN_PRIO_6] +
706  				      s[OCELOT_STAT_RX_GREEN_PRIO_7] +
707  				      s[OCELOT_STAT_RX_YELLOW_PRIO_0] +
708  				      s[OCELOT_STAT_RX_YELLOW_PRIO_1] +
709  				      s[OCELOT_STAT_RX_YELLOW_PRIO_2] +
710  				      s[OCELOT_STAT_RX_YELLOW_PRIO_3] +
711  				      s[OCELOT_STAT_RX_YELLOW_PRIO_4] +
712  				      s[OCELOT_STAT_RX_YELLOW_PRIO_5] +
713  				      s[OCELOT_STAT_RX_YELLOW_PRIO_6] +
714  				      s[OCELOT_STAT_RX_YELLOW_PRIO_7];
715  	mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_MULTICAST];
716  	mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_BROADCAST];
717  	mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_MULTICAST];
718  	mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_BROADCAST];
719  	mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_LONGS];
720  	/* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not
721  	 * counted individually.
722  	 */
723  	mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS];
724  	mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS];
725  }
726  
ocelot_port_pmac_mac_stats_cb(struct ocelot * ocelot,int port,void * priv)727  static void ocelot_port_pmac_mac_stats_cb(struct ocelot *ocelot, int port,
728  					  void *priv)
729  {
730  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
731  	struct ethtool_eth_mac_stats *mac_stats = priv;
732  
733  	mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_PMAC_OCTETS];
734  	mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_PMAC_64] +
735  					 s[OCELOT_STAT_TX_PMAC_65_127] +
736  					 s[OCELOT_STAT_TX_PMAC_128_255] +
737  					 s[OCELOT_STAT_TX_PMAC_256_511] +
738  					 s[OCELOT_STAT_TX_PMAC_512_1023] +
739  					 s[OCELOT_STAT_TX_PMAC_1024_1526] +
740  					 s[OCELOT_STAT_TX_PMAC_1527_MAX];
741  	mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_PMAC_OCTETS];
742  	mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_PMAC_64] +
743  				      s[OCELOT_STAT_RX_PMAC_65_127] +
744  				      s[OCELOT_STAT_RX_PMAC_128_255] +
745  				      s[OCELOT_STAT_RX_PMAC_256_511] +
746  				      s[OCELOT_STAT_RX_PMAC_512_1023] +
747  				      s[OCELOT_STAT_RX_PMAC_1024_1526] +
748  				      s[OCELOT_STAT_RX_PMAC_1527_MAX];
749  	mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_MULTICAST];
750  	mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_BROADCAST];
751  	mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_MULTICAST];
752  	mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_BROADCAST];
753  	mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_PMAC_LONGS];
754  	/* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not
755  	 * counted individually.
756  	 */
757  	mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS];
758  	mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS];
759  }
760  
ocelot_port_get_eth_mac_stats(struct ocelot * ocelot,int port,struct ethtool_eth_mac_stats * mac_stats)761  void ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port,
762  				   struct ethtool_eth_mac_stats *mac_stats)
763  {
764  	struct net_device *dev;
765  
766  	switch (mac_stats->src) {
767  	case ETHTOOL_MAC_STATS_SRC_EMAC:
768  		ocelot_port_stats_run(ocelot, port, mac_stats,
769  				      ocelot_port_mac_stats_cb);
770  		break;
771  	case ETHTOOL_MAC_STATS_SRC_PMAC:
772  		if (ocelot->mm_supported)
773  			ocelot_port_stats_run(ocelot, port, mac_stats,
774  					      ocelot_port_pmac_mac_stats_cb);
775  		break;
776  	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
777  		dev = ocelot->ops->port_to_netdev(ocelot, port);
778  		ethtool_aggregate_mac_stats(dev, mac_stats);
779  		break;
780  	}
781  }
782  EXPORT_SYMBOL_GPL(ocelot_port_get_eth_mac_stats);
783  
ocelot_port_phy_stats_cb(struct ocelot * ocelot,int port,void * priv)784  static void ocelot_port_phy_stats_cb(struct ocelot *ocelot, int port, void *priv)
785  {
786  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
787  	struct ethtool_eth_phy_stats *phy_stats = priv;
788  
789  	phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_SYM_ERRS];
790  }
791  
ocelot_port_pmac_phy_stats_cb(struct ocelot * ocelot,int port,void * priv)792  static void ocelot_port_pmac_phy_stats_cb(struct ocelot *ocelot, int port,
793  					  void *priv)
794  {
795  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
796  	struct ethtool_eth_phy_stats *phy_stats = priv;
797  
798  	phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_PMAC_SYM_ERRS];
799  }
800  
ocelot_port_get_eth_phy_stats(struct ocelot * ocelot,int port,struct ethtool_eth_phy_stats * phy_stats)801  void ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port,
802  				   struct ethtool_eth_phy_stats *phy_stats)
803  {
804  	struct net_device *dev;
805  
806  	switch (phy_stats->src) {
807  	case ETHTOOL_MAC_STATS_SRC_EMAC:
808  		ocelot_port_stats_run(ocelot, port, phy_stats,
809  				      ocelot_port_phy_stats_cb);
810  		break;
811  	case ETHTOOL_MAC_STATS_SRC_PMAC:
812  		if (ocelot->mm_supported)
813  			ocelot_port_stats_run(ocelot, port, phy_stats,
814  					      ocelot_port_pmac_phy_stats_cb);
815  		break;
816  	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
817  		dev = ocelot->ops->port_to_netdev(ocelot, port);
818  		ethtool_aggregate_phy_stats(dev, phy_stats);
819  		break;
820  	}
821  }
822  EXPORT_SYMBOL_GPL(ocelot_port_get_eth_phy_stats);
823  
ocelot_port_get_stats64(struct ocelot * ocelot,int port,struct rtnl_link_stats64 * stats)824  void ocelot_port_get_stats64(struct ocelot *ocelot, int port,
825  			     struct rtnl_link_stats64 *stats)
826  {
827  	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
828  
829  	spin_lock(&ocelot->stats_lock);
830  
831  	/* Get Rx stats */
832  	stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS];
833  	stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] +
834  			    s[OCELOT_STAT_RX_FRAGMENTS] +
835  			    s[OCELOT_STAT_RX_JABBERS] +
836  			    s[OCELOT_STAT_RX_LONGS] +
837  			    s[OCELOT_STAT_RX_64] +
838  			    s[OCELOT_STAT_RX_65_127] +
839  			    s[OCELOT_STAT_RX_128_255] +
840  			    s[OCELOT_STAT_RX_256_511] +
841  			    s[OCELOT_STAT_RX_512_1023] +
842  			    s[OCELOT_STAT_RX_1024_1526] +
843  			    s[OCELOT_STAT_RX_1527_MAX];
844  	stats->multicast = s[OCELOT_STAT_RX_MULTICAST];
845  	stats->rx_missed_errors = s[OCELOT_STAT_DROP_TAIL];
846  	stats->rx_dropped = s[OCELOT_STAT_RX_RED_PRIO_0] +
847  			    s[OCELOT_STAT_RX_RED_PRIO_1] +
848  			    s[OCELOT_STAT_RX_RED_PRIO_2] +
849  			    s[OCELOT_STAT_RX_RED_PRIO_3] +
850  			    s[OCELOT_STAT_RX_RED_PRIO_4] +
851  			    s[OCELOT_STAT_RX_RED_PRIO_5] +
852  			    s[OCELOT_STAT_RX_RED_PRIO_6] +
853  			    s[OCELOT_STAT_RX_RED_PRIO_7] +
854  			    s[OCELOT_STAT_DROP_LOCAL] +
855  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_0] +
856  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_1] +
857  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_2] +
858  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_3] +
859  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_4] +
860  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_5] +
861  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_6] +
862  			    s[OCELOT_STAT_DROP_YELLOW_PRIO_7] +
863  			    s[OCELOT_STAT_DROP_GREEN_PRIO_0] +
864  			    s[OCELOT_STAT_DROP_GREEN_PRIO_1] +
865  			    s[OCELOT_STAT_DROP_GREEN_PRIO_2] +
866  			    s[OCELOT_STAT_DROP_GREEN_PRIO_3] +
867  			    s[OCELOT_STAT_DROP_GREEN_PRIO_4] +
868  			    s[OCELOT_STAT_DROP_GREEN_PRIO_5] +
869  			    s[OCELOT_STAT_DROP_GREEN_PRIO_6] +
870  			    s[OCELOT_STAT_DROP_GREEN_PRIO_7];
871  
872  	/* Get Tx stats */
873  	stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS];
874  	stats->tx_packets = s[OCELOT_STAT_TX_64] +
875  			    s[OCELOT_STAT_TX_65_127] +
876  			    s[OCELOT_STAT_TX_128_255] +
877  			    s[OCELOT_STAT_TX_256_511] +
878  			    s[OCELOT_STAT_TX_512_1023] +
879  			    s[OCELOT_STAT_TX_1024_1526] +
880  			    s[OCELOT_STAT_TX_1527_MAX];
881  	stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] +
882  			    s[OCELOT_STAT_TX_AGED];
883  	stats->collisions = s[OCELOT_STAT_TX_COLLISION];
884  
885  	spin_unlock(&ocelot->stats_lock);
886  }
887  EXPORT_SYMBOL(ocelot_port_get_stats64);
888  
ocelot_prepare_stats_regions(struct ocelot * ocelot)889  static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
890  {
891  	struct ocelot_stats_region *region = NULL;
892  	const struct ocelot_stat_layout *layout;
893  	enum ocelot_reg last = 0;
894  	enum ocelot_stat i;
895  
896  	INIT_LIST_HEAD(&ocelot->stats_regions);
897  
898  	layout = ocelot_get_stats_layout(ocelot);
899  
900  	for (i = 0; i < OCELOT_NUM_STATS; i++) {
901  		if (!layout[i].reg)
902  			continue;
903  
904  		/* enum ocelot_stat must be kept sorted in the same order
905  		 * as the addresses behind layout[i].reg in order to have
906  		 * efficient bulking
907  		 */
908  		if (last) {
909  			WARN(ocelot->map[SYS][last & REG_MASK] >= ocelot->map[SYS][layout[i].reg & REG_MASK],
910  			     "reg 0x%x had address 0x%x but reg 0x%x has address 0x%x, bulking broken!",
911  			     last, ocelot->map[SYS][last & REG_MASK],
912  			     layout[i].reg, ocelot->map[SYS][layout[i].reg & REG_MASK]);
913  		}
914  
915  		if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] ==
916  		    ocelot->map[SYS][last & REG_MASK] + 4) {
917  			region->count++;
918  		} else {
919  			region = devm_kzalloc(ocelot->dev, sizeof(*region),
920  					      GFP_KERNEL);
921  			if (!region)
922  				return -ENOMEM;
923  
924  			region->base = layout[i].reg;
925  			region->first_stat = i;
926  			region->count = 1;
927  			list_add_tail(&region->node, &ocelot->stats_regions);
928  		}
929  
930  		last = layout[i].reg;
931  	}
932  
933  	list_for_each_entry(region, &ocelot->stats_regions, node) {
934  		enum ocelot_target target;
935  		u32 addr;
936  
937  		ocelot_reg_to_target_addr(ocelot, region->base, &target,
938  					  &addr);
939  
940  		dev_dbg(ocelot->dev,
941  			"region of %d contiguous counters starting with SYS:STAT:CNT[0x%03x]\n",
942  			region->count, addr / 4);
943  		region->buf = devm_kcalloc(ocelot->dev, region->count,
944  					   sizeof(*region->buf), GFP_KERNEL);
945  		if (!region->buf)
946  			return -ENOMEM;
947  	}
948  
949  	return 0;
950  }
951  
ocelot_stats_init(struct ocelot * ocelot)952  int ocelot_stats_init(struct ocelot *ocelot)
953  {
954  	char queue_name[32];
955  	int ret;
956  
957  	ocelot->stats = devm_kcalloc(ocelot->dev,
958  				     ocelot->num_phys_ports * OCELOT_NUM_STATS,
959  				     sizeof(u64), GFP_KERNEL);
960  	if (!ocelot->stats)
961  		return -ENOMEM;
962  
963  	snprintf(queue_name, sizeof(queue_name), "%s-stats",
964  		 dev_name(ocelot->dev));
965  	ocelot->stats_queue = create_singlethread_workqueue(queue_name);
966  	if (!ocelot->stats_queue)
967  		return -ENOMEM;
968  
969  	spin_lock_init(&ocelot->stats_lock);
970  	mutex_init(&ocelot->stat_view_lock);
971  
972  	ret = ocelot_prepare_stats_regions(ocelot);
973  	if (ret) {
974  		destroy_workqueue(ocelot->stats_queue);
975  		return ret;
976  	}
977  
978  	INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
979  	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
980  			   OCELOT_STATS_CHECK_DELAY);
981  
982  	return 0;
983  }
984  
ocelot_stats_deinit(struct ocelot * ocelot)985  void ocelot_stats_deinit(struct ocelot *ocelot)
986  {
987  	cancel_delayed_work(&ocelot->stats_work);
988  	destroy_workqueue(ocelot->stats_queue);
989  }
990