Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
  3 */
  4#include "sja1105.h"
  5
  6#define SJA1105_SIZE_MAC_AREA		(0x02 * 4)
  7#define SJA1105_SIZE_HL1_AREA		(0x10 * 4)
  8#define SJA1105_SIZE_HL2_AREA		(0x4 * 4)
  9#define SJA1105_SIZE_QLEVEL_AREA	(0x8 * 4) /* 0x4 to 0xB */
 10#define SJA1105_SIZE_ETHER_AREA		(0x17 * 4)
 11
 12struct sja1105_port_status_mac {
 13	u64 n_runt;
 14	u64 n_soferr;
 15	u64 n_alignerr;
 16	u64 n_miierr;
 17	u64 typeerr;
 18	u64 sizeerr;
 19	u64 tctimeout;
 20	u64 priorerr;
 21	u64 nomaster;
 22	u64 memov;
 23	u64 memerr;
 24	u64 invtyp;
 25	u64 intcyov;
 26	u64 domerr;
 27	u64 pcfbagdrop;
 28	u64 spcprior;
 29	u64 ageprior;
 30	u64 portdrop;
 31	u64 lendrop;
 32	u64 bagdrop;
 33	u64 policeerr;
 34	u64 drpnona664err;
 35	u64 spcerr;
 36	u64 agedrp;
 37};
 38
 39struct sja1105_port_status_hl1 {
 40	u64 n_n664err;
 41	u64 n_vlanerr;
 42	u64 n_unreleased;
 43	u64 n_sizeerr;
 44	u64 n_crcerr;
 45	u64 n_vlnotfound;
 46	u64 n_ctpolerr;
 47	u64 n_polerr;
 48	u64 n_rxfrmsh;
 49	u64 n_rxfrm;
 50	u64 n_rxbytesh;
 51	u64 n_rxbyte;
 52	u64 n_txfrmsh;
 53	u64 n_txfrm;
 54	u64 n_txbytesh;
 55	u64 n_txbyte;
 56};
 57
 58struct sja1105_port_status_hl2 {
 59	u64 n_qfull;
 60	u64 n_part_drop;
 61	u64 n_egr_disabled;
 62	u64 n_not_reach;
 63	u64 qlevel_hwm[8]; /* Only for P/Q/R/S */
 64	u64 qlevel[8];     /* Only for P/Q/R/S */
 65};
 66
 67struct sja1105_port_status_ether {
 68	u64 n_drops_nolearn;
 69	u64 n_drops_noroute;
 70	u64 n_drops_ill_dtag;
 71	u64 n_drops_dtag;
 72	u64 n_drops_sotag;
 73	u64 n_drops_sitag;
 74	u64 n_drops_utag;
 75	u64 n_tx_bytes_1024_2047;
 76	u64 n_tx_bytes_512_1023;
 77	u64 n_tx_bytes_256_511;
 78	u64 n_tx_bytes_128_255;
 79	u64 n_tx_bytes_65_127;
 80	u64 n_tx_bytes_64;
 81	u64 n_tx_mcast;
 82	u64 n_tx_bcast;
 83	u64 n_rx_bytes_1024_2047;
 84	u64 n_rx_bytes_512_1023;
 85	u64 n_rx_bytes_256_511;
 86	u64 n_rx_bytes_128_255;
 87	u64 n_rx_bytes_65_127;
 88	u64 n_rx_bytes_64;
 89	u64 n_rx_mcast;
 90	u64 n_rx_bcast;
 91};
 92
 93struct sja1105_port_status {
 94	struct sja1105_port_status_mac mac;
 95	struct sja1105_port_status_hl1 hl1;
 96	struct sja1105_port_status_hl2 hl2;
 97	struct sja1105_port_status_ether ether;
 98};
 99
