Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0+
  2
  3#include <linux/netdevice.h>
  4
  5#include "lan966x_main.h"
  6
  7/* Number of traffic classes */
  8#define LAN966X_NUM_TC			8
  9#define LAN966X_STATS_CHECK_DELAY	(2 * HZ)
 10
 11static const struct lan966x_stat_layout lan966x_stats_layout[] = {
 12	{ .name = "rx_octets", .offset = 0x00, },
 13	{ .name = "rx_unicast", .offset = 0x01, },
 14	{ .name = "rx_multicast", .offset = 0x02 },
 15	{ .name = "rx_broadcast", .offset = 0x03 },
 16	{ .name = "rx_short", .offset = 0x04 },
 17	{ .name = "rx_frag", .offset = 0x05 },
 18	{ .name = "rx_jabber", .offset = 0x06 },
 19	{ .name = "rx_crc", .offset = 0x07 },
 20	{ .name = "rx_symbol_err", .offset = 0x08 },
 21	{ .name = "rx_sz_64", .offset = 0x09 },
 22	{ .name = "rx_sz_65_127", .offset = 0x0a},
 23	{ .name = "rx_sz_128_255", .offset = 0x0b},
 24	{ .name = "rx_sz_256_511", .offset = 0x0c },
 25	{ .name = "rx_sz_512_1023", .offset = 0x0d },
 26	{ .name = "rx_sz_1024_1526", .offset = 0x0e },
 27	{ .name = "rx_sz_jumbo", .offset = 0x0f },
 28	{ .name = "rx_pause", .offset = 0x10 },
 29	{ .name = "rx_control", .offset = 0x11 },
 30	{ .name = "rx_long", .offset = 0x12 },
 31	{ .name = "rx_cat_drop", .offset = 0x13 },
 32	{ .name = "rx_red_prio_0", .offset = 0x14 },
 33	{ .name = "rx_red_prio_1", .offset = 0x15 },
 34	{ .name = "rx_red_prio_2", .offset = 0x16 },
 35	{ .name = "rx_red_prio_3", .offset = 0x17 },
 36	{ .name = "rx_red_prio_4", .offset = 0x18 },
 37	{ .name = "rx_red_prio_5", .offset = 0x19 },
 38	{ .name = "rx_red_prio_6", .offset = 0x1a },
 39	{ .name = "rx_red_prio_7", .offset = 0x1b },
 40	{ .name = "rx_yellow_prio_0", .offset = 0x1c },
 41	{ .name = "rx_yellow_prio_1", .offset = 0x1d },
 42	{ .name = "rx_yellow_prio_2", .offset = 0x1e },
 43	{ .name = "rx_yellow_prio_3", .offset = 0x1f },
 44	{ .name = "rx_yellow_prio_4", .offset = 0x20 },
 45	{ .name = "rx_yellow_prio_5", .offset = 0x21 },
 46	{ .name = "rx_yellow_prio_6", .offset = 0x22 },
 47	{ .name = "rx_yellow_prio_7", .offset = 0x23 },
 48	{ .name = "rx_green_prio_0", .offset = 0x24 },
 49	{ .name = "rx_green_prio_1", .offset = 0x25 },
 50	{ .name = "rx_green_prio_2", .offset = 0x26 },
 51	{ .name = "rx_green_prio_3", .offset = 0x27 },
 52	{ .name = "rx_green_prio_4", .offset = 0x28 },
 53	{ .name = "rx_green_prio_5", .offset = 0x29 },
 54	{ .name = "rx_green_prio_6", .offset = 0x2a },
 55	{ .name = "rx_green_prio_7", .offset = 0x2b },
 56	{ .name = "rx_assembly_err", .offset = 0x2c },
 57	{ .name = "rx_smd_err", .offset = 0x2d },
 58	{ .name = "rx_assembly_ok", .offset = 0x2e },
 59	{ .name = "rx_merge_frag", .offset = 0x2f },
 60	{ .name = "rx_pmac_octets", .offset = 0x30, },
 61	{ .name = "rx_pmac_unicast", .offset = 0x31, },
 62	{ .name = "rx_pmac_multicast", .offset = 0x32 },
 63	{ .name = "rx_pmac_broadcast", .offset = 0x33 },
 64	{ .name = "rx_pmac_short", .offset = 0x34 },
 65	{ .name = "rx_pmac_frag", .offset = 0x35 },
 66	{ .name = "rx_pmac_jabber", .offset = 0x36 },
 67	{ .name = "rx_pmac_crc", .offset = 0x37 },
 68	{ .name = "rx_pmac_symbol_err", .offset = 0x38 },
 69	{ .name = "rx_pmac_sz_64", .offset = 0x39 },
 70	{ .name = "rx_pmac_sz_65_127", .offset = 0x3a },
 71	{ .name = "rx_pmac_sz_128_255", .offset = 0x3b },
 72	{ .name = "rx_pmac_sz_256_511", .offset = 0x3c },
 73	{ .name = "rx_pmac_sz_512_1023", .offset = 0x3d },
 74	{ .name = "rx_pmac_sz_1024_1526", .offset = 0x3e },
 75	{ .name = "rx_pmac_sz_jumbo", .offset = 0x3f },
 76	{ .name = "rx_pmac_pause", .offset = 0x40 },
 77	{ .name = "rx_pmac_control", .offset = 0x41 },
 78	{ .name = "rx_pmac_long", .offset = 0x42 },
 79
 80	{ .name = "tx_octets", .offset = 0x80, },
 81	{ .name = "tx_unicast", .offset = 0x81, },
 82	{ .name = "tx_multicast", .offset = 0x82 },
 83	{ .name = "tx_broadcast", .offset = 0x83 },
 84	{ .name = "tx_col", .offset = 0x84 },
 85	{ .name = "tx_drop", .offset = 0x85 },
 86	{ .name = "tx_pause", .offset = 0x86 },
 87	{ .name = "tx_sz_64", .offset = 0x87 },
 88	{ .name = "tx_sz_65_127", .offset = 0x88 },
 89	{ .name = "tx_sz_128_255", .offset = 0x89 },
 90	{ .name = "tx_sz_256_511", .offset = 0x8a },
 91	{ .name = "tx_sz_512_1023", .offset = 0x8b },
 92	{ .name = "tx_sz_1024_1526", .offset = 0x8c },
 93	{ .name = "tx_sz_jumbo", .offset = 0x8d },
 94	{ .name = "tx_yellow_prio_0", .offset = 0x8e },
 95	{ .name = "tx_yellow_prio_1", .offset = 0x8f },
 96	{ .name = "tx_yellow_prio_2", .offset = 0x90 },
 97	{ .name = "tx_yellow_prio_3", .offset = 0x91 },
 98	{ .name = "tx_yellow_prio_4", .offset = 0x92 },
 99	{ .name = "tx_yellow_prio_5", .offset = 0x93 },
100	{ .name = "tx_yellow_prio_6", .offset = 0x94 },
101	{ .name = "tx_yellow_prio_7", .offset = 0x95 },
102	{ .name = "tx_green_prio_0", .offset = 0x96 },
103	{ .name = "tx_green_prio_1", .offset = 0x97 },
104	{ .name = "tx_green_prio_2", .offset = 0x98 },
105	{ .name = "tx_green_prio_3", .offset = 0x99 },
106	{ .name = "tx_green_prio_4", .offset = 0x9a },
107	{ .name = "tx_green_prio_5", .offset = 0x9b },
108	{ .name = "tx_green_prio_6", .offset = 0x9c },
109	{ .name = "tx_green_prio_7", .offset = 0x9d },
110	{ .name = "tx_aged", .offset = 0x9e },
111	{ .name = "tx_llct", .offset = 0x9f },
112	{ .name = "tx_ct", .offset = 0xa0 },
113	{ .name = "tx_mm_hold", .offset = 0xa1 },
114	{ .name = "tx_merge_frag", .offset = 0xa2 },
115	{ .name = "tx_pmac_octets", .offset = 0xa3, },
116	{ .name = "tx_pmac_unicast", .offset = 0xa4, },
117	{ .name = "tx_pmac_multicast", .offset = 0xa5 },
118	{ .name = "tx_pmac_broadcast", .offset = 0xa6 },
119	{ .name = "tx_pmac_pause", .offset = 0xa7 },
120	{ .name = "tx_pmac_sz_64", .offset = 0xa8 },
121	{ .name = "tx_pmac_sz_65_127", .offset = 0xa9 },
122	{ .name = "tx_pmac_sz_128_255", .offset = 0xaa },
123	{ .name = "tx_pmac_sz_256_511", .offset = 0xab },
124	{ .name = "tx_pmac_sz_512_1023", .offset = 0xac },
125	{ .name = "tx_pmac_sz_1024_1526", .offset = 0xad },
126	{ .name = "tx_pmac_sz_jumbo", .offset = 0xae },
127
128	{ .name = "dr_local", .offset = 0x100 },
129	{ .name = "dr_tail", .offset = 0x101 },
130	{ .name = "dr_yellow_prio_0", .offset = 0x102 },
131	{ .name = "dr_yellow_prio_1", .offset = 0x103 },
132	{ .name = "dr_yellow_prio_2", .offset = 0x104 },
133	{ .name = "dr_yellow_prio_3", .offset = 0x105 },
134	{ .name = "dr_yellow_prio_4", .offset = 0x106 },
135	{ .name = "dr_yellow_prio_5", .offset = 0x107 },
136	{ .name = "dr_yellow_prio_6", .offset = 0x108 },
137	{ .name = "dr_yellow_prio_7", .offset = 0x109 },
138	{ .name = "dr_green_prio_0", .offset = 0x10a },
139	{ .name = "dr_green_prio_1", .offset = 0x10b },
140	{ .name = "dr_green_prio_2", .offset = 0x10c },
141	{ .name = "dr_green_prio_3", .offset = 0x10d },
142	{ .name = "dr_green_prio_4", .offset = 0x10e },
143	{ .name = "dr_green_prio_5", .offset = 0x10f },
144	{ .name = "dr_green_prio_6", .offset = 0x110 },
145	{ .name = "dr_green_prio_7", .offset = 0x111 },
146};
147
148/* The following numbers are indexes into lan966x_stats_layout[] */
149#define SYS_COUNT_RX_OCT		  0
150#define SYS_COUNT_RX_UC			  1
151#define SYS_COUNT_RX_MC			  2
152#define SYS_COUNT_RX_BC			  3
153#define SYS_COUNT_RX_SHORT		  4
154#define SYS_COUNT_RX_FRAG		  5
155#define SYS_COUNT_RX_JABBER		  6
156#define SYS_COUNT_RX_CRC		  7
157#define SYS_COUNT_RX_SYMBOL_ERR		  8
158#define SYS_COUNT_RX_SZ_64		  9
159#define SYS_COUNT_RX_SZ_65_127		 10
160#define SYS_COUNT_RX_SZ_128_255		 11
161#define SYS_COUNT_RX_SZ_256_511		 12
162#define SYS_COUNT_RX_SZ_512_1023	 13
163#define SYS_COUNT_RX_SZ_1024_1526	 14
164#define SYS_COUNT_RX_SZ_JUMBO		 15
165#define SYS_COUNT_RX_PAUSE		 16
166#define SYS_COUNT_RX_CONTROL		 17
167#define SYS_COUNT_RX_LONG		 18
168#define SYS_COUNT_RX_CAT_DROP		 19
169#define SYS_COUNT_RX_RED_PRIO_0		 20
170#define SYS_COUNT_RX_RED_PRIO_1		 21
171#define SYS_COUNT_RX_RED_PRIO_2		 22
172#define SYS_COUNT_RX_RED_PRIO_3		 23
173#define SYS_COUNT_RX_RED_PRIO_4		 24
174#define SYS_COUNT_RX_RED_PRIO_5		 25
175#define SYS_COUNT_RX_RED_PRIO_6		 26
176#define SYS_COUNT_RX_RED_PRIO_7		 27
177#define SYS_COUNT_RX_YELLOW_PRIO_0	 28
178#define SYS_COUNT_RX_YELLOW_PRIO_1	 29
179#define SYS_COUNT_RX_YELLOW_PRIO_2	 30
180#define SYS_COUNT_RX_YELLOW_PRIO_3	 31
181#define SYS_COUNT_RX_YELLOW_PRIO_4	 32
182#define SYS_COUNT_RX_YELLOW_PRIO_5	 33
183#define SYS_COUNT_RX_YELLOW_PRIO_6	 34
184#define SYS_COUNT_RX_YELLOW_PRIO_7	 35
185#define SYS_COUNT_RX_GREEN_PRIO_0	 36
186#define SYS_COUNT_RX_GREEN_PRIO_1	 37
187#define SYS_COUNT_RX_GREEN_PRIO_2	 38
188#define SYS_COUNT_RX_GREEN_PRIO_3	 39
189#define SYS_COUNT_RX_GREEN_PRIO_4	 40
190#define SYS_COUNT_RX_GREEN_PRIO_5	 41
191#define SYS_COUNT_RX_GREEN_PRIO_6	 42
192#define SYS_COUNT_RX_GREEN_PRIO_7	 43
193#define SYS_COUNT_RX_ASSEMBLY_ERR	 44
194#define SYS_COUNT_RX_SMD_ERR		 45
195#define SYS_COUNT_RX_ASSEMBLY_OK	 46
196#define SYS_COUNT_RX_MERGE_FRAG		 47
197#define SYS_COUNT_RX_PMAC_OCT		 48
198#define SYS_COUNT_RX_PMAC_UC		 49
199#define SYS_COUNT_RX_PMAC_MC		 50
200#define SYS_COUNT_RX_PMAC_BC		 51
201#define SYS_COUNT_RX_PMAC_SHORT		 52
202#define SYS_COUNT_RX_PMAC_FRAG		 53
203#define SYS_COUNT_RX_PMAC_JABBER	 54
204#define SYS_COUNT_RX_PMAC_CRC		 55
205#define SYS_COUNT_RX_PMAC_SYMBOL_ERR	 56
206#define SYS_COUNT_RX_PMAC_SZ_64		 57
207#define SYS_COUNT_RX_PMAC_SZ_65_127	 58
208#define SYS_COUNT_RX_PMAC_SZ_128_255	 59
209#define SYS_COUNT_RX_PMAC_SZ_256_511	 60
210#define SYS_COUNT_RX_PMAC_SZ_512_1023	 61
211#define SYS_COUNT_RX_PMAC_SZ_1024_1526	 62
212#define SYS_COUNT_RX_PMAC_SZ_JUMBO	 63
213#define SYS_COUNT_RX_PMAC_PAUSE		 64
214#define SYS_COUNT_RX_PMAC_CONTROL	 65
215#define SYS_COUNT_RX_PMAC_LONG		 66
216
217#define SYS_COUNT_TX_OCT		 67
218#define SYS_COUNT_TX_UC			 68
219#define SYS_COUNT_TX_MC			 69
220#define SYS_COUNT_TX_BC			 70
221#define SYS_COUNT_TX_COL		 71
222#define SYS_COUNT_TX_DROP		 72
223#define SYS_COUNT_TX_PAUSE		 73
224#define SYS_COUNT_TX_SZ_64		 74
225#define SYS_COUNT_TX_SZ_65_127		 75
226#define SYS_COUNT_TX_SZ_128_255		 76
227#define SYS_COUNT_TX_SZ_256_511		 77
228#define SYS_COUNT_TX_SZ_512_1023	 78
229#define SYS_COUNT_TX_SZ_1024_1526	 79
230#define SYS_COUNT_TX_SZ_JUMBO		 80
231#define SYS_COUNT_TX_YELLOW_PRIO_0	 81
232#define SYS_COUNT_TX_YELLOW_PRIO_1	 82
233#define SYS_COUNT_TX_YELLOW_PRIO_2	 83
234#define SYS_COUNT_TX_YELLOW_PRIO_3	 84
235#define SYS_COUNT_TX_YELLOW_PRIO_4	 85
236#define SYS_COUNT_TX_YELLOW_PRIO_5	 86
237#define SYS_COUNT_TX_YELLOW_PRIO_6	 87
238#define SYS_COUNT_TX_YELLOW_PRIO_7	 88
239#define SYS_COUNT_TX_GREEN_PRIO_0	 89
240#define SYS_COUNT_TX_GREEN_PRIO_1	 90
241#define SYS_COUNT_TX_GREEN_PRIO_2	 91
242#define SYS_COUNT_TX_GREEN_PRIO_3	 92
243#define SYS_COUNT_TX_GREEN_PRIO_4	 93
244#define SYS_COUNT_TX_GREEN_PRIO_5	 94
245#define SYS_COUNT_TX_GREEN_PRIO_6	 95
246#define SYS_COUNT_TX_GREEN_PRIO_7	 96
247#define SYS_COUNT_TX_AGED		 97
248#define SYS_COUNT_TX_LLCT		 98
249#define SYS_COUNT_TX_CT			 99
250#define SYS_COUNT_TX_MM_HOLD		100
251#define SYS_COUNT_TX_MERGE_FRAG		101
252#define SYS_COUNT_TX_PMAC_OCT		102
253#define SYS_COUNT_TX_PMAC_UC		103
254#define SYS_COUNT_TX_PMAC_MC		104
255#define SYS_COUNT_TX_PMAC_BC		105
256#define SYS_COUNT_TX_PMAC_PAUSE		106
257#define SYS_COUNT_TX_PMAC_SZ_64		107
258#define SYS_COUNT_TX_PMAC_SZ_65_127	108
259#define SYS_COUNT_TX_PMAC_SZ_128_255	109
260#define SYS_COUNT_TX_PMAC_SZ_256_511	110
261#define SYS_COUNT_TX_PMAC_SZ_512_1023	111
262#define SYS_COUNT_TX_PMAC_SZ_1024_1526	112
263#define SYS_COUNT_TX_PMAC_SZ_JUMBO	113
264
265#define SYS_COUNT_DR_LOCAL		114
266#define SYS_COUNT_DR_TAIL		115
267#define SYS_COUNT_DR_YELLOW_PRIO_0	116
268#define SYS_COUNT_DR_YELLOW_PRIO_1	117
269#define SYS_COUNT_DR_YELLOW_PRIO_2	118
270#define SYS_COUNT_DR_YELLOW_PRIO_3	119
271#define SYS_COUNT_DR_YELLOW_PRIO_4	120
272#define SYS_COUNT_DR_YELLOW_PRIO_5	121
273#define SYS_COUNT_DR_YELLOW_PRIO_6	122
274#define SYS_COUNT_DR_YELLOW_PRIO_7	123
275#define SYS_COUNT_DR_GREEN_PRIO_0	124
276#define SYS_COUNT_DR_GREEN_PRIO_1	125
277#define SYS_COUNT_DR_GREEN_PRIO_2	126
278#define SYS_COUNT_DR_GREEN_PRIO_3	127
279#define SYS_COUNT_DR_GREEN_PRIO_4	128
280#define SYS_COUNT_DR_GREEN_PRIO_5	129
281#define SYS_COUNT_DR_GREEN_PRIO_6	130
282#define SYS_COUNT_DR_GREEN_PRIO_7	131
283
284/* Add a possibly wrapping 32 bit value to a 64 bit counter */
285static void lan966x_add_cnt(u64 *cnt, u32 val)
286{
287	if (val < (*cnt & U32_MAX))
288		*cnt += (u64)1 << 32; /* value has wrapped */
289
290	*cnt = (*cnt & ~(u64)U32_MAX) + val;
291}
292
293static void lan966x_stats_update(struct lan966x *lan966x)
294{
295	int i, j;
296
297	mutex_lock(&lan966x->stats_lock);
298
299	for (i = 0; i < lan966x->num_phys_ports; i++) {
300		uint idx = i * lan966x->num_stats;
301
302		lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i),
303		       lan966x, SYS_STAT_CFG);
304
305		for (j = 0; j < lan966x->num_stats; j++) {
306			u32 offset = lan966x->stats_layout[j].offset;
307
308			lan966x_add_cnt(&lan966x->stats[idx++],
309					lan_rd(lan966x, SYS_CNT(offset)));
310		}
311	}
312
313	mutex_unlock(&lan966x->stats_lock);
314}
315
316static int lan966x_get_sset_count(struct net_device *dev, int sset)
317{
318	struct lan966x_port *port = netdev_priv(dev);
319	struct lan966x *lan966x = port->lan966x;
320
321	if (sset != ETH_SS_STATS)
322		return -EOPNOTSUPP;
323
324	return lan966x->num_stats;
325}
326
327static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data)
328{
329	struct lan966x_port *port = netdev_priv(netdev);
330	struct lan966x *lan966x = port->lan966x;
331	int i;
332
333	if (sset != ETH_SS_STATS)
334		return;
335
336	for (i = 0; i < lan966x->num_stats; i++)
337		memcpy(data + i * ETH_GSTRING_LEN,
338		       lan966x->stats_layout[i].name, ETH_GSTRING_LEN);
339}
340
341static void lan966x_get_ethtool_stats(struct net_device *dev,
342				      struct ethtool_stats *stats, u64 *data)
343{
344	struct lan966x_port *port = netdev_priv(dev);
345	struct lan966x *lan966x = port->lan966x;
346	int i;
347
348	/* check and update now */
349	lan966x_stats_update(lan966x);
350
351	/* Copy all counters */
352	for (i = 0; i < lan966x->num_stats; i++)
353		*data++ = lan966x->stats[port->chip_port *
354					 lan966x->num_stats + i];
355}
356
357static void lan966x_get_eth_mac_stats(struct net_device *dev,
358				      struct ethtool_eth_mac_stats *mac_stats)
359{
360	struct lan966x_port *port = netdev_priv(dev);
361	struct lan966x *lan966x = port->lan966x;
362	u32 idx;
363
364	lan966x_stats_update(lan966x);
365
366	idx = port->chip_port * lan966x->num_stats;
367
368	mutex_lock(&lan966x->stats_lock);
369
370	mac_stats->FramesTransmittedOK =
371		lan966x->stats[idx + SYS_COUNT_TX_UC] +
372		lan966x->stats[idx + SYS_COUNT_TX_MC] +
373		lan966x->stats[idx + SYS_COUNT_TX_BC] +
374		lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] +
375		lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] +
376		lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
377	mac_stats->SingleCollisionFrames =
378		lan966x->stats[idx + SYS_COUNT_TX_COL];
 
