xref: /linux/drivers/net/dsa/motorcomm/mib.c (revision ed4453587dc0082a6b6b5a52c89d6b84d713e8ac)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2026 David Yang
4  */
5 
6 #include "chip.h"
7 #include "mib.h"
8 #include "smi.h"
9 
10 struct yt921x_mib_desc {
11 	unsigned int size;
12 	unsigned int offset;
13 	const char *name;
14 };
15 
16 #define MIB_DESC(_size, _offset, _name) \
17 	{_size, _offset, _name}
18 
19 /* Must agree with yt921x_mib_stats
20  *
21  * Unstructured fields (name != NULL) will appear in get_ethtool_stats(),
22  * structured go to their *_stats() methods, but we need their sizes and offsets
23  * to perform 32bit MIB overflow wraparound.
24  */
25 static const struct yt921x_mib_desc yt921x_mib_descs[] = {
26 	MIB_DESC(1, YT921X_MIB_DATA_RX_BROADCAST, NULL),
27 	MIB_DESC(1, YT921X_MIB_DATA_RX_PAUSE, NULL),
28 	MIB_DESC(1, YT921X_MIB_DATA_RX_MULTICAST, NULL),
29 	MIB_DESC(1, YT921X_MIB_DATA_RX_CRC_ERR, NULL),
30 
31 	MIB_DESC(1, YT921X_MIB_DATA_RX_ALIGN_ERR, NULL),
32 	MIB_DESC(1, YT921X_MIB_DATA_RX_UNDERSIZE_ERR, NULL),
33 	MIB_DESC(1, YT921X_MIB_DATA_RX_FRAG_ERR, NULL),
34 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_64, NULL),
35 
36 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_65_TO_127, NULL),
37 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_128_TO_255, NULL),
38 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_256_TO_511, NULL),
39 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_512_TO_1023, NULL),
40 
41 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1024_TO_1518, NULL),
42 	MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1519_TO_MAX, NULL),
43 	MIB_DESC(2, YT921X_MIB_DATA_RX_GOOD_BYTES, NULL),
44 
45 	MIB_DESC(2, YT921X_MIB_DATA_RX_BAD_BYTES, "RxBadBytes"),
46 	MIB_DESC(1, YT921X_MIB_DATA_RX_OVERSIZE_ERR, NULL),
47 
48 	MIB_DESC(1, YT921X_MIB_DATA_RX_DROPPED, NULL),
49 	MIB_DESC(1, YT921X_MIB_DATA_TX_BROADCAST, NULL),
50 	MIB_DESC(1, YT921X_MIB_DATA_TX_PAUSE, NULL),
51 	MIB_DESC(1, YT921X_MIB_DATA_TX_MULTICAST, NULL),
52 
53 	MIB_DESC(1, YT921X_MIB_DATA_TX_UNDERSIZE_ERR, NULL),
54 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_64, NULL),
55 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_65_TO_127, NULL),
56 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_128_TO_255, NULL),
57 
58 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_256_TO_511, NULL),
59 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_512_TO_1023, NULL),
60 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1024_TO_1518, NULL),
61 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1519_TO_MAX, NULL),
62 
63 	MIB_DESC(2, YT921X_MIB_DATA_TX_GOOD_BYTES, NULL),
64 	MIB_DESC(1, YT921X_MIB_DATA_TX_COLLISION, NULL),
65 
66 	MIB_DESC(1, YT921X_MIB_DATA_TX_EXCESSIVE_COLLISION, NULL),
67 	MIB_DESC(1, YT921X_MIB_DATA_TX_MULTIPLE_COLLISION, NULL),
68 	MIB_DESC(1, YT921X_MIB_DATA_TX_SINGLE_COLLISION, NULL),
69 	MIB_DESC(1, YT921X_MIB_DATA_TX_PKT, NULL),
70 
71 	MIB_DESC(1, YT921X_MIB_DATA_TX_DEFERRED, NULL),
72 	MIB_DESC(1, YT921X_MIB_DATA_TX_LATE_COLLISION, NULL),
73 	MIB_DESC(1, YT921X_MIB_DATA_RX_OAM, "RxOAM"),
74 	MIB_DESC(1, YT921X_MIB_DATA_TX_OAM, "TxOAM"),
75 };
76 
77 static_assert(ARRAY_SIZE(yt921x_mib_descs) == YT921X_MIB_STAT_NUM);
78 
79 /* The interval should be small enough to avoid overflow of 32bit MIBs.
80  *
81  * Until we can read MIBs from stats64 call directly (i.e. sleep
82  * there), we have to poll stats more frequently then it is actually needed.
83  * For overflow protection, normally, 100 sec interval should have been OK.
84  */
85 #define YT921X_STATS_INTERVAL_JIFFIES	(3 * HZ)
86 
87 /* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */
88 static int yt921x_mib_read(struct yt921x_priv *priv, int port)
89 {
90 	struct device *dev = yt921x_priv_to_device(priv);
91 	struct yt921x_port *pp = &priv->ports[port];
92 	struct yt921x_mib *pm = pp->mib;
93 	struct yt921x_mib_stats *mib;
94 	u64 *buf = pm->data;
95 	unsigned long flags;
96 	u64 rx_frames;
97 	u64 tx_frames;
98 	int res = 0;
99 
100 	mib = &pm->stats;
101 
102 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
103 		const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
104 		u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
105 		u32 val0;
106 		u64 val;
107 
108 		res = yt921x_reg_read(priv, reg, &val0);
109 		if (res)
110 			break;
111 
112 		if (desc->size <= 1) {
113 			u64 old_val = buf[i];
114 
115 			val = (old_val & ~(u64)U32_MAX) | val0;
116 			if (val < old_val)
117 				val += 1ull << 32;
118 		} else {
119 			u32 val1;
120 
121 			res = yt921x_reg_read(priv, reg + 4, &val1);
122 			if (res)
123 				break;
124 			val = ((u64)val1 << 32) | val0;
125 		}
126 
127 		buf[i] = val;
128 	}
129 
130 	flags = u64_stats_update_begin_irqsave(&pm->syncp);
131 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++)
132 		u64_stats_set(&((u64_stats_t *)mib)[i], buf[i]);
133 	rx_frames = u64_stats_read(&mib->rx_64byte) +
134 		    u64_stats_read(&mib->rx_65_127byte) +
135 		    u64_stats_read(&mib->rx_128_255byte) +
136 		    u64_stats_read(&mib->rx_256_511byte) +
137 		    u64_stats_read(&mib->rx_512_1023byte) +
138 		    u64_stats_read(&mib->rx_1024_1518byte) +
139 		    u64_stats_read(&mib->rx_jumbo);
140 	tx_frames = u64_stats_read(&mib->tx_64byte) +
141 		    u64_stats_read(&mib->tx_65_127byte) +
142 		    u64_stats_read(&mib->tx_128_255byte) +
143 		    u64_stats_read(&mib->tx_256_511byte) +
144 		    u64_stats_read(&mib->tx_512_1023byte) +
145 		    u64_stats_read(&mib->tx_1024_1518byte) +
146 		    u64_stats_read(&mib->tx_jumbo);
147 	u64_stats_set(&pm->rx_frames, rx_frames);
148 	u64_stats_set(&pm->tx_frames, tx_frames);
149 	u64_stats_update_end_irqrestore(&pm->syncp, flags);
150 
151 	if (res)
152 		dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
153 			port, res);
154 	return res;
155 }
156 
157 void yt921x_mib_poll(struct work_struct *work)
158 {
159 	struct yt921x_mib *pm = container_of_const(work, struct yt921x_mib,
160 						   work.work);
161 	struct yt921x_port *pp = pm->port;
162 	unsigned long delay = YT921X_STATS_INTERVAL_JIFFIES;
163 	struct yt921x_priv *priv = yt921x_port_to_priv(pp);
164 	int port = pp->index;
165 	int res;
166 
167 	mutex_lock(&priv->reg_lock);
168 	res = yt921x_mib_read(priv, port);
169 	mutex_unlock(&priv->reg_lock);
170 	if (res)
171 		delay *= 4;
172 
173 	schedule_delayed_work(&pm->work, delay);
174 }
175 
176 void
177 yt921x_dsa_get_strings(struct dsa_switch *ds, int port, u32 stringset,
178 		       uint8_t *data)
179 {
180 	if (stringset != ETH_SS_STATS)
181 		return;
182 
183 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
184 		const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
185 
186 		if (desc->name)
187 			ethtool_puts(&data, desc->name);
188 	}
189 }
190 
191 void
192 yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
193 {
194 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
195 	struct yt921x_port *pp = &priv->ports[port];
196 	struct yt921x_mib *pm = pp->mib;
197 	u64 *buf;
198 	size_t j;
199 
200 	if (!pm)
201 		return;
202 	buf = pm->data;
203 
204 	mutex_lock(&priv->reg_lock);
205 
206 	yt921x_mib_read(priv, port);
207 
208 	j = 0;
209 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
210 		const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
211 
212 		if (!desc->name)
213 			continue;
214 
215 		data[j] = buf[i];
216 		j++;
217 	}
218 
219 	mutex_unlock(&priv->reg_lock);
220 }
221 
222 int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset)
223 {
224 	int cnt = 0;
225 
226 	if (sset != ETH_SS_STATS)
227 		return 0;
228 
229 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
230 		const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
231 
232 		if (desc->name)
233 			cnt++;
234 	}
235 
236 	return cnt;
237 }
238 
239 void
240 yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
241 			     struct ethtool_eth_mac_stats *mac_stats)
242 {
243 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
244 	struct yt921x_port *pp = &priv->ports[port];
245 	struct yt921x_mib *pm = pp->mib;
246 	struct yt921x_mib_stats *mib;
247 
248 	if (!pm)
249 		return;
250 	mib = &pm->stats;
251 
252 	mutex_lock(&priv->reg_lock);
253 
254 	yt921x_mib_read(priv, port);
255 
256 	mac_stats->FramesTransmittedOK = u64_stats_read(&pm->tx_frames);
257 	mac_stats->SingleCollisionFrames = u64_stats_read(&mib->tx_single_collisions);
258 	mac_stats->MultipleCollisionFrames = u64_stats_read(&mib->tx_multiple_collisions);
259 	mac_stats->FramesReceivedOK = u64_stats_read(&pm->rx_frames);
260 	mac_stats->FrameCheckSequenceErrors = u64_stats_read(&mib->rx_crc_errors);
261 	mac_stats->AlignmentErrors = u64_stats_read(&mib->rx_alignment_errors);
262 	mac_stats->OctetsTransmittedOK = u64_stats_read(&mib->tx_good_bytes);
263 	mac_stats->FramesWithDeferredXmissions = u64_stats_read(&mib->tx_deferred);
264 	mac_stats->LateCollisions = u64_stats_read(&mib->tx_late_collisions);
265 	mac_stats->FramesAbortedDueToXSColls = u64_stats_read(&mib->tx_aborted_errors);
266 	/* mac_stats->FramesLostDueToIntMACXmitError */
267 	/* mac_stats->CarrierSenseErrors */
268 	mac_stats->OctetsReceivedOK = u64_stats_read(&mib->rx_good_bytes);
269 	/* mac_stats->FramesLostDueToIntMACRcvError */
270 	mac_stats->MulticastFramesXmittedOK = u64_stats_read(&mib->tx_multicast);
271 	mac_stats->BroadcastFramesXmittedOK = u64_stats_read(&mib->tx_broadcast);
272 	/* mac_stats->FramesWithExcessiveDeferral */
273 	mac_stats->MulticastFramesReceivedOK = u64_stats_read(&mib->rx_multicast);
274 	mac_stats->BroadcastFramesReceivedOK = u64_stats_read(&mib->rx_broadcast);
275 	/* mac_stats->InRangeLengthErrors */
276 	/* mac_stats->OutOfRangeLengthField */
277 	mac_stats->FrameTooLongErrors = u64_stats_read(&mib->rx_oversize_errors);
278 
279 	mutex_unlock(&priv->reg_lock);
280 }
281 
282 void
283 yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
284 			      struct ethtool_eth_ctrl_stats *ctrl_stats)
285 {
286 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
287 	struct yt921x_port *pp = &priv->ports[port];
288 	struct yt921x_mib *pm = pp->mib;
289 	struct yt921x_mib_stats *mib;
290 
291 	if (!pm)
292 		return;
293 	mib = &pm->stats;
294 
295 	mutex_lock(&priv->reg_lock);
296 
297 	yt921x_mib_read(priv, port);
298 
299 	ctrl_stats->MACControlFramesTransmitted = u64_stats_read(&mib->tx_pause);
300 	ctrl_stats->MACControlFramesReceived = u64_stats_read(&mib->rx_pause);
301 	/* ctrl_stats->UnsupportedOpcodesReceived */
302 
303 	mutex_unlock(&priv->reg_lock);
304 }
305 
306 static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = {
307 	{ 0, 64 },
308 	{ 65, 127 },
309 	{ 128, 255 },
310 	{ 256, 511 },
311 	{ 512, 1023 },
312 	{ 1024, 1518 },
313 	{ 1519, YT921X_FRAME_SIZE_MAX },
314 	{}
315 };
316 
317 void
318 yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
319 			  struct ethtool_rmon_stats *rmon_stats,
320 			  const struct ethtool_rmon_hist_range **ranges)
321 {
322 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
323 	struct yt921x_port *pp = &priv->ports[port];
324 	struct yt921x_mib *pm = pp->mib;
325 	struct yt921x_mib_stats *mib;
326 
327 	if (!pm)
328 		return;
329 	mib = &pm->stats;
330 
331 	mutex_lock(&priv->reg_lock);
332 
333 	yt921x_mib_read(priv, port);
334 
335 	*ranges = yt921x_rmon_ranges;
336 
337 	rmon_stats->undersize_pkts = u64_stats_read(&mib->rx_undersize_errors);
338 	rmon_stats->oversize_pkts = u64_stats_read(&mib->rx_oversize_errors);
339 	rmon_stats->fragments = u64_stats_read(&mib->rx_alignment_errors);
340 	/* rmon_stats->jabbers */
341 
342 	rmon_stats->hist[0] = u64_stats_read(&mib->rx_64byte);
343 	rmon_stats->hist[1] = u64_stats_read(&mib->rx_65_127byte);
344 	rmon_stats->hist[2] = u64_stats_read(&mib->rx_128_255byte);
345 	rmon_stats->hist[3] = u64_stats_read(&mib->rx_256_511byte);
346 	rmon_stats->hist[4] = u64_stats_read(&mib->rx_512_1023byte);
347 	rmon_stats->hist[5] = u64_stats_read(&mib->rx_1024_1518byte);
348 	rmon_stats->hist[6] = u64_stats_read(&mib->rx_jumbo);
349 
350 	rmon_stats->hist_tx[0] = u64_stats_read(&mib->tx_64byte);
351 	rmon_stats->hist_tx[1] = u64_stats_read(&mib->tx_65_127byte);
352 	rmon_stats->hist_tx[2] = u64_stats_read(&mib->tx_128_255byte);
353 	rmon_stats->hist_tx[3] = u64_stats_read(&mib->tx_256_511byte);
354 	rmon_stats->hist_tx[4] = u64_stats_read(&mib->tx_512_1023byte);
355 	rmon_stats->hist_tx[5] = u64_stats_read(&mib->tx_1024_1518byte);
356 	rmon_stats->hist_tx[6] = u64_stats_read(&mib->tx_jumbo);
357 
358 	mutex_unlock(&priv->reg_lock);
359 }
360 
361 void
362 yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
363 		       struct rtnl_link_stats64 *stats)
364 {
365 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
366 	struct yt921x_port *pp = &priv->ports[port];
367 	struct yt921x_mib *pm = pp->mib;
368 	struct yt921x_mib_stats *mib;
369 	unsigned int start;
370 
371 	if (!pm)
372 		return;
373 	mib = &pm->stats;
374 
375 	do {
376 		start = u64_stats_fetch_begin(&pm->syncp);
377 
378 		stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) +
379 					  u64_stats_read(&mib->rx_fragment_errors);
380 		stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors);
381 		stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors);
382 		stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors);
383 		/* stats->rx_fifo_errors */
384 		/* stats->rx_missed_errors */
385 
386 		stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors);
387 		/* stats->tx_carrier_errors */
388 		stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors);
389 		/* stats->tx_heartbeat_errors */
390 		stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions);
391 
392 		stats->rx_packets = u64_stats_read(&pm->rx_frames);
393 		stats->tx_packets = u64_stats_read(&pm->tx_frames);
394 		stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) -
395 				  ETH_FCS_LEN * stats->rx_packets;
396 		stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) -
397 				  ETH_FCS_LEN * stats->tx_packets;
398 		stats->rx_dropped = u64_stats_read(&mib->rx_dropped);
399 		/* stats->tx_dropped */
400 		stats->multicast = u64_stats_read(&mib->rx_multicast);
401 		stats->collisions = u64_stats_read(&mib->tx_collisions);
402 	} while (u64_stats_fetch_retry(&pm->syncp, start));
403 
404 	stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
405 			   stats->rx_crc_errors + stats->rx_frame_errors;
406 	stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
407 			   stats->tx_window_errors;
408 }
409 
410 void
411 yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
412 			   struct ethtool_pause_stats *pause_stats)
413 {
414 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
415 	struct yt921x_port *pp = &priv->ports[port];
416 	struct yt921x_mib *pm = pp->mib;
417 	struct yt921x_mib_stats *mib;
418 
419 	if (!pm)
420 		return;
421 	mib = &pm->stats;
422 
423 	mutex_lock(&priv->reg_lock);
424 
425 	yt921x_mib_read(priv, port);
426 
427 	pause_stats->tx_pause_frames = u64_stats_read(&mib->tx_pause);
428 	pause_stats->rx_pause_frames = u64_stats_read(&mib->rx_pause);
429 
430 	mutex_unlock(&priv->reg_lock);
431 }
432