100static void
101sja1105_port_status_mac_unpack(void *buf,
102			       struct sja1105_port_status_mac *status)
103{
104	/* Make pointer arithmetic work on 4 bytes */
105	u32 *p = buf;
106
107	sja1105_unpack(p + 0x0, &status->n_runt,       31, 24, 4);
108	sja1105_unpack(p + 0x0, &status->n_soferr,     23, 16, 4);
109	sja1105_unpack(p + 0x0, &status->n_alignerr,   15,  8, 4);
110	sja1105_unpack(p + 0x0, &status->n_miierr,      7,  0, 4);
111	sja1105_unpack(p + 0x1, &status->typeerr,      27, 27, 4);
112	sja1105_unpack(p + 0x1, &status->sizeerr,      26, 26, 4);
113	sja1105_unpack(p + 0x1, &status->tctimeout,    25, 25, 4);
114	sja1105_unpack(p + 0x1, &status->priorerr,     24, 24, 4);
115	sja1105_unpack(p + 0x1, &status->nomaster,     23, 23, 4);
116	sja1105_unpack(p + 0x1, &status->memov,        22, 22, 4);
117	sja1105_unpack(p + 0x1, &status->memerr,       21, 21, 4);
118	sja1105_unpack(p + 0x1, &status->invtyp,       19, 19, 4);
119	sja1105_unpack(p + 0x1, &status->intcyov,      18, 18, 4);
120	sja1105_unpack(p + 0x1, &status->domerr,       17, 17, 4);
121	sja1105_unpack(p + 0x1, &status->pcfbagdrop,   16, 16, 4);
122	sja1105_unpack(p + 0x1, &status->spcprior,     15, 12, 4);
123	sja1105_unpack(p + 0x1, &status->ageprior,     11,  8, 4);
124	sja1105_unpack(p + 0x1, &status->portdrop,      6,  6, 4);
125	sja1105_unpack(p + 0x1, &status->lendrop,       5,  5, 4);
126	sja1105_unpack(p + 0x1, &status->bagdrop,       4,  4, 4);
127	sja1105_unpack(p + 0x1, &status->policeerr,     3,  3, 4);
128	sja1105_unpack(p + 0x1, &status->drpnona664err, 2,  2, 4);
129	sja1105_unpack(p + 0x1, &status->spcerr,        1,  1, 4);
130	sja1105_unpack(p + 0x1, &status->agedrp,        0,  0, 4);
131}
132
133static void
134sja1105_port_status_hl1_unpack(void *buf,
135			       struct sja1105_port_status_hl1 *status)
136{
137	/* Make pointer arithmetic work on 4 bytes */
138	u32 *p = buf;
139
140	sja1105_unpack(p + 0xF, &status->n_n664err,    31,  0, 4);
141	sja1105_unpack(p + 0xE, &status->n_vlanerr,    31,  0, 4);
142	sja1105_unpack(p + 0xD, &status->n_unreleased, 31,  0, 4);
143	sja1105_unpack(p + 0xC, &status->n_sizeerr,    31,  0, 4);
144	sja1105_unpack(p + 0xB, &status->n_crcerr,     31,  0, 4);
145	sja1105_unpack(p + 0xA, &status->n_vlnotfound, 31,  0, 4);
146	sja1105_unpack(p + 0x9, &status->n_ctpolerr,   31,  0, 4);
147	sja1105_unpack(p + 0x8, &status->n_polerr,     31,  0, 4);
148	sja1105_unpack(p + 0x7, &status->n_rxfrmsh,    31,  0, 4);
149	sja1105_unpack(p + 0x6, &status->n_rxfrm,      31,  0, 4);
150	sja1105_unpack(p + 0x5, &status->n_rxbytesh,   31,  0, 4);
151	sja1105_unpack(p + 0x4, &status->n_rxbyte,     31,  0, 4);
152	sja1105_unpack(p + 0x3, &status->n_txfrmsh,    31,  0, 4);
153	sja1105_unpack(p + 0x2, &status->n_txfrm,      31,  0, 4);
154	sja1105_unpack(p + 0x1, &status->n_txbytesh,   31,  0, 4);
155	sja1105_unpack(p + 0x0, &status->n_txbyte,     31,  0, 4);
156	status->n_rxfrm  += status->n_rxfrmsh  << 32;
157	status->n_rxbyte += status->n_rxbytesh << 32;
158	status->n_txfrm  += status->n_txfrmsh  << 32;
159	status->n_txbyte += status->n_txbytesh << 32;
160}
161
162static void
163sja1105_port_status_hl2_unpack(void *buf,
164			       struct sja1105_port_status_hl2 *status)
165{
166	/* Make pointer arithmetic work on 4 bytes */
167	u32 *p = buf;
168
169	sja1105_unpack(p + 0x3, &status->n_qfull,        31,  0, 4);
170	sja1105_unpack(p + 0x2, &status->n_part_drop,    31,  0, 4);
171	sja1105_unpack(p + 0x1, &status->n_egr_disabled, 31,  0, 4);
172	sja1105_unpack(p + 0x0, &status->n_not_reach,    31,  0, 4);
173}
174
175static void
176sja1105pqrs_port_status_qlevel_unpack(void *buf,
177				      struct sja1105_port_status_hl2 *status)
178{
179	/* Make pointer arithmetic work on 4 bytes */
180	u32 *p = buf;
181	int i;
182
183	for (i = 0; i < 8; i++) {
184		sja1105_unpack(p + i, &status->qlevel_hwm[i], 24, 16, 4);
185		sja1105_unpack(p + i, &status->qlevel[i],      8,  0, 4);
186	}
187}
188
189static void
190sja1105pqrs_port_status_ether_unpack(void *buf,
191				     struct sja1105_port_status_ether *status)
192{
193	/* Make pointer arithmetic work on 4 bytes */
194	u32 *p = buf;
195
196	sja1105_unpack(p + 0x16, &status->n_drops_nolearn,      31, 0, 4);
197	sja1105_unpack(p + 0x15, &status->n_drops_noroute,      31, 0, 4);
198	sja1105_unpack(p + 0x14, &status->n_drops_ill_dtag,     31, 0, 4);
199	sja1105_unpack(p + 0x13, &status->n_drops_dtag,         31, 0, 4);
200	sja1105_unpack(p + 0x12, &status->n_drops_sotag,        31, 0, 4);
201	sja1105_unpack(p + 0x11, &status->n_drops_sitag,        31, 0, 4);
202	sja1105_unpack(p + 0x10, &status->n_drops_utag,         31, 0, 4);
203	sja1105_unpack(p + 0x0F, &status->n_tx_bytes_1024_2047, 31, 0, 4);
204	sja1105_unpack(p + 0x0E, &status->n_tx_bytes_512_1023,  31, 0, 4);
205	sja1105_unpack(p + 0x0D, &status->n_tx_bytes_256_511,   31, 0, 4);
206	sja1105_unpack(p + 0x0C, &status->n_tx_bytes_128_255,   31, 0, 4);
207	sja1105_unpack(p + 0x0B, &status->n_tx_bytes_65_127,    31, 0, 4);
208	sja1105_unpack(p + 0x0A, &status->n_tx_bytes_64,        31, 0, 4);
209	sja1105_unpack(p + 0x09, &status->n_tx_mcast,           31, 0, 4);
210	sja1105_unpack(p + 0x08, &status->n_tx_bcast,           31, 0, 4);
211	sja1105_unpack(p + 0x07, &status->n_rx_bytes_1024_2047, 31, 0, 4);
212	sja1105_unpack(p + 0x06, &status->n_rx_bytes_512_1023,  31, 0, 4);
213	sja1105_unpack(p + 0x05, &status->n_rx_bytes_256_511,   31, 0, 4);
214	sja1105_unpack(p + 0x04, &status->n_rx_bytes_128_255,   31, 0, 4);
215	sja1105_unpack(p + 0x03, &status->n_rx_bytes_65_127,    31, 0, 4);
216	sja1105_unpack(p + 0x02, &status->n_rx_bytes_64,        31, 0, 4);
217	sja1105_unpack(p + 0x01, &status->n_rx_mcast,           31, 0, 4);
218	sja1105_unpack(p + 0x00, &status->n_rx_bcast,           31, 0, 4);
219}
220
221static int
222sja1105pqrs_port_status_get_ether(struct sja1105_private *priv,
223				  struct sja1105_port_status_ether *ether,
224				  int port)
225{
226	const struct sja1105_regs *regs = priv->info->regs;
227	u8 packed_buf[SJA1105_SIZE_ETHER_AREA] = {0};
228	int rc;
229
230	/* Ethernet statistics area */
231	rc = sja1105_xfer_buf(priv, SPI_READ, regs->ether_stats[port],
232			      packed_buf, SJA1105_SIZE_ETHER_AREA);
233	if (rc < 0)
234		return rc;
235
236	sja1105pqrs_port_status_ether_unpack(packed_buf, ether);
237
238	return 0;
239}
240
241static int sja1105_port_status_get_mac(struct sja1105_private *priv,
242				       struct sja1105_port_status_mac *status,
243				       int port)
244{
245	const struct sja1105_regs *regs = priv->info->regs;
246	u8 packed_buf[SJA1105_SIZE_MAC_AREA] = {0};
247	int rc;
248
249	/* MAC area */
250	rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac[port], packed_buf,
251			      SJA1105_SIZE_MAC_AREA);
252	if (rc < 0)
253		return rc;
254
255	sja1105_port_status_mac_unpack(packed_buf, status);
256
257	return 0;
258}
259
260static int sja1105_port_status_get_hl1(struct sja1105_private *priv,
261				       struct sja1105_port_status_hl1 *status,
262				       int port)
263{
264	const struct sja1105_regs *regs = priv->info->regs;
265	u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0};
266	int rc;
267
268	rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl1[port], packed_buf,
269			      SJA1105_SIZE_HL1_AREA);
270	if (rc < 0)
271		return rc;
272
273	sja1105_port_status_hl1_unpack(packed_buf, status);
274
275	return 0;
276}
277
278static int sja1105_port_status_get_hl2(struct sja1105_private *priv,
279				       struct sja1105_port_status_hl2 *status,
280				       int port)
281{
282	const struct sja1105_regs *regs = priv->info->regs;
283	u8 packed_buf[SJA1105_SIZE_QLEVEL_AREA] = {0};
284	int rc;
285
286	rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl2[port], packed_buf,
287			      SJA1105_SIZE_HL2_AREA);
288	if (rc < 0)
289		return rc;
290
291	sja1105_port_status_hl2_unpack(packed_buf, status);
292
293	/* Code below is strictly P/Q/R/S specific. */
294	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
295	    priv->info->device_id == SJA1105T_DEVICE_ID)
296		return 0;
297
298	rc = sja1105_xfer_buf(priv, SPI_READ, regs->qlevel[port], packed_buf,
299			      SJA1105_SIZE_QLEVEL_AREA);
300	if (rc < 0)
301		return rc;
302
303	sja1105pqrs_port_status_qlevel_unpack(packed_buf, status);
304
305	return 0;
306}
307
308static int sja1105_port_status_get(struct sja1105_private *priv,
309				   struct sja1105_port_status *status,
310				   int port)
311{
312	int rc;
313
314	rc = sja1105_port_status_get_mac(priv, &status->mac, port);
315	if (rc < 0)
316		return rc;
317	rc = sja1105_port_status_get_hl1(priv, &status->hl1, port);
318	if (rc < 0)
319		return rc;
320	rc = sja1105_port_status_get_hl2(priv, &status->hl2, port);
321	if (rc < 0)
322		return rc;
323
324	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
325	    priv->info->device_id == SJA1105T_DEVICE_ID)
326		return 0;
327
328	return sja1105pqrs_port_status_get_ether(priv, &status->ether, port);
329}
330
331static char sja1105_port_stats[][ETH_GSTRING_LEN] = {
332	/* MAC-Level Diagnostic Counters */
333	"n_runt",
334	"n_soferr",
335	"n_alignerr",
336	"n_miierr",
337	/* MAC-Level Diagnostic Flags */
338	"typeerr",
339	"sizeerr",
340	"tctimeout",
341	"priorerr",
342	"nomaster",
343	"memov",
344	"memerr",
345	"invtyp",
346	"intcyov",
347	"domerr",
348	"pcfbagdrop",
349	"spcprior",
350	"ageprior",
351	"portdrop",
352	"lendrop",
353	"bagdrop",
354	"policeerr",
355	"drpnona664err",
356	"spcerr",
357	"agedrp",
358	/* High-Level Diagnostic Counters */
359	"n_n664err",
360	"n_vlanerr",
361	"n_unreleased",
362	"n_sizeerr",
363	"n_crcerr",
364	"n_vlnotfound",
365	"n_ctpolerr",
366	"n_polerr",
367	"n_rxfrm",
368	"n_rxbyte",
369	"n_txfrm",
370	"n_txbyte",
371	"n_qfull",
372	"n_part_drop",
373	"n_egr_disabled",
374	"n_not_reach",
375};
376
377static char sja1105pqrs_extra_port_stats[][ETH_GSTRING_LEN] = {
378	/* Queue Levels */
379	"qlevel_hwm_0",
380	"qlevel_hwm_1",
381	"qlevel_hwm_2",
382	"qlevel_hwm_3",
383	"qlevel_hwm_4",
384	"qlevel_hwm_5",
385	"qlevel_hwm_6",
386	"qlevel_hwm_7",
387	"qlevel_0",
388	"qlevel_1",
389	"qlevel_2",
390	"qlevel_3",
391	"qlevel_4",
392	"qlevel_5",
393	"qlevel_6",
394	"qlevel_7",
395	/* Ether Stats */
396	"n_drops_nolearn",
397	"n_drops_noroute",
398	"n_drops_ill_dtag",
399	"n_drops_dtag",
400	"n_drops_sotag",
401	"n_drops_sitag",
402	"n_drops_utag",
403	"n_tx_bytes_1024_2047",
404	"n_tx_bytes_512_1023",
405	"n_tx_bytes_256_511",
406	"n_tx_bytes_128_255",
407	"n_tx_bytes_65_127",
408	"n_tx_bytes_64",
409	"n_tx_mcast",
410	"n_tx_bcast",
411	"n_rx_bytes_1024_2047",
412	"n_rx_bytes_512_1023",
413	"n_rx_bytes_256_511",
414	"n_rx_bytes_128_255",
415	"n_rx_bytes_65_127",
416	"n_rx_bytes_64",
417	"n_rx_mcast",
418	"n_rx_bcast",
419};
420
421void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
422{
423	struct sja1105_private *priv = ds->priv;
424	struct sja1105_port_status *status;
425	int rc, i, k = 0;
426
427	status = kzalloc(sizeof(*status), GFP_KERNEL);
428	if (!status)
429		goto out;
430
431	rc = sja1105_port_status_get(priv, status, port);
432	if (rc < 0) {
433		dev_err(ds->dev, "Failed to read port %d counters: %d\n",
434			port, rc);
435		goto out;
436	}
437	memset(data, 0, ARRAY_SIZE(sja1105_port_stats) * sizeof(u64));
438	data[k++] = status->mac.n_runt;
439	data[k++] = status->mac.n_soferr;
440	data[k++] = status->mac.n_alignerr;
441	data[k++] = status->mac.n_miierr;
442	data[k++] = status->mac.typeerr;
443	data[k++] = status->mac.sizeerr;
444	data[k++] = status->mac.tctimeout;
445	data[k++] = status->mac.priorerr;
446	data[k++] = status->mac.nomaster;
447	data[k++] = status->mac.memov;
448	data[k++] = status->mac.memerr;
449	data[k++] = status->mac.invtyp;
450	data[k++] = status->mac.intcyov;
451	data[k++] = status->mac.domerr;
452	data[k++] = status->mac.pcfbagdrop;
453	data[k++] = status->mac.spcprior;
454	data[k++] = status->mac.ageprior;
455	data[k++] = status->mac.portdrop;
456	data[k++] = status->mac.lendrop;
457	data[k++] = status->mac.bagdrop;
458	data[k++] = status->mac.policeerr;
459	data[k++] = status->mac.drpnona664err;
460	data[k++] = status->mac.spcerr;
461	data[k++] = status->mac.agedrp;
462	data[k++] = status->hl1.n_n664err;
463	data[k++] = status->hl1.n_vlanerr;
464	data[k++] = status->hl1.n_unreleased;
465	data[k++] = status->hl1.n_sizeerr;
466	data[k++] = status->hl1.n_crcerr;
467	data[k++] = status->hl1.n_vlnotfound;
468	data[k++] = status->hl1.n_ctpolerr;
469	data[k++] = status->hl1.n_polerr;
470	data[k++] = status->hl1.n_rxfrm;
471	data[k++] = status->hl1.n_rxbyte;
472	data[k++] = status->hl1.n_txfrm;
473	data[k++] = status->hl1.n_txbyte;
474	data[k++] = status->hl2.n_qfull;
475	data[k++] = status->hl2.n_part_drop;
476	data[k++] = status->hl2.n_egr_disabled;
477	data[k++] = status->hl2.n_not_reach;
478
479	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
480	    priv->info->device_id == SJA1105T_DEVICE_ID)
481		goto out;
482
483	memset(data + k, 0, ARRAY_SIZE(sja1105pqrs_extra_port_stats) *
484			sizeof(u64));
485	for (i = 0; i < 8; i++) {
486		data[k++] = status->hl2.qlevel_hwm[i];
487		data[k++] = status->hl2.qlevel[i];
488	}
489	data[k++] = status->ether.n_drops_nolearn;
490	data[k++] = status->ether.n_drops_noroute;
491	data[k++] = status->ether.n_drops_ill_dtag;
492	data[k++] = status->ether.n_drops_dtag;
493	data[k++] = status->ether.n_drops_sotag;
494	data[k++] = status->ether.n_drops_sitag;
495	data[k++] = status->ether.n_drops_utag;
496	data[k++] = status->ether.n_tx_bytes_1024_2047;
497	data[k++] = status->ether.n_tx_bytes_512_1023;
498	data[k++] = status->ether.n_tx_bytes_256_511;
499	data[k++] = status->ether.n_tx_bytes_128_255;
500	data[k++] = status->ether.n_tx_bytes_65_127;
501	data[k++] = status->ether.n_tx_bytes_64;
502	data[k++] = status->ether.n_tx_mcast;
503	data[k++] = status->ether.n_tx_bcast;
504	data[k++] = status->ether.n_rx_bytes_1024_2047;
505	data[k++] = status->ether.n_rx_bytes_512_1023;
506	data[k++] = status->ether.n_rx_bytes_256_511;
507	data[k++] = status->ether.n_rx_bytes_128_255;
508	data[k++] = status->ether.n_rx_bytes_65_127;
509	data[k++] = status->ether.n_rx_bytes_64;
510	data[k++] = status->ether.n_rx_mcast;
511	data[k++] = status->ether.n_rx_bcast;
512out:
513	kfree(status);
514}
515
516void sja1105_get_strings(struct dsa_switch *ds, int port,
517			 u32 stringset, u8 *data)
518{
519	struct sja1105_private *priv = ds->priv;
520	u8 *p = data;
521	int i;
522
523	switch (stringset) {
524	case ETH_SS_STATS:
525		for (i = 0; i < ARRAY_SIZE(sja1105_port_stats); i++) {
526			strlcpy(p, sja1105_port_stats[i], ETH_GSTRING_LEN);
527			p += ETH_GSTRING_LEN;
528		}
529		if (priv->info->device_id == SJA1105E_DEVICE_ID ||
530		    priv->info->device_id == SJA1105T_DEVICE_ID)
531			return;
532		for (i = 0; i < ARRAY_SIZE(sja1105pqrs_extra_port_stats); i++) {
533			strlcpy(p, sja1105pqrs_extra_port_stats[i],
534				ETH_GSTRING_LEN);
535			p += ETH_GSTRING_LEN;
536		}
537		break;
538	}
539}
540
541int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
542{
543	int count = ARRAY_SIZE(sja1105_port_stats);
544	struct sja1105_private *priv = ds->priv;
545
546	if (sset != ETH_SS_STATS)
547		return -EOPNOTSUPP;
548
549	if (priv->info->device_id == SJA1105PR_DEVICE_ID ||
550	    priv->info->device_id == SJA1105QS_DEVICE_ID)
551		count += ARRAY_SIZE(sja1105pqrs_extra_port_stats);
552
553	return count;
554}