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 
12 struct 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 
39 struct 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 
58 struct 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 
67 struct 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 
93 struct 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 
100 static void
101 sja1105_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 
133 static void
134 sja1105_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 
162 static void
163 sja1105_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 
175 static void
176 sja1105pqrs_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 
189 static void
190 sja1105pqrs_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 
221 static int
222 sja1105pqrs_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 
241 static 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 
260 static 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 
278 static 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 
308 static 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 
331 static 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 
377 static 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 
421 void 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 	memset(&status, 0, sizeof(status));
428 
429 	rc = sja1105_port_status_get(priv, &status, port);
430 	if (rc < 0) {
431 		dev_err(ds->dev, "Failed to read port %d counters: %d\n",
432 			port, rc);
433 		return;
434 	}
435 	memset(data, 0, ARRAY_SIZE(sja1105_port_stats) * sizeof(u64));
436 	data[k++] = status.mac.n_runt;
437 	data[k++] = status.mac.n_soferr;
438 	data[k++] = status.mac.n_alignerr;
439 	data[k++] = status.mac.n_miierr;
440 	data[k++] = status.mac.typeerr;
441 	data[k++] = status.mac.sizeerr;
442 	data[k++] = status.mac.tctimeout;
443 	data[k++] = status.mac.priorerr;
444 	data[k++] = status.mac.nomaster;
445 	data[k++] = status.mac.memov;
446 	data[k++] = status.mac.memerr;
447 	data[k++] = status.mac.invtyp;
448 	data[k++] = status.mac.intcyov;
449 	data[k++] = status.mac.domerr;
450 	data[k++] = status.mac.pcfbagdrop;
451 	data[k++] = status.mac.spcprior;
452 	data[k++] = status.mac.ageprior;
453 	data[k++] = status.mac.portdrop;
454 	data[k++] = status.mac.lendrop;
455 	data[k++] = status.mac.bagdrop;
456 	data[k++] = status.mac.policeerr;
457 	data[k++] = status.mac.drpnona664err;
458 	data[k++] = status.mac.spcerr;
459 	data[k++] = status.mac.agedrp;
460 	data[k++] = status.hl1.n_n664err;
461 	data[k++] = status.hl1.n_vlanerr;
462 	data[k++] = status.hl1.n_unreleased;
463 	data[k++] = status.hl1.n_sizeerr;
464 	data[k++] = status.hl1.n_crcerr;
465 	data[k++] = status.hl1.n_vlnotfound;
466 	data[k++] = status.hl1.n_ctpolerr;
467 	data[k++] = status.hl1.n_polerr;
468 	data[k++] = status.hl1.n_rxfrm;
469 	data[k++] = status.hl1.n_rxbyte;
470 	data[k++] = status.hl1.n_txfrm;
471 	data[k++] = status.hl1.n_txbyte;
472 	data[k++] = status.hl2.n_qfull;
473 	data[k++] = status.hl2.n_part_drop;
474 	data[k++] = status.hl2.n_egr_disabled;
475 	data[k++] = status.hl2.n_not_reach;
476 
477 	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
478 	    priv->info->device_id == SJA1105T_DEVICE_ID)
479 		return;
480 
481 	memset(data + k, 0, ARRAY_SIZE(sja1105pqrs_extra_port_stats) *
482 			sizeof(u64));
483 	for (i = 0; i < 8; i++) {
484 		data[k++] = status.hl2.qlevel_hwm[i];
485 		data[k++] = status.hl2.qlevel[i];
486 	}
487 	data[k++] = status.ether.n_drops_nolearn;
488 	data[k++] = status.ether.n_drops_noroute;
489 	data[k++] = status.ether.n_drops_ill_dtag;
490 	data[k++] = status.ether.n_drops_dtag;
491 	data[k++] = status.ether.n_drops_sotag;
492 	data[k++] = status.ether.n_drops_sitag;
493 	data[k++] = status.ether.n_drops_utag;
494 	data[k++] = status.ether.n_tx_bytes_1024_2047;
495 	data[k++] = status.ether.n_tx_bytes_512_1023;
496 	data[k++] = status.ether.n_tx_bytes_256_511;
497 	data[k++] = status.ether.n_tx_bytes_128_255;
498 	data[k++] = status.ether.n_tx_bytes_65_127;
499 	data[k++] = status.ether.n_tx_bytes_64;
500 	data[k++] = status.ether.n_tx_mcast;
501 	data[k++] = status.ether.n_tx_bcast;
502 	data[k++] = status.ether.n_rx_bytes_1024_2047;
503 	data[k++] = status.ether.n_rx_bytes_512_1023;
504 	data[k++] = status.ether.n_rx_bytes_256_511;
505 	data[k++] = status.ether.n_rx_bytes_128_255;
506 	data[k++] = status.ether.n_rx_bytes_65_127;
507 	data[k++] = status.ether.n_rx_bytes_64;
508 	data[k++] = status.ether.n_rx_mcast;
509 	data[k++] = status.ether.n_rx_bcast;
510 }
511 
512 void sja1105_get_strings(struct dsa_switch *ds, int port,
513 			 u32 stringset, u8 *data)
514 {
515 	struct sja1105_private *priv = ds->priv;
516 	u8 *p = data;
517 	int i;
518 
519 	switch (stringset) {
520 	case ETH_SS_STATS:
521 		for (i = 0; i < ARRAY_SIZE(sja1105_port_stats); i++) {
522 			strlcpy(p, sja1105_port_stats[i], ETH_GSTRING_LEN);
523 			p += ETH_GSTRING_LEN;
524 		}
525 		if (priv->info->device_id == SJA1105E_DEVICE_ID ||
526 		    priv->info->device_id == SJA1105T_DEVICE_ID)
527 			return;
528 		for (i = 0; i < ARRAY_SIZE(sja1105pqrs_extra_port_stats); i++) {
529 			strlcpy(p, sja1105pqrs_extra_port_stats[i],
530 				ETH_GSTRING_LEN);
531 			p += ETH_GSTRING_LEN;
532 		}
533 		break;
534 	}
535 }
536 
537 int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
538 {
539 	int count = ARRAY_SIZE(sja1105_port_stats);
540 	struct sja1105_private *priv = ds->priv;
541 
542 	if (sset != ETH_SS_STATS)
543 		return -EOPNOTSUPP;
544 
545 	if (priv->info->device_id == SJA1105PR_DEVICE_ID ||
546 	    priv->info->device_id == SJA1105QS_DEVICE_ID)
547 		count += ARRAY_SIZE(sja1105pqrs_extra_port_stats);
548 
549 	return count;
550 }
551