630 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>3 */4#include "sja1105.h"5 6enum sja1105_counter_index {7 __SJA1105_COUNTER_UNUSED,8 /* MAC */9 N_RUNT,10 N_SOFERR,11 N_ALIGNERR,12 N_MIIERR,13 TYPEERR,14 SIZEERR,15 TCTIMEOUT,16 PRIORERR,17 NOMASTER,18 MEMOV,19 MEMERR,20 INVTYP,21 INTCYOV,22 DOMERR,23 PCFBAGDROP,24 SPCPRIOR,25 AGEPRIOR,26 PORTDROP,27 LENDROP,28 BAGDROP,29 POLICEERR,30 DRPNONA664ERR,31 SPCERR,32 AGEDRP,33 /* HL1 */34 N_N664ERR,35 N_VLANERR,36 N_UNRELEASED,37 N_SIZEERR,38 N_CRCERR,39 N_VLNOTFOUND,40 N_CTPOLERR,41 N_POLERR,42 N_RXFRM,43 N_RXBYTE,44 N_TXFRM,45 N_TXBYTE,46 /* HL2 */47 N_QFULL,48 N_PART_DROP,49 N_EGR_DISABLED,50 N_NOT_REACH,51 __MAX_SJA1105ET_PORT_COUNTER,52 /* P/Q/R/S only */53 /* ETHER */54 N_DROPS_NOLEARN = __MAX_SJA1105ET_PORT_COUNTER,55 N_DROPS_NOROUTE,56 N_DROPS_ILL_DTAG,57 N_DROPS_DTAG,58 N_DROPS_SOTAG,59 N_DROPS_SITAG,60 N_DROPS_UTAG,61 N_TX_BYTES_1024_2047,62 N_TX_BYTES_512_1023,63 N_TX_BYTES_256_511,64 N_TX_BYTES_128_255,65 N_TX_BYTES_65_127,66 N_TX_BYTES_64,67 N_TX_MCAST,68 N_TX_BCAST,69 N_RX_BYTES_1024_2047,70 N_RX_BYTES_512_1023,71 N_RX_BYTES_256_511,72 N_RX_BYTES_128_255,73 N_RX_BYTES_65_127,74 N_RX_BYTES_64,75 N_RX_MCAST,76 N_RX_BCAST,77 __MAX_SJA1105PQRS_PORT_COUNTER,78};79 80struct sja1105_port_counter {81 enum sja1105_stats_area area;82 const char name[ETH_GSTRING_LEN];83 int offset;84 int start;85 int end;86 bool is_64bit;87};88 89static const struct sja1105_port_counter sja1105_port_counters[] = {90 /* MAC-Level Diagnostic Counters */91 [N_RUNT] = {92 .area = MAC,93 .name = "n_runt",94 .offset = 0,95 .start = 31,96 .end = 24,97 },98 [N_SOFERR] = {99 .area = MAC,100 .name = "n_soferr",101 .offset = 0x0,102 .start = 23,103 .end = 16,104 },105 [N_ALIGNERR] = {106 .area = MAC,107 .name = "n_alignerr",108 .offset = 0x0,109 .start = 15,110 .end = 8,111 },112 [N_MIIERR] = {113 .area = MAC,114 .name = "n_miierr",115 .offset = 0x0,116 .start = 7,117 .end = 0,118 },119 /* MAC-Level Diagnostic Flags */120 [TYPEERR] = {121 .area = MAC,122 .name = "typeerr",123 .offset = 0x1,124 .start = 27,125 .end = 27,126 },127 [SIZEERR] = {128 .area = MAC,129 .name = "sizeerr",130 .offset = 0x1,131 .start = 26,132 .end = 26,133 },134 [TCTIMEOUT] = {135 .area = MAC,136 .name = "tctimeout",137 .offset = 0x1,138 .start = 25,139 .end = 25,140 },141 [PRIORERR] = {142 .area = MAC,143 .name = "priorerr",144 .offset = 0x1,145 .start = 24,146 .end = 24,147 },148 [NOMASTER] = {149 .area = MAC,150 .name = "nomaster",151 .offset = 0x1,152 .start = 23,153 .end = 23,154 },155 [MEMOV] = {156 .area = MAC,157 .name = "memov",158 .offset = 0x1,159 .start = 22,160 .end = 22,161 },162 [MEMERR] = {163 .area = MAC,164 .name = "memerr",165 .offset = 0x1,166 .start = 21,167 .end = 21,168 },169 [INVTYP] = {170 .area = MAC,171 .name = "invtyp",172 .offset = 0x1,173 .start = 19,174 .end = 19,175 },176 [INTCYOV] = {177 .area = MAC,178 .name = "intcyov",179 .offset = 0x1,180 .start = 18,181 .end = 18,182 },183 [DOMERR] = {184 .area = MAC,185 .name = "domerr",186 .offset = 0x1,187 .start = 17,188 .end = 17,189 },190 [PCFBAGDROP] = {191 .area = MAC,192 .name = "pcfbagdrop",193 .offset = 0x1,194 .start = 16,195 .end = 16,196 },197 [SPCPRIOR] = {198 .area = MAC,199 .name = "spcprior",200 .offset = 0x1,201 .start = 15,202 .end = 12,203 },204 [AGEPRIOR] = {205 .area = MAC,206 .name = "ageprior",207 .offset = 0x1,208 .start = 11,209 .end = 8,210 },211 [PORTDROP] = {212 .area = MAC,213 .name = "portdrop",214 .offset = 0x1,215 .start = 6,216 .end = 6,217 },218 [LENDROP] = {219 .area = MAC,220 .name = "lendrop",221 .offset = 0x1,222 .start = 5,223 .end = 5,224 },225 [BAGDROP] = {226 .area = MAC,227 .name = "bagdrop",228 .offset = 0x1,229 .start = 4,230 .end = 4,231 },232 [POLICEERR] = {233 .area = MAC,234 .name = "policeerr",235 .offset = 0x1,236 .start = 3,237 .end = 3,238 },239 [DRPNONA664ERR] = {240 .area = MAC,241 .name = "drpnona664err",242 .offset = 0x1,243 .start = 2,244 .end = 2,245 },246 [SPCERR] = {247 .area = MAC,248 .name = "spcerr",249 .offset = 0x1,250 .start = 1,251 .end = 1,252 },253 [AGEDRP] = {254 .area = MAC,255 .name = "agedrp",256 .offset = 0x1,257 .start = 0,258 .end = 0,259 },260 /* High-Level Diagnostic Counters */261 [N_N664ERR] = {262 .area = HL1,263 .name = "n_n664err",264 .offset = 0xF,265 .start = 31,266 .end = 0,267 },268 [N_VLANERR] = {269 .area = HL1,270 .name = "n_vlanerr",271 .offset = 0xE,272 .start = 31,273 .end = 0,274 },275 [N_UNRELEASED] = {276 .area = HL1,277 .name = "n_unreleased",278 .offset = 0xD,279 .start = 31,280 .end = 0,281 },282 [N_SIZEERR] = {283 .area = HL1,284 .name = "n_sizeerr",285 .offset = 0xC,286 .start = 31,287 .end = 0,288 },289 [N_CRCERR] = {290 .area = HL1,291 .name = "n_crcerr",292 .offset = 0xB,293 .start = 31,294 .end = 0,295 },296 [N_VLNOTFOUND] = {297 .area = HL1,298 .name = "n_vlnotfound",299 .offset = 0xA,300 .start = 31,301 .end = 0,302 },303 [N_CTPOLERR] = {304 .area = HL1,305 .name = "n_ctpolerr",306 .offset = 0x9,307 .start = 31,308 .end = 0,309 },310 [N_POLERR] = {311 .area = HL1,312 .name = "n_polerr",313 .offset = 0x8,314 .start = 31,315 .end = 0,316 },317 [N_RXFRM] = {318 .area = HL1,319 .name = "n_rxfrm",320 .offset = 0x6,321 .start = 31,322 .end = 0,323 .is_64bit = true,324 },325 [N_RXBYTE] = {326 .area = HL1,327 .name = "n_rxbyte",328 .offset = 0x4,329 .start = 31,330 .end = 0,331 .is_64bit = true,332 },333 [N_TXFRM] = {334 .area = HL1,335 .name = "n_txfrm",336 .offset = 0x2,337 .start = 31,338 .end = 0,339 .is_64bit = true,340 },341 [N_TXBYTE] = {342 .area = HL1,343 .name = "n_txbyte",344 .offset = 0x0,345 .start = 31,346 .end = 0,347 .is_64bit = true,348 },349 [N_QFULL] = {350 .area = HL2,351 .name = "n_qfull",352 .offset = 0x3,353 .start = 31,354 .end = 0,355 },356 [N_PART_DROP] = {357 .area = HL2,358 .name = "n_part_drop",359 .offset = 0x2,360 .start = 31,361 .end = 0,362 },363 [N_EGR_DISABLED] = {364 .area = HL2,365 .name = "n_egr_disabled",366 .offset = 0x1,367 .start = 31,368 .end = 0,369 },370 [N_NOT_REACH] = {371 .area = HL2,372 .name = "n_not_reach",373 .offset = 0x0,374 .start = 31,375 .end = 0,376 },377 /* Ether Stats */378 [N_DROPS_NOLEARN] = {379 .area = ETHER,380 .name = "n_drops_nolearn",381 .offset = 0x16,382 .start = 31,383 .end = 0,384 },385 [N_DROPS_NOROUTE] = {386 .area = ETHER,387 .name = "n_drops_noroute",388 .offset = 0x15,389 .start = 31,390 .end = 0,391 },392 [N_DROPS_ILL_DTAG] = {393 .area = ETHER,394 .name = "n_drops_ill_dtag",395 .offset = 0x14,396 .start = 31,397 .end = 0,398 },399 [N_DROPS_DTAG] = {400 .area = ETHER,401 .name = "n_drops_dtag",402 .offset = 0x13,403 .start = 31,404 .end = 0,405 },406 [N_DROPS_SOTAG] = {407 .area = ETHER,408 .name = "n_drops_sotag",409 .offset = 0x12,410 .start = 31,411 .end = 0,412 },413 [N_DROPS_SITAG] = {414 .area = ETHER,415 .name = "n_drops_sitag",416 .offset = 0x11,417 .start = 31,418 .end = 0,419 },420 [N_DROPS_UTAG] = {421 .area = ETHER,422 .name = "n_drops_utag",423 .offset = 0x10,424 .start = 31,425 .end = 0,426 },427 [N_TX_BYTES_1024_2047] = {428 .area = ETHER,429 .name = "n_tx_bytes_1024_2047",430 .offset = 0x0F,431 .start = 31,432 .end = 0,433 },434 [N_TX_BYTES_512_1023] = {435 .area = ETHER,436 .name = "n_tx_bytes_512_1023",437 .offset = 0x0E,438 .start = 31,439 .end = 0,440 },441 [N_TX_BYTES_256_511] = {442 .area = ETHER,443 .name = "n_tx_bytes_256_511",444 .offset = 0x0D,445 .start = 31,446 .end = 0,447 },448 [N_TX_BYTES_128_255] = {449 .area = ETHER,450 .name = "n_tx_bytes_128_255",451 .offset = 0x0C,452 .start = 31,453 .end = 0,454 },455 [N_TX_BYTES_65_127] = {456 .area = ETHER,457 .name = "n_tx_bytes_65_127",458 .offset = 0x0B,459 .start = 31,460 .end = 0,461 },462 [N_TX_BYTES_64] = {463 .area = ETHER,464 .name = "n_tx_bytes_64",465 .offset = 0x0A,466 .start = 31,467 .end = 0,468 },469 [N_TX_MCAST] = {470 .area = ETHER,471 .name = "n_tx_mcast",472 .offset = 0x09,473 .start = 31,474 .end = 0,475 },476 [N_TX_BCAST] = {477 .area = ETHER,478 .name = "n_tx_bcast",479 .offset = 0x08,480 .start = 31,481 .end = 0,482 },483 [N_RX_BYTES_1024_2047] = {484 .area = ETHER,485 .name = "n_rx_bytes_1024_2047",486 .offset = 0x07,487 .start = 31,488 .end = 0,489 },490 [N_RX_BYTES_512_1023] = {491 .area = ETHER,492 .name = "n_rx_bytes_512_1023",493 .offset = 0x06,494 .start = 31,495 .end = 0,496 },497 [N_RX_BYTES_256_511] = {498 .area = ETHER,499 .name = "n_rx_bytes_256_511",500 .offset = 0x05,501 .start = 31,502 .end = 0,503 },504 [N_RX_BYTES_128_255] = {505 .area = ETHER,506 .name = "n_rx_bytes_128_255",507 .offset = 0x04,508 .start = 31,509 .end = 0,510 },511 [N_RX_BYTES_65_127] = {512 .area = ETHER,513 .name = "n_rx_bytes_65_127",514 .offset = 0x03,515 .start = 31,516 .end = 0,517 },518 [N_RX_BYTES_64] = {519 .area = ETHER,520 .name = "n_rx_bytes_64",521 .offset = 0x02,522 .start = 31,523 .end = 0,524 },525 [N_RX_MCAST] = {526 .area = ETHER,527 .name = "n_rx_mcast",528 .offset = 0x01,529 .start = 31,530 .end = 0,531 },532 [N_RX_BCAST] = {533 .area = ETHER,534 .name = "n_rx_bcast",535 .offset = 0x00,536 .start = 31,537 .end = 0,538 },539};540 541static int sja1105_port_counter_read(struct sja1105_private *priv, int port,542 enum sja1105_counter_index idx, u64 *ctr)543{544 const struct sja1105_port_counter *c = &sja1105_port_counters[idx];545 size_t size = c->is_64bit ? 8 : 4;546 u8 buf[8] = {0};547 u64 regs;548 int rc;549 550 regs = priv->info->regs->stats[c->area][port];551 552 rc = sja1105_xfer_buf(priv, SPI_READ, regs + c->offset, buf, size);553 if (rc)554 return rc;555 556 sja1105_unpack(buf, ctr, c->start, c->end, size);557 558 return 0;559}560 561void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)562{563 struct sja1105_private *priv = ds->priv;564 enum sja1105_counter_index max_ctr, i;565 int rc, k = 0;566 567 if (priv->info->device_id == SJA1105E_DEVICE_ID ||568 priv->info->device_id == SJA1105T_DEVICE_ID)569 max_ctr = __MAX_SJA1105ET_PORT_COUNTER;570 else571 max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;572 573 for (i = 0; i < max_ctr; i++) {574 rc = sja1105_port_counter_read(priv, port, i, &data[k++]);575 if (rc) {576 dev_err(ds->dev,577 "Failed to read port %d counters: %d\n",578 port, rc);579 break;580 }581 }582}583 584void sja1105_get_strings(struct dsa_switch *ds, int port,585 u32 stringset, u8 *data)586{587 struct sja1105_private *priv = ds->priv;588 enum sja1105_counter_index max_ctr, i;589 char *p = data;590 591 if (stringset != ETH_SS_STATS)592 return;593 594 if (priv->info->device_id == SJA1105E_DEVICE_ID ||595 priv->info->device_id == SJA1105T_DEVICE_ID)596 max_ctr = __MAX_SJA1105ET_PORT_COUNTER;597 else598 max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;599 600 for (i = 0; i < max_ctr; i++) {601 strscpy(p, sja1105_port_counters[i].name, ETH_GSTRING_LEN);602 p += ETH_GSTRING_LEN;603 }604}605 606int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)607{608 struct sja1105_private *priv = ds->priv;609 enum sja1105_counter_index max_ctr, i;610 int sset_count = 0;611 612 if (sset != ETH_SS_STATS)613 return -EOPNOTSUPP;614 615 if (priv->info->device_id == SJA1105E_DEVICE_ID ||616 priv->info->device_id == SJA1105T_DEVICE_ID)617 max_ctr = __MAX_SJA1105ET_PORT_COUNTER;618 else619 max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;620 621 for (i = 0; i < max_ctr; i++) {622 if (!strlen(sja1105_port_counters[i].name))623 continue;624 625 sset_count++;626 }627 628 return sset_count;629}630