WIP FPC-III support
[linux/fpc-iii.git] / drivers / net / dsa / sja1105 / sja1105_ethtool.c
blob9133a831ec79d91eb7f4939fe7b28ef173ec3a35
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
3 */
4 #include "sja1105.h"
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)
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;
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;
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 */
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;
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;
100 static void
101 sja1105_port_status_mac_unpack(void *buf,
102 struct sja1105_port_status_mac *status)
104 /* Make pointer arithmetic work on 4 bytes */
105 u32 *p = buf;
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);
133 static void
134 sja1105_port_status_hl1_unpack(void *buf,
135 struct sja1105_port_status_hl1 *status)
137 /* Make pointer arithmetic work on 4 bytes */
138 u32 *p = buf;
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;
162 static void
163 sja1105_port_status_hl2_unpack(void *buf,
164 struct sja1105_port_status_hl2 *status)
166 /* Make pointer arithmetic work on 4 bytes */
167 u32 *p = buf;
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);
175 static void
176 sja1105pqrs_port_status_qlevel_unpack(void *buf,
177 struct sja1105_port_status_hl2 *status)
179 /* Make pointer arithmetic work on 4 bytes */
180 u32 *p = buf;
181 int i;
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);
189 static void
190 sja1105pqrs_port_status_ether_unpack(void *buf,
191 struct sja1105_port_status_ether *status)
193 /* Make pointer arithmetic work on 4 bytes */
194 u32 *p = buf;
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);
221 static int
222 sja1105pqrs_port_status_get_ether(struct sja1105_private *priv,
223 struct sja1105_port_status_ether *ether,
224 int port)
226 const struct sja1105_regs *regs = priv->info->regs;
227 u8 packed_buf[SJA1105_SIZE_ETHER_AREA] = {0};
228 int rc;
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;
236 sja1105pqrs_port_status_ether_unpack(packed_buf, ether);
238 return 0;
241 static int sja1105_port_status_get_mac(struct sja1105_private *priv,
242 struct sja1105_port_status_mac *status,
243 int port)
245 const struct sja1105_regs *regs = priv->info->regs;
246 u8 packed_buf[SJA1105_SIZE_MAC_AREA] = {0};
247 int rc;
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;
255 sja1105_port_status_mac_unpack(packed_buf, status);
257 return 0;
260 static int sja1105_port_status_get_hl1(struct sja1105_private *priv,
261 struct sja1105_port_status_hl1 *status,
262 int port)
264 const struct sja1105_regs *regs = priv->info->regs;
265 u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0};
266 int rc;
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;
273 sja1105_port_status_hl1_unpack(packed_buf, status);
275 return 0;
278 static int sja1105_port_status_get_hl2(struct sja1105_private *priv,
279 struct sja1105_port_status_hl2 *status,
280 int port)
282 const struct sja1105_regs *regs = priv->info->regs;
283 u8 packed_buf[SJA1105_SIZE_QLEVEL_AREA] = {0};
284 int rc;
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;
291 sja1105_port_status_hl2_unpack(packed_buf, status);
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;
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;
303 sja1105pqrs_port_status_qlevel_unpack(packed_buf, status);
305 return 0;
308 static int sja1105_port_status_get(struct sja1105_private *priv,
309 struct sja1105_port_status *status,
310 int port)
312 int rc;
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;
324 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
325 priv->info->device_id == SJA1105T_DEVICE_ID)
326 return 0;
328 return sja1105pqrs_port_status_get_ether(priv, &status->ether, port);
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",
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",
421 void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
423 struct sja1105_private *priv = ds->priv;
424 struct sja1105_port_status *status;
425 int rc, i, k = 0;
427 status = kzalloc(sizeof(*status), GFP_KERNEL);
428 if (!status)
429 goto out;
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;
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;
479 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
480 priv->info->device_id == SJA1105T_DEVICE_ID)
481 goto out;
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];
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;
512 out:
513 kfree(status);
516 void sja1105_get_strings(struct dsa_switch *ds, int port,
517 u32 stringset, u8 *data)
519 struct sja1105_private *priv = ds->priv;
520 u8 *p = data;
521 int i;
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;
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;
537 break;
541 int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
543 int count = ARRAY_SIZE(sja1105_port_stats);
544 struct sja1105_private *priv = ds->priv;
546 if (sset != ETH_SS_STATS)
547 return -EOPNOTSUPP;
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);
553 return count;