xref: /linux/drivers/net/dsa/sja1105/sja1105_ethtool.c (revision 30a2e9c0f5cf8892255e21153952cd347c81b36b)
152c34e6eSVladimir Oltean // SPDX-License-Identifier: GPL-2.0
252c34e6eSVladimir Oltean /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
352c34e6eSVladimir Oltean  */
452c34e6eSVladimir Oltean #include "sja1105.h"
552c34e6eSVladimir Oltean 
652c34e6eSVladimir Oltean #define SJA1105_SIZE_MAC_AREA		(0x02 * 4)
752c34e6eSVladimir Oltean #define SJA1105_SIZE_HL1_AREA		(0x10 * 4)
852c34e6eSVladimir Oltean #define SJA1105_SIZE_HL2_AREA		(0x4 * 4)
9336aa67bSVladimir Oltean #define SJA1105_SIZE_ETHER_AREA		(0x17 * 4)
1052c34e6eSVladimir Oltean 
1152c34e6eSVladimir Oltean struct sja1105_port_status_mac {
1252c34e6eSVladimir Oltean 	u64 n_runt;
1352c34e6eSVladimir Oltean 	u64 n_soferr;
1452c34e6eSVladimir Oltean 	u64 n_alignerr;
1552c34e6eSVladimir Oltean 	u64 n_miierr;
1652c34e6eSVladimir Oltean 	u64 typeerr;
1752c34e6eSVladimir Oltean 	u64 sizeerr;
1852c34e6eSVladimir Oltean 	u64 tctimeout;
1952c34e6eSVladimir Oltean 	u64 priorerr;
2052c34e6eSVladimir Oltean 	u64 nomaster;
2152c34e6eSVladimir Oltean 	u64 memov;
2252c34e6eSVladimir Oltean 	u64 memerr;
2352c34e6eSVladimir Oltean 	u64 invtyp;
2452c34e6eSVladimir Oltean 	u64 intcyov;
2552c34e6eSVladimir Oltean 	u64 domerr;
2652c34e6eSVladimir Oltean 	u64 pcfbagdrop;
2752c34e6eSVladimir Oltean 	u64 spcprior;
2852c34e6eSVladimir Oltean 	u64 ageprior;
2952c34e6eSVladimir Oltean 	u64 portdrop;
3052c34e6eSVladimir Oltean 	u64 lendrop;
3152c34e6eSVladimir Oltean 	u64 bagdrop;
3252c34e6eSVladimir Oltean 	u64 policeerr;
3352c34e6eSVladimir Oltean 	u64 drpnona664err;
3452c34e6eSVladimir Oltean 	u64 spcerr;
3552c34e6eSVladimir Oltean 	u64 agedrp;
3652c34e6eSVladimir Oltean };
3752c34e6eSVladimir Oltean 
3852c34e6eSVladimir Oltean struct sja1105_port_status_hl1 {
3952c34e6eSVladimir Oltean 	u64 n_n664err;
4052c34e6eSVladimir Oltean 	u64 n_vlanerr;
4152c34e6eSVladimir Oltean 	u64 n_unreleased;
4252c34e6eSVladimir Oltean 	u64 n_sizeerr;
4352c34e6eSVladimir Oltean 	u64 n_crcerr;
4452c34e6eSVladimir Oltean 	u64 n_vlnotfound;
4552c34e6eSVladimir Oltean 	u64 n_ctpolerr;
4652c34e6eSVladimir Oltean 	u64 n_polerr;
4752c34e6eSVladimir Oltean 	u64 n_rxfrmsh;
4852c34e6eSVladimir Oltean 	u64 n_rxfrm;
4952c34e6eSVladimir Oltean 	u64 n_rxbytesh;
5052c34e6eSVladimir Oltean 	u64 n_rxbyte;
5152c34e6eSVladimir Oltean 	u64 n_txfrmsh;
5252c34e6eSVladimir Oltean 	u64 n_txfrm;
5352c34e6eSVladimir Oltean 	u64 n_txbytesh;
5452c34e6eSVladimir Oltean 	u64 n_txbyte;
5552c34e6eSVladimir Oltean };
5652c34e6eSVladimir Oltean 
5752c34e6eSVladimir Oltean struct sja1105_port_status_hl2 {
5852c34e6eSVladimir Oltean 	u64 n_qfull;
5952c34e6eSVladimir Oltean 	u64 n_part_drop;
6052c34e6eSVladimir Oltean 	u64 n_egr_disabled;
6152c34e6eSVladimir Oltean 	u64 n_not_reach;
6252c34e6eSVladimir Oltean };
6352c34e6eSVladimir Oltean 
64336aa67bSVladimir Oltean struct sja1105_port_status_ether {
65336aa67bSVladimir Oltean 	u64 n_drops_nolearn;
66336aa67bSVladimir Oltean 	u64 n_drops_noroute;
67336aa67bSVladimir Oltean 	u64 n_drops_ill_dtag;
68336aa67bSVladimir Oltean 	u64 n_drops_dtag;
69336aa67bSVladimir Oltean 	u64 n_drops_sotag;
70336aa67bSVladimir Oltean 	u64 n_drops_sitag;
71336aa67bSVladimir Oltean 	u64 n_drops_utag;
72336aa67bSVladimir Oltean 	u64 n_tx_bytes_1024_2047;
73336aa67bSVladimir Oltean 	u64 n_tx_bytes_512_1023;
74336aa67bSVladimir Oltean 	u64 n_tx_bytes_256_511;
75336aa67bSVladimir Oltean 	u64 n_tx_bytes_128_255;
76336aa67bSVladimir Oltean 	u64 n_tx_bytes_65_127;
77336aa67bSVladimir Oltean 	u64 n_tx_bytes_64;
78336aa67bSVladimir Oltean 	u64 n_tx_mcast;
79336aa67bSVladimir Oltean 	u64 n_tx_bcast;
80336aa67bSVladimir Oltean 	u64 n_rx_bytes_1024_2047;
81336aa67bSVladimir Oltean 	u64 n_rx_bytes_512_1023;
82336aa67bSVladimir Oltean 	u64 n_rx_bytes_256_511;
83336aa67bSVladimir Oltean 	u64 n_rx_bytes_128_255;
84336aa67bSVladimir Oltean 	u64 n_rx_bytes_65_127;
85336aa67bSVladimir Oltean 	u64 n_rx_bytes_64;
86336aa67bSVladimir Oltean 	u64 n_rx_mcast;
87336aa67bSVladimir Oltean 	u64 n_rx_bcast;
88336aa67bSVladimir Oltean };
89336aa67bSVladimir Oltean 
9052c34e6eSVladimir Oltean struct sja1105_port_status {
9152c34e6eSVladimir Oltean 	struct sja1105_port_status_mac mac;
9252c34e6eSVladimir Oltean 	struct sja1105_port_status_hl1 hl1;
9352c34e6eSVladimir Oltean 	struct sja1105_port_status_hl2 hl2;
94336aa67bSVladimir Oltean 	struct sja1105_port_status_ether ether;
9552c34e6eSVladimir Oltean };
9652c34e6eSVladimir Oltean 
9752c34e6eSVladimir Oltean static void
9852c34e6eSVladimir Oltean sja1105_port_status_mac_unpack(void *buf,
9952c34e6eSVladimir Oltean 			       struct sja1105_port_status_mac *status)
10052c34e6eSVladimir Oltean {
10152c34e6eSVladimir Oltean 	/* Make pointer arithmetic work on 4 bytes */
10252c34e6eSVladimir Oltean 	u32 *p = buf;
10352c34e6eSVladimir Oltean 
10452c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x0, &status->n_runt,       31, 24, 4);
10552c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x0, &status->n_soferr,     23, 16, 4);
10652c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x0, &status->n_alignerr,   15,  8, 4);
10752c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x0, &status->n_miierr,      7,  0, 4);
10852c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->typeerr,      27, 27, 4);
10952c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->sizeerr,      26, 26, 4);
11052c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->tctimeout,    25, 25, 4);
11152c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->priorerr,     24, 24, 4);
11252c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->nomaster,     23, 23, 4);
11352c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->memov,        22, 22, 4);
11452c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->memerr,       21, 21, 4);
11552c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->invtyp,       19, 19, 4);
11652c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->intcyov,      18, 18, 4);
11752c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->domerr,       17, 17, 4);
11852c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->pcfbagdrop,   16, 16, 4);
11952c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->spcprior,     15, 12, 4);
12052c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->ageprior,     11,  8, 4);
12152c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->portdrop,      6,  6, 4);
12252c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->lendrop,       5,  5, 4);
12352c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->bagdrop,       4,  4, 4);
12452c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->policeerr,     3,  3, 4);
12552c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->drpnona664err, 2,  2, 4);
12652c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->spcerr,        1,  1, 4);
12752c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->agedrp,        0,  0, 4);
12852c34e6eSVladimir Oltean }
12952c34e6eSVladimir Oltean 
13052c34e6eSVladimir Oltean static void
13152c34e6eSVladimir Oltean sja1105_port_status_hl1_unpack(void *buf,
13252c34e6eSVladimir Oltean 			       struct sja1105_port_status_hl1 *status)
13352c34e6eSVladimir Oltean {
13452c34e6eSVladimir Oltean 	/* Make pointer arithmetic work on 4 bytes */
13552c34e6eSVladimir Oltean 	u32 *p = buf;
13652c34e6eSVladimir Oltean 
13752c34e6eSVladimir Oltean 	sja1105_unpack(p + 0xF, &status->n_n664err,    31,  0, 4);
13852c34e6eSVladimir Oltean 	sja1105_unpack(p + 0xE, &status->n_vlanerr,    31,  0, 4);
13952c34e6eSVladimir Oltean 	sja1105_unpack(p + 0xD, &status->n_unreleased, 31,  0, 4);
14052c34e6eSVladimir Oltean 	sja1105_unpack(p + 0xC, &status->n_sizeerr,    31,  0, 4);
14152c34e6eSVladimir Oltean 	sja1105_unpack(p + 0xB, &status->n_crcerr,     31,  0, 4);
14252c34e6eSVladimir Oltean 	sja1105_unpack(p + 0xA, &status->n_vlnotfound, 31,  0, 4);
14352c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x9, &status->n_ctpolerr,   31,  0, 4);
14452c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x8, &status->n_polerr,     31,  0, 4);
14552c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x7, &status->n_rxfrmsh,    31,  0, 4);
14652c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x6, &status->n_rxfrm,      31,  0, 4);
14752c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x5, &status->n_rxbytesh,   31,  0, 4);
14852c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x4, &status->n_rxbyte,     31,  0, 4);
14952c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x3, &status->n_txfrmsh,    31,  0, 4);
15052c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x2, &status->n_txfrm,      31,  0, 4);
15152c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->n_txbytesh,   31,  0, 4);
15252c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x0, &status->n_txbyte,     31,  0, 4);
15352c34e6eSVladimir Oltean 	status->n_rxfrm  += status->n_rxfrmsh  << 32;
15452c34e6eSVladimir Oltean 	status->n_rxbyte += status->n_rxbytesh << 32;
15552c34e6eSVladimir Oltean 	status->n_txfrm  += status->n_txfrmsh  << 32;
15652c34e6eSVladimir Oltean 	status->n_txbyte += status->n_txbytesh << 32;
15752c34e6eSVladimir Oltean }
15852c34e6eSVladimir Oltean 
15952c34e6eSVladimir Oltean static void
16052c34e6eSVladimir Oltean sja1105_port_status_hl2_unpack(void *buf,
16152c34e6eSVladimir Oltean 			       struct sja1105_port_status_hl2 *status)
16252c34e6eSVladimir Oltean {
16352c34e6eSVladimir Oltean 	/* Make pointer arithmetic work on 4 bytes */
16452c34e6eSVladimir Oltean 	u32 *p = buf;
16552c34e6eSVladimir Oltean 
16652c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x3, &status->n_qfull,        31,  0, 4);
16752c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x2, &status->n_part_drop,    31,  0, 4);
16852c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x1, &status->n_egr_disabled, 31,  0, 4);
16952c34e6eSVladimir Oltean 	sja1105_unpack(p + 0x0, &status->n_not_reach,    31,  0, 4);
17052c34e6eSVladimir Oltean }
17152c34e6eSVladimir Oltean 
17252c34e6eSVladimir Oltean static void
173336aa67bSVladimir Oltean sja1105pqrs_port_status_ether_unpack(void *buf,
174336aa67bSVladimir Oltean 				     struct sja1105_port_status_ether *status)
175336aa67bSVladimir Oltean {
176336aa67bSVladimir Oltean 	/* Make pointer arithmetic work on 4 bytes */
177336aa67bSVladimir Oltean 	u32 *p = buf;
178336aa67bSVladimir Oltean 
179336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x16, &status->n_drops_nolearn,      31, 0, 4);
180336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x15, &status->n_drops_noroute,      31, 0, 4);
181336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x14, &status->n_drops_ill_dtag,     31, 0, 4);
182336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x13, &status->n_drops_dtag,         31, 0, 4);
183336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x12, &status->n_drops_sotag,        31, 0, 4);
184336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x11, &status->n_drops_sitag,        31, 0, 4);
185336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x10, &status->n_drops_utag,         31, 0, 4);
186336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x0F, &status->n_tx_bytes_1024_2047, 31, 0, 4);
187336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x0E, &status->n_tx_bytes_512_1023,  31, 0, 4);
188336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x0D, &status->n_tx_bytes_256_511,   31, 0, 4);
189336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x0C, &status->n_tx_bytes_128_255,   31, 0, 4);
190336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x0B, &status->n_tx_bytes_65_127,    31, 0, 4);
191336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x0A, &status->n_tx_bytes_64,        31, 0, 4);
192336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x09, &status->n_tx_mcast,           31, 0, 4);
193336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x08, &status->n_tx_bcast,           31, 0, 4);
194336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x07, &status->n_rx_bytes_1024_2047, 31, 0, 4);
195336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x06, &status->n_rx_bytes_512_1023,  31, 0, 4);
196336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x05, &status->n_rx_bytes_256_511,   31, 0, 4);
197336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x04, &status->n_rx_bytes_128_255,   31, 0, 4);
198336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x03, &status->n_rx_bytes_65_127,    31, 0, 4);
199336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x02, &status->n_rx_bytes_64,        31, 0, 4);
200336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x01, &status->n_rx_mcast,           31, 0, 4);
201336aa67bSVladimir Oltean 	sja1105_unpack(p + 0x00, &status->n_rx_bcast,           31, 0, 4);
202336aa67bSVladimir Oltean }
203336aa67bSVladimir Oltean 
204336aa67bSVladimir Oltean static int
205336aa67bSVladimir Oltean sja1105pqrs_port_status_get_ether(struct sja1105_private *priv,
206336aa67bSVladimir Oltean 				  struct sja1105_port_status_ether *ether,
207336aa67bSVladimir Oltean 				  int port)
208336aa67bSVladimir Oltean {
209336aa67bSVladimir Oltean 	const struct sja1105_regs *regs = priv->info->regs;
210336aa67bSVladimir Oltean 	u8 packed_buf[SJA1105_SIZE_ETHER_AREA] = {0};
211336aa67bSVladimir Oltean 	int rc;
212336aa67bSVladimir Oltean 
213336aa67bSVladimir Oltean 	/* Ethernet statistics area */
214336aa67bSVladimir Oltean 	rc = sja1105_xfer_buf(priv, SPI_READ, regs->ether_stats[port],
215336aa67bSVladimir Oltean 			      packed_buf, SJA1105_SIZE_ETHER_AREA);
216336aa67bSVladimir Oltean 	if (rc < 0)
217336aa67bSVladimir Oltean 		return rc;
218336aa67bSVladimir Oltean 
219336aa67bSVladimir Oltean 	sja1105pqrs_port_status_ether_unpack(packed_buf, ether);
220336aa67bSVladimir Oltean 
221336aa67bSVladimir Oltean 	return 0;
222336aa67bSVladimir Oltean }
223336aa67bSVladimir Oltean 
22452c34e6eSVladimir Oltean static int sja1105_port_status_get_mac(struct sja1105_private *priv,
22552c34e6eSVladimir Oltean 				       struct sja1105_port_status_mac *status,
22652c34e6eSVladimir Oltean 				       int port)
22752c34e6eSVladimir Oltean {
22852c34e6eSVladimir Oltean 	const struct sja1105_regs *regs = priv->info->regs;
22952c34e6eSVladimir Oltean 	u8 packed_buf[SJA1105_SIZE_MAC_AREA] = {0};
23052c34e6eSVladimir Oltean 	int rc;
23152c34e6eSVladimir Oltean 
23252c34e6eSVladimir Oltean 	/* MAC area */
2331bd44870SVladimir Oltean 	rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac[port], packed_buf,
2341bd44870SVladimir Oltean 			      SJA1105_SIZE_MAC_AREA);
23552c34e6eSVladimir Oltean 	if (rc < 0)
23652c34e6eSVladimir Oltean 		return rc;
23752c34e6eSVladimir Oltean 
23852c34e6eSVladimir Oltean 	sja1105_port_status_mac_unpack(packed_buf, status);
23952c34e6eSVladimir Oltean 
24052c34e6eSVladimir Oltean 	return 0;
24152c34e6eSVladimir Oltean }
24252c34e6eSVladimir Oltean 
24352c34e6eSVladimir Oltean static int sja1105_port_status_get_hl1(struct sja1105_private *priv,
24452c34e6eSVladimir Oltean 				       struct sja1105_port_status_hl1 *status,
24552c34e6eSVladimir Oltean 				       int port)
24652c34e6eSVladimir Oltean {
24752c34e6eSVladimir Oltean 	const struct sja1105_regs *regs = priv->info->regs;
24852c34e6eSVladimir Oltean 	u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0};
24952c34e6eSVladimir Oltean 	int rc;
25052c34e6eSVladimir Oltean 
2511bd44870SVladimir Oltean 	rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl1[port], packed_buf,
2521bd44870SVladimir Oltean 			      SJA1105_SIZE_HL1_AREA);
25352c34e6eSVladimir Oltean 	if (rc < 0)
25452c34e6eSVladimir Oltean 		return rc;
25552c34e6eSVladimir Oltean 
25652c34e6eSVladimir Oltean 	sja1105_port_status_hl1_unpack(packed_buf, status);
25752c34e6eSVladimir Oltean 
25852c34e6eSVladimir Oltean 	return 0;
25952c34e6eSVladimir Oltean }
26052c34e6eSVladimir Oltean 
26152c34e6eSVladimir Oltean static int sja1105_port_status_get_hl2(struct sja1105_private *priv,
26252c34e6eSVladimir Oltean 				       struct sja1105_port_status_hl2 *status,
26352c34e6eSVladimir Oltean 				       int port)
26452c34e6eSVladimir Oltean {
26552c34e6eSVladimir Oltean 	const struct sja1105_regs *regs = priv->info->regs;
266*30a2e9c0SVladimir Oltean 	u8 packed_buf[SJA1105_SIZE_HL2_AREA] = {0};
26752c34e6eSVladimir Oltean 	int rc;
26852c34e6eSVladimir Oltean 
2691bd44870SVladimir Oltean 	rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl2[port], packed_buf,
2701bd44870SVladimir Oltean 			      SJA1105_SIZE_HL2_AREA);
27152c34e6eSVladimir Oltean 	if (rc < 0)
27252c34e6eSVladimir Oltean 		return rc;
27352c34e6eSVladimir Oltean 
27452c34e6eSVladimir Oltean 	sja1105_port_status_hl2_unpack(packed_buf, status);
27552c34e6eSVladimir Oltean 
27652c34e6eSVladimir Oltean 	return 0;
27752c34e6eSVladimir Oltean }
27852c34e6eSVladimir Oltean 
27952c34e6eSVladimir Oltean static int sja1105_port_status_get(struct sja1105_private *priv,
28052c34e6eSVladimir Oltean 				   struct sja1105_port_status *status,
28152c34e6eSVladimir Oltean 				   int port)
28252c34e6eSVladimir Oltean {
28352c34e6eSVladimir Oltean 	int rc;
28452c34e6eSVladimir Oltean 
28552c34e6eSVladimir Oltean 	rc = sja1105_port_status_get_mac(priv, &status->mac, port);
28652c34e6eSVladimir Oltean 	if (rc < 0)
28752c34e6eSVladimir Oltean 		return rc;
28852c34e6eSVladimir Oltean 	rc = sja1105_port_status_get_hl1(priv, &status->hl1, port);
28952c34e6eSVladimir Oltean 	if (rc < 0)
29052c34e6eSVladimir Oltean 		return rc;
29152c34e6eSVladimir Oltean 	rc = sja1105_port_status_get_hl2(priv, &status->hl2, port);
29252c34e6eSVladimir Oltean 	if (rc < 0)
29352c34e6eSVladimir Oltean 		return rc;
29452c34e6eSVladimir Oltean 
295336aa67bSVladimir Oltean 	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
296336aa67bSVladimir Oltean 	    priv->info->device_id == SJA1105T_DEVICE_ID)
29752c34e6eSVladimir Oltean 		return 0;
298336aa67bSVladimir Oltean 
299336aa67bSVladimir Oltean 	return sja1105pqrs_port_status_get_ether(priv, &status->ether, port);
30052c34e6eSVladimir Oltean }
30152c34e6eSVladimir Oltean 
30252c34e6eSVladimir Oltean static char sja1105_port_stats[][ETH_GSTRING_LEN] = {
30352c34e6eSVladimir Oltean 	/* MAC-Level Diagnostic Counters */
30452c34e6eSVladimir Oltean 	"n_runt",
30552c34e6eSVladimir Oltean 	"n_soferr",
30652c34e6eSVladimir Oltean 	"n_alignerr",
30752c34e6eSVladimir Oltean 	"n_miierr",
30852c34e6eSVladimir Oltean 	/* MAC-Level Diagnostic Flags */
30952c34e6eSVladimir Oltean 	"typeerr",
31052c34e6eSVladimir Oltean 	"sizeerr",
31152c34e6eSVladimir Oltean 	"tctimeout",
31252c34e6eSVladimir Oltean 	"priorerr",
31352c34e6eSVladimir Oltean 	"nomaster",
31452c34e6eSVladimir Oltean 	"memov",
31552c34e6eSVladimir Oltean 	"memerr",
31652c34e6eSVladimir Oltean 	"invtyp",
31752c34e6eSVladimir Oltean 	"intcyov",
31852c34e6eSVladimir Oltean 	"domerr",
31952c34e6eSVladimir Oltean 	"pcfbagdrop",
32052c34e6eSVladimir Oltean 	"spcprior",
32152c34e6eSVladimir Oltean 	"ageprior",
32252c34e6eSVladimir Oltean 	"portdrop",
32352c34e6eSVladimir Oltean 	"lendrop",
32452c34e6eSVladimir Oltean 	"bagdrop",
32552c34e6eSVladimir Oltean 	"policeerr",
32652c34e6eSVladimir Oltean 	"drpnona664err",
32752c34e6eSVladimir Oltean 	"spcerr",
32852c34e6eSVladimir Oltean 	"agedrp",
32952c34e6eSVladimir Oltean 	/* High-Level Diagnostic Counters */
33052c34e6eSVladimir Oltean 	"n_n664err",
33152c34e6eSVladimir Oltean 	"n_vlanerr",
33252c34e6eSVladimir Oltean 	"n_unreleased",
33352c34e6eSVladimir Oltean 	"n_sizeerr",
33452c34e6eSVladimir Oltean 	"n_crcerr",
33552c34e6eSVladimir Oltean 	"n_vlnotfound",
33652c34e6eSVladimir Oltean 	"n_ctpolerr",
33752c34e6eSVladimir Oltean 	"n_polerr",
33852c34e6eSVladimir Oltean 	"n_rxfrm",
33952c34e6eSVladimir Oltean 	"n_rxbyte",
34052c34e6eSVladimir Oltean 	"n_txfrm",
34152c34e6eSVladimir Oltean 	"n_txbyte",
34252c34e6eSVladimir Oltean 	"n_qfull",
34352c34e6eSVladimir Oltean 	"n_part_drop",
34452c34e6eSVladimir Oltean 	"n_egr_disabled",
34552c34e6eSVladimir Oltean 	"n_not_reach",
34652c34e6eSVladimir Oltean };
34752c34e6eSVladimir Oltean 
34852c34e6eSVladimir Oltean static char sja1105pqrs_extra_port_stats[][ETH_GSTRING_LEN] = {
349336aa67bSVladimir Oltean 	/* Ether Stats */
350336aa67bSVladimir Oltean 	"n_drops_nolearn",
351336aa67bSVladimir Oltean 	"n_drops_noroute",
352336aa67bSVladimir Oltean 	"n_drops_ill_dtag",
353336aa67bSVladimir Oltean 	"n_drops_dtag",
354336aa67bSVladimir Oltean 	"n_drops_sotag",
355336aa67bSVladimir Oltean 	"n_drops_sitag",
356336aa67bSVladimir Oltean 	"n_drops_utag",
357336aa67bSVladimir Oltean 	"n_tx_bytes_1024_2047",
358336aa67bSVladimir Oltean 	"n_tx_bytes_512_1023",
359336aa67bSVladimir Oltean 	"n_tx_bytes_256_511",
360336aa67bSVladimir Oltean 	"n_tx_bytes_128_255",
361336aa67bSVladimir Oltean 	"n_tx_bytes_65_127",
362336aa67bSVladimir Oltean 	"n_tx_bytes_64",
363336aa67bSVladimir Oltean 	"n_tx_mcast",
364336aa67bSVladimir Oltean 	"n_tx_bcast",
365336aa67bSVladimir Oltean 	"n_rx_bytes_1024_2047",
366336aa67bSVladimir Oltean 	"n_rx_bytes_512_1023",
367336aa67bSVladimir Oltean 	"n_rx_bytes_256_511",
368336aa67bSVladimir Oltean 	"n_rx_bytes_128_255",
369336aa67bSVladimir Oltean 	"n_rx_bytes_65_127",
370336aa67bSVladimir Oltean 	"n_rx_bytes_64",
371336aa67bSVladimir Oltean 	"n_rx_mcast",
372336aa67bSVladimir Oltean 	"n_rx_bcast",
37352c34e6eSVladimir Oltean };
37452c34e6eSVladimir Oltean 
37552c34e6eSVladimir Oltean void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
37652c34e6eSVladimir Oltean {
37752c34e6eSVladimir Oltean 	struct sja1105_private *priv = ds->priv;
378ae1804deSArnd Bergmann 	struct sja1105_port_status *status;
379*30a2e9c0SVladimir Oltean 	int rc, k = 0;
38052c34e6eSVladimir Oltean 
381ae1804deSArnd Bergmann 	status = kzalloc(sizeof(*status), GFP_KERNEL);
382ae1804deSArnd Bergmann 	if (!status)
383ae1804deSArnd Bergmann 		goto out;
3848e8673a2SNathan Chancellor 
385ae1804deSArnd Bergmann 	rc = sja1105_port_status_get(priv, status, port);
38652c34e6eSVladimir Oltean 	if (rc < 0) {
38752c34e6eSVladimir Oltean 		dev_err(ds->dev, "Failed to read port %d counters: %d\n",
38852c34e6eSVladimir Oltean 			port, rc);
389ae1804deSArnd Bergmann 		goto out;
39052c34e6eSVladimir Oltean 	}
39152c34e6eSVladimir Oltean 	memset(data, 0, ARRAY_SIZE(sja1105_port_stats) * sizeof(u64));
392ae1804deSArnd Bergmann 	data[k++] = status->mac.n_runt;
393ae1804deSArnd Bergmann 	data[k++] = status->mac.n_soferr;
394ae1804deSArnd Bergmann 	data[k++] = status->mac.n_alignerr;
395ae1804deSArnd Bergmann 	data[k++] = status->mac.n_miierr;
396ae1804deSArnd Bergmann 	data[k++] = status->mac.typeerr;
397ae1804deSArnd Bergmann 	data[k++] = status->mac.sizeerr;
398ae1804deSArnd Bergmann 	data[k++] = status->mac.tctimeout;
399ae1804deSArnd Bergmann 	data[k++] = status->mac.priorerr;
400ae1804deSArnd Bergmann 	data[k++] = status->mac.nomaster;
401ae1804deSArnd Bergmann 	data[k++] = status->mac.memov;
402ae1804deSArnd Bergmann 	data[k++] = status->mac.memerr;
403ae1804deSArnd Bergmann 	data[k++] = status->mac.invtyp;
404ae1804deSArnd Bergmann 	data[k++] = status->mac.intcyov;
405ae1804deSArnd Bergmann 	data[k++] = status->mac.domerr;
406ae1804deSArnd Bergmann 	data[k++] = status->mac.pcfbagdrop;
407ae1804deSArnd Bergmann 	data[k++] = status->mac.spcprior;
408ae1804deSArnd Bergmann 	data[k++] = status->mac.ageprior;
409ae1804deSArnd Bergmann 	data[k++] = status->mac.portdrop;
410ae1804deSArnd Bergmann 	data[k++] = status->mac.lendrop;
411ae1804deSArnd Bergmann 	data[k++] = status->mac.bagdrop;
412ae1804deSArnd Bergmann 	data[k++] = status->mac.policeerr;
413ae1804deSArnd Bergmann 	data[k++] = status->mac.drpnona664err;
414ae1804deSArnd Bergmann 	data[k++] = status->mac.spcerr;
415ae1804deSArnd Bergmann 	data[k++] = status->mac.agedrp;
416ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_n664err;
417ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_vlanerr;
418ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_unreleased;
419ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_sizeerr;
420ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_crcerr;
421ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_vlnotfound;
422ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_ctpolerr;
423ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_polerr;
424ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_rxfrm;
425ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_rxbyte;
426ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_txfrm;
427ae1804deSArnd Bergmann 	data[k++] = status->hl1.n_txbyte;
428ae1804deSArnd Bergmann 	data[k++] = status->hl2.n_qfull;
429ae1804deSArnd Bergmann 	data[k++] = status->hl2.n_part_drop;
430ae1804deSArnd Bergmann 	data[k++] = status->hl2.n_egr_disabled;
431ae1804deSArnd Bergmann 	data[k++] = status->hl2.n_not_reach;
43252c34e6eSVladimir Oltean 
43352c34e6eSVladimir Oltean 	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
43452c34e6eSVladimir Oltean 	    priv->info->device_id == SJA1105T_DEVICE_ID)
4354f6cd04fSkbuild test robot 		goto out;
43652c34e6eSVladimir Oltean 
43752c34e6eSVladimir Oltean 	memset(data + k, 0, ARRAY_SIZE(sja1105pqrs_extra_port_stats) *
43852c34e6eSVladimir Oltean 			sizeof(u64));
439ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_nolearn;
440ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_noroute;
441ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_ill_dtag;
442ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_dtag;
443ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_sotag;
444ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_sitag;
445ae1804deSArnd Bergmann 	data[k++] = status->ether.n_drops_utag;
446ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bytes_1024_2047;
447ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bytes_512_1023;
448ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bytes_256_511;
449ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bytes_128_255;
450ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bytes_65_127;
451ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bytes_64;
452ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_mcast;
453ae1804deSArnd Bergmann 	data[k++] = status->ether.n_tx_bcast;
454ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bytes_1024_2047;
455ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bytes_512_1023;
456ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bytes_256_511;
457ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bytes_128_255;
458ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bytes_65_127;
459ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bytes_64;
460ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_mcast;
461ae1804deSArnd Bergmann 	data[k++] = status->ether.n_rx_bcast;
462ae1804deSArnd Bergmann out:
463ae1804deSArnd Bergmann 	kfree(status);
46452c34e6eSVladimir Oltean }
46552c34e6eSVladimir Oltean 
46652c34e6eSVladimir Oltean void sja1105_get_strings(struct dsa_switch *ds, int port,
46752c34e6eSVladimir Oltean 			 u32 stringset, u8 *data)
46852c34e6eSVladimir Oltean {
46952c34e6eSVladimir Oltean 	struct sja1105_private *priv = ds->priv;
47052c34e6eSVladimir Oltean 	u8 *p = data;
47152c34e6eSVladimir Oltean 	int i;
47252c34e6eSVladimir Oltean 
47352c34e6eSVladimir Oltean 	switch (stringset) {
47452c34e6eSVladimir Oltean 	case ETH_SS_STATS:
47552c34e6eSVladimir Oltean 		for (i = 0; i < ARRAY_SIZE(sja1105_port_stats); i++) {
47652c34e6eSVladimir Oltean 			strlcpy(p, sja1105_port_stats[i], ETH_GSTRING_LEN);
47752c34e6eSVladimir Oltean 			p += ETH_GSTRING_LEN;
47852c34e6eSVladimir Oltean 		}
47952c34e6eSVladimir Oltean 		if (priv->info->device_id == SJA1105E_DEVICE_ID ||
48052c34e6eSVladimir Oltean 		    priv->info->device_id == SJA1105T_DEVICE_ID)
48152c34e6eSVladimir Oltean 			return;
48252c34e6eSVladimir Oltean 		for (i = 0; i < ARRAY_SIZE(sja1105pqrs_extra_port_stats); i++) {
48352c34e6eSVladimir Oltean 			strlcpy(p, sja1105pqrs_extra_port_stats[i],
48452c34e6eSVladimir Oltean 				ETH_GSTRING_LEN);
48552c34e6eSVladimir Oltean 			p += ETH_GSTRING_LEN;
48652c34e6eSVladimir Oltean 		}
48752c34e6eSVladimir Oltean 		break;
48852c34e6eSVladimir Oltean 	}
48952c34e6eSVladimir Oltean }
49052c34e6eSVladimir Oltean 
49152c34e6eSVladimir Oltean int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
49252c34e6eSVladimir Oltean {
49352c34e6eSVladimir Oltean 	int count = ARRAY_SIZE(sja1105_port_stats);
49452c34e6eSVladimir Oltean 	struct sja1105_private *priv = ds->priv;
49552c34e6eSVladimir Oltean 
49652c34e6eSVladimir Oltean 	if (sset != ETH_SS_STATS)
49752c34e6eSVladimir Oltean 		return -EOPNOTSUPP;
49852c34e6eSVladimir Oltean 
49952c34e6eSVladimir Oltean 	if (priv->info->device_id == SJA1105PR_DEVICE_ID ||
50052c34e6eSVladimir Oltean 	    priv->info->device_id == SJA1105QS_DEVICE_ID)
50152c34e6eSVladimir Oltean 		count += ARRAY_SIZE(sja1105pqrs_extra_port_stats);
50252c34e6eSVladimir Oltean 
50352c34e6eSVladimir Oltean 	return count;
50452c34e6eSVladimir Oltean }
505