379	mac_stats->FramesReceivedOK =
380		lan966x->stats[idx + SYS_COUNT_RX_UC] +
381		lan966x->stats[idx + SYS_COUNT_RX_MC] +
382		lan966x->stats[idx + SYS_COUNT_RX_BC];
383	mac_stats->FrameCheckSequenceErrors =
384		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
385		lan966x->stats[idx + SYS_COUNT_RX_CRC];
 
386	mac_stats->OctetsTransmittedOK =
387		lan966x->stats[idx + SYS_COUNT_TX_OCT] +
388		lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
389	mac_stats->FramesWithDeferredXmissions =
390		lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];
 
 
 
 
391	mac_stats->OctetsReceivedOK =
392		lan966x->stats[idx + SYS_COUNT_RX_OCT];
 
393	mac_stats->MulticastFramesXmittedOK =
394		lan966x->stats[idx + SYS_COUNT_TX_MC] +
395		lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];
396	mac_stats->BroadcastFramesXmittedOK =
397		lan966x->stats[idx + SYS_COUNT_TX_BC] +
398		lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
 
399	mac_stats->MulticastFramesReceivedOK =
400		lan966x->stats[idx + SYS_COUNT_RX_MC];
401	mac_stats->BroadcastFramesReceivedOK =
402		lan966x->stats[idx + SYS_COUNT_RX_BC];
403	mac_stats->InRangeLengthErrors =
404		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
405		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
406		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
407		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
408		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
409		lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];
410	mac_stats->OutOfRangeLengthField =
411		lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
412		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
413		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
414		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
415	mac_stats->FrameTooLongErrors =
416		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
417		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
418
419	mutex_unlock(&lan966x->stats_lock);
420}
421
422static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {
423	{    0,    64 },
424	{   65,   127 },
425	{  128,   255 },
426	{  256,   511 },
427	{  512,  1023 },
428	{ 1024,  1518 },
429	{ 1519, 10239 },
430	{}
431};
432
433static void lan966x_get_eth_rmon_stats(struct net_device *dev,
434				       struct ethtool_rmon_stats *rmon_stats,
435				       const struct ethtool_rmon_hist_range **ranges)
436{
437	struct lan966x_port *port = netdev_priv(dev);
438	struct lan966x *lan966x = port->lan966x;
439	u32 idx;
440
441	lan966x_stats_update(lan966x);
442
443	idx = port->chip_port * lan966x->num_stats;
444
445	mutex_lock(&lan966x->stats_lock);
446
447	rmon_stats->undersize_pkts =
448		lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
449		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];
450	rmon_stats->oversize_pkts =
451		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
452		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
453	rmon_stats->fragments =
454		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
455		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];
456	rmon_stats->jabbers =
457		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
458		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];
459	rmon_stats->hist[0] =
460		lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
461		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];
462	rmon_stats->hist[1] =
463		lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
464		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];
465	rmon_stats->hist[2] =
466		lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
467		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];
468	rmon_stats->hist[3] =
469		lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
470		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];
471	rmon_stats->hist[4] =
472		lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
473		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];
474	rmon_stats->hist[5] =
475		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
476		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
477	rmon_stats->hist[6] =
478		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
479		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
480
481	rmon_stats->hist_tx[0] =
482		lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
483		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];
484	rmon_stats->hist_tx[1] =
485		lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
486		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];
487	rmon_stats->hist_tx[2] =
488		lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
489		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];
490	rmon_stats->hist_tx[3] =
491		lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
492		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];
493	rmon_stats->hist_tx[4] =
494		lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
495		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];
496	rmon_stats->hist_tx[5] =
497		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
498		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
499	rmon_stats->hist_tx[6] =
500		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
501		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
502
503	mutex_unlock(&lan966x->stats_lock);
504
505	*ranges = lan966x_rmon_ranges;
506}
507
508static int lan966x_get_link_ksettings(struct net_device *ndev,
509				      struct ethtool_link_ksettings *cmd)
510{
511	struct lan966x_port *port = netdev_priv(ndev);
512
513	return phylink_ethtool_ksettings_get(port->phylink, cmd);
514}
515
516static int lan966x_set_link_ksettings(struct net_device *ndev,
517				      const struct ethtool_link_ksettings *cmd)
518{
519	struct lan966x_port *port = netdev_priv(ndev);
520
521	return phylink_ethtool_ksettings_set(port->phylink, cmd);
522}
523
524static void lan966x_get_pauseparam(struct net_device *dev,
525				   struct ethtool_pauseparam *pause)
526{
527	struct lan966x_port *port = netdev_priv(dev);
528
529	phylink_ethtool_get_pauseparam(port->phylink, pause);
530}
531
532static int lan966x_set_pauseparam(struct net_device *dev,
533				  struct ethtool_pauseparam *pause)
534{
535	struct lan966x_port *port = netdev_priv(dev);
536
537	return phylink_ethtool_set_pauseparam(port->phylink, pause);
538}
539
540static int lan966x_get_ts_info(struct net_device *dev,
541			       struct kernel_ethtool_ts_info *info)
542{
543	struct lan966x_port *port = netdev_priv(dev);
544	struct lan966x *lan966x = port->lan966x;
545	struct lan966x_phc *phc;
546
547	if (!lan966x->ptp)
548		return ethtool_op_get_ts_info(dev, info);
549
550	phc = &lan966x->phc[LAN966X_PHC_PORT];
551
552	if (phc->clock) {
553		info->phc_index = ptp_clock_index(phc->clock);
554	} else {
555		info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE;
 
556		return 0;
557	}
558	info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
 
 
559				 SOF_TIMESTAMPING_TX_HARDWARE |
560				 SOF_TIMESTAMPING_RX_HARDWARE |
561				 SOF_TIMESTAMPING_RAW_HARDWARE;
562	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
563			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
564	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
565			   BIT(HWTSTAMP_FILTER_ALL);
566
567	return 0;
568}
569
570const struct ethtool_ops lan966x_ethtool_ops = {
571	.get_link_ksettings     = lan966x_get_link_ksettings,
572	.set_link_ksettings     = lan966x_set_link_ksettings,
573	.get_pauseparam		= lan966x_get_pauseparam,
574	.set_pauseparam		= lan966x_set_pauseparam,
575	.get_sset_count		= lan966x_get_sset_count,
576	.get_strings		= lan966x_get_strings,
577	.get_ethtool_stats	= lan966x_get_ethtool_stats,
578	.get_eth_mac_stats      = lan966x_get_eth_mac_stats,
579	.get_rmon_stats		= lan966x_get_eth_rmon_stats,
580	.get_link		= ethtool_op_get_link,
581	.get_ts_info		= lan966x_get_ts_info,
582};
583
584static void lan966x_check_stats_work(struct work_struct *work)
585{
586	struct delayed_work *del_work = to_delayed_work(work);
587	struct lan966x *lan966x = container_of(del_work, struct lan966x,
588					       stats_work);
589
590	lan966x_stats_update(lan966x);
591
592	queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
593			   LAN966X_STATS_CHECK_DELAY);
594}
595
596void lan966x_stats_get(struct net_device *dev,
597		       struct rtnl_link_stats64 *stats)
598{
599	struct lan966x_port *port = netdev_priv(dev);
600	struct lan966x *lan966x = port->lan966x;
601	u32 idx;
602	int i;
603
604	idx = port->chip_port * lan966x->num_stats;
605
606	mutex_lock(&lan966x->stats_lock);
607
608	stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +
609		lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];
610
611	stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
612		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
613		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
614		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
615		lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
616		lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
617		lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
618		lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
619		lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
620		lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
621		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
622		lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +
623		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
624		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
625		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
626		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
627		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +
628		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +
629		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +
630		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +
631		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +
632		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +
633		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];
634
635	stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +
636		lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];
637
638	stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
639		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
640		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
641		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
642		lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
643		lan966x->stats[idx + SYS_COUNT_RX_LONG];
644
645	stats->rx_dropped = dev->stats.rx_dropped +
646		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
647		lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +
648		lan966x->stats[idx + SYS_COUNT_DR_TAIL] +
649		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_0] +
650		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_1] +
651		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_2] +
652		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_3] +
653		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_4] +
654		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_5] +
655		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_6] +
656		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_7];
657
658	for (i = 0; i < LAN966X_NUM_TC; i++) {
659		stats->rx_dropped +=
660			(lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +
661			 lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);
662	}
663
664	/* Get Tx stats */
665	stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +
666		lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
667
668	stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
669		lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
670		lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
671		lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
672		lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
673		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
674		lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +
675		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +
676		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +
677		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +
678		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +
679		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +
680		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +
681		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];
682
683	stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +
684		lan966x->stats[idx + SYS_COUNT_TX_AGED];
685
686	stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];
687
688	mutex_unlock(&lan966x->stats_lock);
689}
690
691int lan966x_stats_init(struct lan966x *lan966x)
692{
693	char queue_name[32];
694
695	lan966x->stats_layout = lan966x_stats_layout;
696	lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);
697	lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *
698				      lan966x->num_stats,
699				      sizeof(u64), GFP_KERNEL);
700	if (!lan966x->stats)
701		return -ENOMEM;
702
703	/* Init stats worker */
704	mutex_init(&lan966x->stats_lock);
705	snprintf(queue_name, sizeof(queue_name), "%s-stats",
706		 dev_name(lan966x->dev));
707	lan966x->stats_queue = create_singlethread_workqueue(queue_name);
708	if (!lan966x->stats_queue)
709		return -ENOMEM;
710
711	INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work);
712	queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
713			   LAN966X_STATS_CHECK_DELAY);
714
715	return 0;
716}
v6.2
  1// SPDX-License-Identifier: GPL-2.0+
  2
  3#include <linux/netdevice.h>
  4
  5#include "lan966x_main.h"
  6
  7/* Number of traffic classes */
  8#define LAN966X_NUM_TC			8
  9#define LAN966X_STATS_CHECK_DELAY	(2 * HZ)
 10
 11static const struct lan966x_stat_layout lan966x_stats_layout[] = {
 12	{ .name = "rx_octets", .offset = 0x00, },
 13	{ .name = "rx_unicast", .offset = 0x01, },
 14	{ .name = "rx_multicast", .offset = 0x02 },
 15	{ .name = "rx_broadcast", .offset = 0x03 },
 16	{ .name = "rx_short", .offset = 0x04 },
 17	{ .name = "rx_frag", .offset = 0x05 },
 18	{ .name = "rx_jabber", .offset = 0x06 },
 19	{ .name = "rx_crc", .offset = 0x07 },
 20	{ .name = "rx_symbol_err", .offset = 0x08 },
 21	{ .name = "rx_sz_64", .offset = 0x09 },
 22	{ .name = "rx_sz_65_127", .offset = 0x0a},
 23	{ .name = "rx_sz_128_255", .offset = 0x0b},
 24	{ .name = "rx_sz_256_511", .offset = 0x0c },
 25	{ .name = "rx_sz_512_1023", .offset = 0x0d },
 26	{ .name = "rx_sz_1024_1526", .offset = 0x0e },
 27	{ .name = "rx_sz_jumbo", .offset = 0x0f },
 28	{ .name = "rx_pause", .offset = 0x10 },
 29	{ .name = "rx_control", .offset = 0x11 },
 30	{ .name = "rx_long", .offset = 0x12 },
 31	{ .name = "rx_cat_drop", .offset = 0x13 },
 32	{ .name = "rx_red_prio_0", .offset = 0x14 },
 33	{ .name = "rx_red_prio_1", .offset = 0x15 },
 34	{ .name = "rx_red_prio_2", .offset = 0x16 },
 35	{ .name = "rx_red_prio_3", .offset = 0x17 },
 36	{ .name = "rx_red_prio_4", .offset = 0x18 },
 37	{ .name = "rx_red_prio_5", .offset = 0x19 },
 38	{ .name = "rx_red_prio_6", .offset = 0x1a },
 39	{ .name = "rx_red_prio_7", .offset = 0x1b },
 40	{ .name = "rx_yellow_prio_0", .offset = 0x1c },
 41	{ .name = "rx_yellow_prio_1", .offset = 0x1d },
 42	{ .name = "rx_yellow_prio_2", .offset = 0x1e },
 43	{ .name = "rx_yellow_prio_3", .offset = 0x1f },
 44	{ .name = "rx_yellow_prio_4", .offset = 0x20 },
 45	{ .name = "rx_yellow_prio_5", .offset = 0x21 },
 46	{ .name = "rx_yellow_prio_6", .offset = 0x22 },
 47	{ .name = "rx_yellow_prio_7", .offset = 0x23 },
 48	{ .name = "rx_green_prio_0", .offset = 0x24 },
 49	{ .name = "rx_green_prio_1", .offset = 0x25 },
 50	{ .name = "rx_green_prio_2", .offset = 0x26 },
 51	{ .name = "rx_green_prio_3", .offset = 0x27 },
 52	{ .name = "rx_green_prio_4", .offset = 0x28 },
 53	{ .name = "rx_green_prio_5", .offset = 0x29 },
 54	{ .name = "rx_green_prio_6", .offset = 0x2a },
 55	{ .name = "rx_green_prio_7", .offset = 0x2b },
 56	{ .name = "rx_assembly_err", .offset = 0x2c },
 57	{ .name = "rx_smd_err", .offset = 0x2d },
 58	{ .name = "rx_assembly_ok", .offset = 0x2e },
 59	{ .name = "rx_merge_frag", .offset = 0x2f },
 60	{ .name = "rx_pmac_octets", .offset = 0x30, },
 61	{ .name = "rx_pmac_unicast", .offset = 0x31, },
 62	{ .name = "rx_pmac_multicast", .offset = 0x32 },
 63	{ .name = "rx_pmac_broadcast", .offset = 0x33 },
 64	{ .name = "rx_pmac_short", .offset = 0x34 },
 65	{ .name = "rx_pmac_frag", .offset = 0x35 },
 66	{ .name = "rx_pmac_jabber", .offset = 0x36 },
 67	{ .name = "rx_pmac_crc", .offset = 0x37 },
 68	{ .name = "rx_pmac_symbol_err", .offset = 0x38 },
 69	{ .name = "rx_pmac_sz_64", .offset = 0x39 },
 70	{ .name = "rx_pmac_sz_65_127", .offset = 0x3a },
 71	{ .name = "rx_pmac_sz_128_255", .offset = 0x3b },
 72	{ .name = "rx_pmac_sz_256_511", .offset = 0x3c },
 73	{ .name = "rx_pmac_sz_512_1023", .offset = 0x3d },
 74	{ .name = "rx_pmac_sz_1024_1526", .offset = 0x3e },
 75	{ .name = "rx_pmac_sz_jumbo", .offset = 0x3f },
 76	{ .name = "rx_pmac_pause", .offset = 0x40 },
 77	{ .name = "rx_pmac_control", .offset = 0x41 },
 78	{ .name = "rx_pmac_long", .offset = 0x42 },
 79
 80	{ .name = "tx_octets", .offset = 0x80, },
 81	{ .name = "tx_unicast", .offset = 0x81, },
 82	{ .name = "tx_multicast", .offset = 0x82 },
 83	{ .name = "tx_broadcast", .offset = 0x83 },
 84	{ .name = "tx_col", .offset = 0x84 },
 85	{ .name = "tx_drop", .offset = 0x85 },
 86	{ .name = "tx_pause", .offset = 0x86 },
 87	{ .name = "tx_sz_64", .offset = 0x87 },
 88	{ .name = "tx_sz_65_127", .offset = 0x88 },
 89	{ .name = "tx_sz_128_255", .offset = 0x89 },
 90	{ .name = "tx_sz_256_511", .offset = 0x8a },
 91	{ .name = "tx_sz_512_1023", .offset = 0x8b },
 92	{ .name = "tx_sz_1024_1526", .offset = 0x8c },
 93	{ .name = "tx_sz_jumbo", .offset = 0x8d },
 94	{ .name = "tx_yellow_prio_0", .offset = 0x8e },
 95	{ .name = "tx_yellow_prio_1", .offset = 0x8f },
 96	{ .name = "tx_yellow_prio_2", .offset = 0x90 },
 97	{ .name = "tx_yellow_prio_3", .offset = 0x91 },
 98	{ .name = "tx_yellow_prio_4", .offset = 0x92 },
 99	{ .name = "tx_yellow_prio_5", .offset = 0x93 },
100	{ .name = "tx_yellow_prio_6", .offset = 0x94 },
101	{ .name = "tx_yellow_prio_7", .offset = 0x95 },
102	{ .name = "tx_green_prio_0", .offset = 0x96 },
103	{ .name = "tx_green_prio_1", .offset = 0x97 },
104	{ .name = "tx_green_prio_2", .offset = 0x98 },
105	{ .name = "tx_green_prio_3", .offset = 0x99 },
106	{ .name = "tx_green_prio_4", .offset = 0x9a },
107	{ .name = "tx_green_prio_5", .offset = 0x9b },
108	{ .name = "tx_green_prio_6", .offset = 0x9c },
109	{ .name = "tx_green_prio_7", .offset = 0x9d },
110	{ .name = "tx_aged", .offset = 0x9e },
111	{ .name = "tx_llct", .offset = 0x9f },
112	{ .name = "tx_ct", .offset = 0xa0 },
113	{ .name = "tx_mm_hold", .offset = 0xa1 },
114	{ .name = "tx_merge_frag", .offset = 0xa2 },
115	{ .name = "tx_pmac_octets", .offset = 0xa3, },
116	{ .name = "tx_pmac_unicast", .offset = 0xa4, },
117	{ .name = "tx_pmac_multicast", .offset = 0xa5 },
118	{ .name = "tx_pmac_broadcast", .offset = 0xa6 },
119	{ .name = "tx_pmac_pause", .offset = 0xa7 },
120	{ .name = "tx_pmac_sz_64", .offset = 0xa8 },
121	{ .name = "tx_pmac_sz_65_127", .offset = 0xa9 },
122	{ .name = "tx_pmac_sz_128_255", .offset = 0xaa },
123	{ .name = "tx_pmac_sz_256_511", .offset = 0xab },
124	{ .name = "tx_pmac_sz_512_1023", .offset = 0xac },
125	{ .name = "tx_pmac_sz_1024_1526", .offset = 0xad },
126	{ .name = "tx_pmac_sz_jumbo", .offset = 0xae },
127
128	{ .name = "dr_local", .offset = 0x100 },
129	{ .name = "dr_tail", .offset = 0x101 },
130	{ .name = "dr_yellow_prio_0", .offset = 0x102 },
131	{ .name = "dr_yellow_prio_1", .offset = 0x103 },
132	{ .name = "dr_yellow_prio_2", .offset = 0x104 },
133	{ .name = "dr_yellow_prio_3", .offset = 0x105 },
134	{ .name = "dr_yellow_prio_4", .offset = 0x106 },
135	{ .name = "dr_yellow_prio_5", .offset = 0x107 },
136	{ .name = "dr_yellow_prio_6", .offset = 0x108 },
137	{ .name = "dr_yellow_prio_7", .offset = 0x109 },
138	{ .name = "dr_green_prio_0", .offset = 0x10a },
139	{ .name = "dr_green_prio_1", .offset = 0x10b },
140	{ .name = "dr_green_prio_2", .offset = 0x10c },
141	{ .name = "dr_green_prio_3", .offset = 0x10d },
142	{ .name = "dr_green_prio_4", .offset = 0x10e },
143	{ .name = "dr_green_prio_5", .offset = 0x10f },
144	{ .name = "dr_green_prio_6", .offset = 0x110 },
145	{ .name = "dr_green_prio_7", .offset = 0x111 },
146};
147
148/* The following numbers are indexes into lan966x_stats_layout[] */
149#define SYS_COUNT_RX_OCT		  0
150#define SYS_COUNT_RX_UC			  1
151#define SYS_COUNT_RX_MC			  2
152#define SYS_COUNT_RX_BC			  3
153#define SYS_COUNT_RX_SHORT		  4
154#define SYS_COUNT_RX_FRAG		  5
155#define SYS_COUNT_RX_JABBER		  6
156#define SYS_COUNT_RX_CRC		  7
157#define SYS_COUNT_RX_SYMBOL_ERR		  8
158#define SYS_COUNT_RX_SZ_64		  9
159#define SYS_COUNT_RX_SZ_65_127		 10
160#define SYS_COUNT_RX_SZ_128_255		 11
161#define SYS_COUNT_RX_SZ_256_511		 12
162#define SYS_COUNT_RX_SZ_512_1023	 13
163#define SYS_COUNT_RX_SZ_1024_1526	 14
164#define SYS_COUNT_RX_SZ_JUMBO		 15
165#define SYS_COUNT_RX_PAUSE		 16
166#define SYS_COUNT_RX_CONTROL		 17
167#define SYS_COUNT_RX_LONG		 18
168#define SYS_COUNT_RX_CAT_DROP		 19
169#define SYS_COUNT_RX_RED_PRIO_0		 20
170#define SYS_COUNT_RX_RED_PRIO_1		 21
171#define SYS_COUNT_RX_RED_PRIO_2		 22
172#define SYS_COUNT_RX_RED_PRIO_3		 23
173#define SYS_COUNT_RX_RED_PRIO_4		 24
174#define SYS_COUNT_RX_RED_PRIO_5		 25
175#define SYS_COUNT_RX_RED_PRIO_6		 26
176#define SYS_COUNT_RX_RED_PRIO_7		 27
177#define SYS_COUNT_RX_YELLOW_PRIO_0	 28
178#define SYS_COUNT_RX_YELLOW_PRIO_1	 29
179#define SYS_COUNT_RX_YELLOW_PRIO_2	 30
180#define SYS_COUNT_RX_YELLOW_PRIO_3	 31
181#define SYS_COUNT_RX_YELLOW_PRIO_4	 32
182#define SYS_COUNT_RX_YELLOW_PRIO_5	 33
183#define SYS_COUNT_RX_YELLOW_PRIO_6	 34
184#define SYS_COUNT_RX_YELLOW_PRIO_7	 35
185#define SYS_COUNT_RX_GREEN_PRIO_0	 36
186#define SYS_COUNT_RX_GREEN_PRIO_1	 37
187#define SYS_COUNT_RX_GREEN_PRIO_2	 38
188#define SYS_COUNT_RX_GREEN_PRIO_3	 39
189#define SYS_COUNT_RX_GREEN_PRIO_4	 40
190#define SYS_COUNT_RX_GREEN_PRIO_5	 41
191#define SYS_COUNT_RX_GREEN_PRIO_6	 42
192#define SYS_COUNT_RX_GREEN_PRIO_7	 43
193#define SYS_COUNT_RX_ASSEMBLY_ERR	 44
194#define SYS_COUNT_RX_SMD_ERR		 45
195#define SYS_COUNT_RX_ASSEMBLY_OK	 46
196#define SYS_COUNT_RX_MERGE_FRAG		 47
197#define SYS_COUNT_RX_PMAC_OCT		 48
198#define SYS_COUNT_RX_PMAC_UC		 49
199#define SYS_COUNT_RX_PMAC_MC		 50
200#define SYS_COUNT_RX_PMAC_BC		 51
201#define SYS_COUNT_RX_PMAC_SHORT		 52
202#define SYS_COUNT_RX_PMAC_FRAG		 53
203#define SYS_COUNT_RX_PMAC_JABBER	 54
204#define SYS_COUNT_RX_PMAC_CRC		 55
205#define SYS_COUNT_RX_PMAC_SYMBOL_ERR	 56
206#define SYS_COUNT_RX_PMAC_SZ_64		 57
207#define SYS_COUNT_RX_PMAC_SZ_65_127	 58
208#define SYS_COUNT_RX_PMAC_SZ_128_255	 59
209#define SYS_COUNT_RX_PMAC_SZ_256_511	 60
210#define SYS_COUNT_RX_PMAC_SZ_512_1023	 61
211#define SYS_COUNT_RX_PMAC_SZ_1024_1526	 62
212#define SYS_COUNT_RX_PMAC_SZ_JUMBO	 63
213#define SYS_COUNT_RX_PMAC_PAUSE		 64
214#define SYS_COUNT_RX_PMAC_CONTROL	 65
215#define SYS_COUNT_RX_PMAC_LONG		 66
216
217#define SYS_COUNT_TX_OCT		 67
218#define SYS_COUNT_TX_UC			 68
219#define SYS_COUNT_TX_MC			 69
220#define SYS_COUNT_TX_BC			 70
221#define SYS_COUNT_TX_COL		 71
222#define SYS_COUNT_TX_DROP		 72
223#define SYS_COUNT_TX_PAUSE		 73
224#define SYS_COUNT_TX_SZ_64		 74
225#define SYS_COUNT_TX_SZ_65_127		 75
226#define SYS_COUNT_TX_SZ_128_255		 76
227#define SYS_COUNT_TX_SZ_256_511		 77
228#define SYS_COUNT_TX_SZ_512_1023	 78
229#define SYS_COUNT_TX_SZ_1024_1526	 79
230#define SYS_COUNT_TX_SZ_JUMBO		 80
231#define SYS_COUNT_TX_YELLOW_PRIO_0	 81
232#define SYS_COUNT_TX_YELLOW_PRIO_1	 82
233#define SYS_COUNT_TX_YELLOW_PRIO_2	 83
234#define SYS_COUNT_TX_YELLOW_PRIO_3	 84
235#define SYS_COUNT_TX_YELLOW_PRIO_4	 85
236#define SYS_COUNT_TX_YELLOW_PRIO_5	 86
237#define SYS_COUNT_TX_YELLOW_PRIO_6	 87
238#define SYS_COUNT_TX_YELLOW_PRIO_7	 88
239#define SYS_COUNT_TX_GREEN_PRIO_0	 89
240#define SYS_COUNT_TX_GREEN_PRIO_1	 90
241#define SYS_COUNT_TX_GREEN_PRIO_2	 91
242#define SYS_COUNT_TX_GREEN_PRIO_3	 92
243#define SYS_COUNT_TX_GREEN_PRIO_4	 93
244#define SYS_COUNT_TX_GREEN_PRIO_5	 94
245#define SYS_COUNT_TX_GREEN_PRIO_6	 95
246#define SYS_COUNT_TX_GREEN_PRIO_7	 96
247#define SYS_COUNT_TX_AGED		 97
248#define SYS_COUNT_TX_LLCT		 98
249#define SYS_COUNT_TX_CT			 99
250#define SYS_COUNT_TX_MM_HOLD		100
251#define SYS_COUNT_TX_MERGE_FRAG		101
252#define SYS_COUNT_TX_PMAC_OCT		102
253#define SYS_COUNT_TX_PMAC_UC		103
254#define SYS_COUNT_TX_PMAC_MC		104
255#define SYS_COUNT_TX_PMAC_BC		105
256#define SYS_COUNT_TX_PMAC_PAUSE		106
257#define SYS_COUNT_TX_PMAC_SZ_64		107
258#define SYS_COUNT_TX_PMAC_SZ_65_127	108
259#define SYS_COUNT_TX_PMAC_SZ_128_255	109
260#define SYS_COUNT_TX_PMAC_SZ_256_511	110
261#define SYS_COUNT_TX_PMAC_SZ_512_1023	111
262#define SYS_COUNT_TX_PMAC_SZ_1024_1526	112
263#define SYS_COUNT_TX_PMAC_SZ_JUMBO	113
264
265#define SYS_COUNT_DR_LOCAL		114
266#define SYS_COUNT_DR_TAIL		115
267#define SYS_COUNT_DR_YELLOW_PRIO_0	116
268#define SYS_COUNT_DR_YELLOW_PRIO_1	117
269#define SYS_COUNT_DR_YELLOW_PRIO_2	118
270#define SYS_COUNT_DR_YELLOW_PRIO_3	119
271#define SYS_COUNT_DR_YELLOW_PRIO_4	120
272#define SYS_COUNT_DR_YELLOW_PRIO_5	121
273#define SYS_COUNT_DR_YELLOW_PRIO_6	122
274#define SYS_COUNT_DR_YELLOW_PRIO_7	123
275#define SYS_COUNT_DR_GREEN_PRIO_0	124
276#define SYS_COUNT_DR_GREEN_PRIO_1	125
277#define SYS_COUNT_DR_GREEN_PRIO_2	126
278#define SYS_COUNT_DR_GREEN_PRIO_3	127
279#define SYS_COUNT_DR_GREEN_PRIO_4	128
280#define SYS_COUNT_DR_GREEN_PRIO_5	129
281#define SYS_COUNT_DR_GREEN_PRIO_6	130
282#define SYS_COUNT_DR_GREEN_PRIO_7	131
283
284/* Add a possibly wrapping 32 bit value to a 64 bit counter */
285static void lan966x_add_cnt(u64 *cnt, u32 val)
286{
287	if (val < (*cnt & U32_MAX))
288		*cnt += (u64)1 << 32; /* value has wrapped */
289
290	*cnt = (*cnt & ~(u64)U32_MAX) + val;
291}
292
293static void lan966x_stats_update(struct lan966x *lan966x)
294{
295	int i, j;
296
297	mutex_lock(&lan966x->stats_lock);
298
299	for (i = 0; i < lan966x->num_phys_ports; i++) {
300		uint idx = i * lan966x->num_stats;
301
302		lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i),
303		       lan966x, SYS_STAT_CFG);
304
305		for (j = 0; j < lan966x->num_stats; j++) {
306			u32 offset = lan966x->stats_layout[j].offset;
307
308			lan966x_add_cnt(&lan966x->stats[idx++],
309					lan_rd(lan966x, SYS_CNT(offset)));
310		}
311	}
312
313	mutex_unlock(&lan966x->stats_lock);
314}
315
316static int lan966x_get_sset_count(struct net_device *dev, int sset)
317{
318	struct lan966x_port *port = netdev_priv(dev);
319	struct lan966x *lan966x = port->lan966x;
320
321	if (sset != ETH_SS_STATS)
322		return -EOPNOTSUPP;
323
324	return lan966x->num_stats;
325}
326
327static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data)
328{
329	struct lan966x_port *port = netdev_priv(netdev);
330	struct lan966x *lan966x = port->lan966x;
331	int i;
332
333	if (sset != ETH_SS_STATS)
334		return;
335
336	for (i = 0; i < lan966x->num_stats; i++)
337		memcpy(data + i * ETH_GSTRING_LEN,
338		       lan966x->stats_layout[i].name, ETH_GSTRING_LEN);
339}
340
341static void lan966x_get_ethtool_stats(struct net_device *dev,
342				      struct ethtool_stats *stats, u64 *data)
343{
344	struct lan966x_port *port = netdev_priv(dev);
345	struct lan966x *lan966x = port->lan966x;
346	int i;
347
348	/* check and update now */
349	lan966x_stats_update(lan966x);
350
351	/* Copy all counters */
352	for (i = 0; i < lan966x->num_stats; i++)
353		*data++ = lan966x->stats[port->chip_port *
354					 lan966x->num_stats + i];
355}
356
357static void lan966x_get_eth_mac_stats(struct net_device *dev,
358				      struct ethtool_eth_mac_stats *mac_stats)
359{
360	struct lan966x_port *port = netdev_priv(dev);
361	struct lan966x *lan966x = port->lan966x;
362	u32 idx;
363
364	lan966x_stats_update(lan966x);
365
366	idx = port->chip_port * lan966x->num_stats;
367
368	mutex_lock(&lan966x->stats_lock);
369
370	mac_stats->FramesTransmittedOK =
371		lan966x->stats[idx + SYS_COUNT_TX_UC] +
372		lan966x->stats[idx + SYS_COUNT_TX_MC] +
373		lan966x->stats[idx + SYS_COUNT_TX_BC] +
374		lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] +
375		lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] +
376		lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
377	mac_stats->SingleCollisionFrames =
378		lan966x->stats[idx + SYS_COUNT_TX_COL];
379	mac_stats->MultipleCollisionFrames = 0;
380	mac_stats->FramesReceivedOK =
381		lan966x->stats[idx + SYS_COUNT_RX_UC] +
382		lan966x->stats[idx + SYS_COUNT_RX_MC] +
383		lan966x->stats[idx + SYS_COUNT_RX_BC];
384	mac_stats->FrameCheckSequenceErrors =
385		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
386		lan966x->stats[idx + SYS_COUNT_RX_CRC];
387	mac_stats->AlignmentErrors = 0;
388	mac_stats->OctetsTransmittedOK =
389		lan966x->stats[idx + SYS_COUNT_TX_OCT] +
390		lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
391	mac_stats->FramesWithDeferredXmissions =
392		lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];
393	mac_stats->LateCollisions = 0;
394	mac_stats->FramesAbortedDueToXSColls = 0;
395	mac_stats->FramesLostDueToIntMACXmitError = 0;
396	mac_stats->CarrierSenseErrors = 0;
397	mac_stats->OctetsReceivedOK =
398		lan966x->stats[idx + SYS_COUNT_RX_OCT];
399	mac_stats->FramesLostDueToIntMACRcvError = 0;
400	mac_stats->MulticastFramesXmittedOK =
401		lan966x->stats[idx + SYS_COUNT_TX_MC] +
402		lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];
403	mac_stats->BroadcastFramesXmittedOK =
404		lan966x->stats[idx + SYS_COUNT_TX_BC] +
405		lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
406	mac_stats->FramesWithExcessiveDeferral = 0;
407	mac_stats->MulticastFramesReceivedOK =
408		lan966x->stats[idx + SYS_COUNT_RX_MC];
409	mac_stats->BroadcastFramesReceivedOK =
410		lan966x->stats[idx + SYS_COUNT_RX_BC];
411	mac_stats->InRangeLengthErrors =
412		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
413		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
414		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
415		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
416		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
417		lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];
418	mac_stats->OutOfRangeLengthField =
419		lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
420		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
421		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
422		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
423	mac_stats->FrameTooLongErrors =
424		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
425		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
426
427	mutex_unlock(&lan966x->stats_lock);
428}
429
430static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {
431	{    0,    64 },
432	{   65,   127 },
433	{  128,   255 },
434	{  256,   511 },
435	{  512,  1023 },
436	{ 1024,  1518 },
437	{ 1519, 10239 },
438	{}
439};
440
441static void lan966x_get_eth_rmon_stats(struct net_device *dev,
442				       struct ethtool_rmon_stats *rmon_stats,
443				       const struct ethtool_rmon_hist_range **ranges)
444{
445	struct lan966x_port *port = netdev_priv(dev);
446	struct lan966x *lan966x = port->lan966x;
447	u32 idx;
448
449	lan966x_stats_update(lan966x);
450
451	idx = port->chip_port * lan966x->num_stats;
452
453	mutex_lock(&lan966x->stats_lock);
454
455	rmon_stats->undersize_pkts =
456		lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
457		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];
458	rmon_stats->oversize_pkts =
459		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
460		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
461	rmon_stats->fragments =
462		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
463		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];
464	rmon_stats->jabbers =
465		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
466		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];
467	rmon_stats->hist[0] =
468		lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
469		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];
470	rmon_stats->hist[1] =
471		lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
472		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];
473	rmon_stats->hist[2] =
474		lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
475		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];
476	rmon_stats->hist[3] =
477		lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
478		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];
479	rmon_stats->hist[4] =
480		lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
481		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];
482	rmon_stats->hist[5] =
483		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
484		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
485	rmon_stats->hist[6] =
486		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
487		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
488
489	rmon_stats->hist_tx[0] =
490		lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
491		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];
492	rmon_stats->hist_tx[1] =
493		lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
494		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];
495	rmon_stats->hist_tx[2] =
496		lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
497		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];
498	rmon_stats->hist_tx[3] =
499		lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
500		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];
501	rmon_stats->hist_tx[4] =
502		lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
503		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];
504	rmon_stats->hist_tx[5] =
505		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
506		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
507	rmon_stats->hist_tx[6] =
508		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
509		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
510
511	mutex_unlock(&lan966x->stats_lock);
512
513	*ranges = lan966x_rmon_ranges;
514}
515
516static int lan966x_get_link_ksettings(struct net_device *ndev,
517				      struct ethtool_link_ksettings *cmd)
518{
519	struct lan966x_port *port = netdev_priv(ndev);
520
521	return phylink_ethtool_ksettings_get(port->phylink, cmd);
522}
523
524static int lan966x_set_link_ksettings(struct net_device *ndev,
525				      const struct ethtool_link_ksettings *cmd)
526{
527	struct lan966x_port *port = netdev_priv(ndev);
528
529	return phylink_ethtool_ksettings_set(port->phylink, cmd);
530}
531
532static void lan966x_get_pauseparam(struct net_device *dev,
533				   struct ethtool_pauseparam *pause)
534{
535	struct lan966x_port *port = netdev_priv(dev);
536
537	phylink_ethtool_get_pauseparam(port->phylink, pause);
538}
539
540static int lan966x_set_pauseparam(struct net_device *dev,
541				  struct ethtool_pauseparam *pause)
542{
543	struct lan966x_port *port = netdev_priv(dev);
544
545	return phylink_ethtool_set_pauseparam(port->phylink, pause);
546}
547
548static int lan966x_get_ts_info(struct net_device *dev,
549			       struct ethtool_ts_info *info)
550{
551	struct lan966x_port *port = netdev_priv(dev);
552	struct lan966x *lan966x = port->lan966x;
553	struct lan966x_phc *phc;
554
555	if (!lan966x->ptp)
556		return ethtool_op_get_ts_info(dev, info);
557
558	phc = &lan966x->phc[LAN966X_PHC_PORT];
559
560	info->phc_index = phc->clock ? ptp_clock_index(phc->clock) : -1;
561	if (info->phc_index == -1) {
562		info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
563					 SOF_TIMESTAMPING_RX_SOFTWARE |
564					 SOF_TIMESTAMPING_SOFTWARE;
565		return 0;
566	}
567	info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
568				 SOF_TIMESTAMPING_RX_SOFTWARE |
569				 SOF_TIMESTAMPING_SOFTWARE |
570				 SOF_TIMESTAMPING_TX_HARDWARE |
571				 SOF_TIMESTAMPING_RX_HARDWARE |
572				 SOF_TIMESTAMPING_RAW_HARDWARE;
573	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
574			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
575	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
576			   BIT(HWTSTAMP_FILTER_ALL);
577
578	return 0;
579}
580
581const struct ethtool_ops lan966x_ethtool_ops = {
582	.get_link_ksettings     = lan966x_get_link_ksettings,
583	.set_link_ksettings     = lan966x_set_link_ksettings,
584	.get_pauseparam		= lan966x_get_pauseparam,
585	.set_pauseparam		= lan966x_set_pauseparam,
586	.get_sset_count		= lan966x_get_sset_count,
587	.get_strings		= lan966x_get_strings,
588	.get_ethtool_stats	= lan966x_get_ethtool_stats,
589	.get_eth_mac_stats      = lan966x_get_eth_mac_stats,
590	.get_rmon_stats		= lan966x_get_eth_rmon_stats,
591	.get_link		= ethtool_op_get_link,
592	.get_ts_info		= lan966x_get_ts_info,
593};
594
595static void lan966x_check_stats_work(struct work_struct *work)
596{
597	struct delayed_work *del_work = to_delayed_work(work);
598	struct lan966x *lan966x = container_of(del_work, struct lan966x,
599					       stats_work);
600
601	lan966x_stats_update(lan966x);
602
603	queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
604			   LAN966X_STATS_CHECK_DELAY);
605}
606
607void lan966x_stats_get(struct net_device *dev,
608		       struct rtnl_link_stats64 *stats)
609{
610	struct lan966x_port *port = netdev_priv(dev);
611	struct lan966x *lan966x = port->lan966x;
612	u32 idx;
613	int i;
614
615	idx = port->chip_port * lan966x->num_stats;
616
617	mutex_lock(&lan966x->stats_lock);
618
619	stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +
620		lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];
621
622	stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
623		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
624		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
625		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
626		lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
627		lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
628		lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
629		lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
630		lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
631		lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
632		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
633		lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +
634		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
635		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
636		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
637		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
638		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +
639		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +
640		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +
641		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +
642		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +
643		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +
644		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];
645
646	stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +
647		lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];
648
649	stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
650		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
651		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
652		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
653		lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
654		lan966x->stats[idx + SYS_COUNT_RX_LONG];
655
656	stats->rx_dropped = dev->stats.rx_dropped +
657		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
658		lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +
659		lan966x->stats[idx + SYS_COUNT_DR_TAIL] +
660		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_0] +
661		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_1] +
662		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_2] +
663		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_3] +
664		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_4] +
665		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_5] +
666		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_6] +
667		lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_7];
668
669	for (i = 0; i < LAN966X_NUM_TC; i++) {
670		stats->rx_dropped +=
671			(lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +
672			 lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);
673	}
674
675	/* Get Tx stats */
676	stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +
677		lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
678
679	stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
680		lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
681		lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
682		lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
683		lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
684		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
685		lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +
686		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +
687		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +
688		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +
689		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +
690		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +
691		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +
692		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];
693
694	stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +
695		lan966x->stats[idx + SYS_COUNT_TX_AGED];
696
697	stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];
698
699	mutex_unlock(&lan966x->stats_lock);
700}
701
702int lan966x_stats_init(struct lan966x *lan966x)
703{
704	char queue_name[32];
705
706	lan966x->stats_layout = lan966x_stats_layout;
707	lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);
708	lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *
709				      lan966x->num_stats,
710				      sizeof(u64), GFP_KERNEL);
711	if (!lan966x->stats)
712		return -ENOMEM;
713
714	/* Init stats worker */
715	mutex_init(&lan966x->stats_lock);
716	snprintf(queue_name, sizeof(queue_name), "%s-stats",
717		 dev_name(lan966x->dev));
718	lan966x->stats_queue = create_singlethread_workqueue(queue_name);
719	if (!lan966x->stats_queue)
720		return -ENOMEM;
721
722	INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work);
723	queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
724			   LAN966X_STATS_CHECK_DELAY);
725
726	return 0;
727}