123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright (c) 2018-2019, Vladimir Oltean <[email protected]>
- */
- #include "sja1105.h"
- enum sja1105_counter_index {
- __SJA1105_COUNTER_UNUSED,
- /* MAC */
- N_RUNT,
- N_SOFERR,
- N_ALIGNERR,
- N_MIIERR,
- TYPEERR,
- SIZEERR,
- TCTIMEOUT,
- PRIORERR,
- NOMASTER,
- MEMOV,
- MEMERR,
- INVTYP,
- INTCYOV,
- DOMERR,
- PCFBAGDROP,
- SPCPRIOR,
- AGEPRIOR,
- PORTDROP,
- LENDROP,
- BAGDROP,
- POLICEERR,
- DRPNONA664ERR,
- SPCERR,
- AGEDRP,
- /* HL1 */
- N_N664ERR,
- N_VLANERR,
- N_UNRELEASED,
- N_SIZEERR,
- N_CRCERR,
- N_VLNOTFOUND,
- N_CTPOLERR,
- N_POLERR,
- N_RXFRM,
- N_RXBYTE,
- N_TXFRM,
- N_TXBYTE,
- /* HL2 */
- N_QFULL,
- N_PART_DROP,
- N_EGR_DISABLED,
- N_NOT_REACH,
- __MAX_SJA1105ET_PORT_COUNTER,
- /* P/Q/R/S only */
- /* ETHER */
- N_DROPS_NOLEARN = __MAX_SJA1105ET_PORT_COUNTER,
- N_DROPS_NOROUTE,
- N_DROPS_ILL_DTAG,
- N_DROPS_DTAG,
- N_DROPS_SOTAG,
- N_DROPS_SITAG,
- N_DROPS_UTAG,
- N_TX_BYTES_1024_2047,
- N_TX_BYTES_512_1023,
- N_TX_BYTES_256_511,
- N_TX_BYTES_128_255,
- N_TX_BYTES_65_127,
- N_TX_BYTES_64,
- N_TX_MCAST,
- N_TX_BCAST,
- N_RX_BYTES_1024_2047,
- N_RX_BYTES_512_1023,
- N_RX_BYTES_256_511,
- N_RX_BYTES_128_255,
- N_RX_BYTES_65_127,
- N_RX_BYTES_64,
- N_RX_MCAST,
- N_RX_BCAST,
- __MAX_SJA1105PQRS_PORT_COUNTER,
- };
- struct sja1105_port_counter {
- enum sja1105_stats_area area;
- const char name[ETH_GSTRING_LEN];
- int offset;
- int start;
- int end;
- bool is_64bit;
- };
- static const struct sja1105_port_counter sja1105_port_counters[] = {
- /* MAC-Level Diagnostic Counters */
- [N_RUNT] = {
- .area = MAC,
- .name = "n_runt",
- .offset = 0,
- .start = 31,
- .end = 24,
- },
- [N_SOFERR] = {
- .area = MAC,
- .name = "n_soferr",
- .offset = 0x0,
- .start = 23,
- .end = 16,
- },
- [N_ALIGNERR] = {
- .area = MAC,
- .name = "n_alignerr",
- .offset = 0x0,
- .start = 15,
- .end = 8,
- },
- [N_MIIERR] = {
- .area = MAC,
- .name = "n_miierr",
- .offset = 0x0,
- .start = 7,
- .end = 0,
- },
- /* MAC-Level Diagnostic Flags */
- [TYPEERR] = {
- .area = MAC,
- .name = "typeerr",
- .offset = 0x1,
- .start = 27,
- .end = 27,
- },
- [SIZEERR] = {
- .area = MAC,
- .name = "sizeerr",
- .offset = 0x1,
- .start = 26,
- .end = 26,
- },
- [TCTIMEOUT] = {
- .area = MAC,
- .name = "tctimeout",
- .offset = 0x1,
- .start = 25,
- .end = 25,
- },
- [PRIORERR] = {
- .area = MAC,
- .name = "priorerr",
- .offset = 0x1,
- .start = 24,
- .end = 24,
- },
- [NOMASTER] = {
- .area = MAC,
- .name = "nomaster",
- .offset = 0x1,
- .start = 23,
- .end = 23,
- },
- [MEMOV] = {
- .area = MAC,
- .name = "memov",
- .offset = 0x1,
- .start = 22,
- .end = 22,
- },
- [MEMERR] = {
- .area = MAC,
- .name = "memerr",
- .offset = 0x1,
- .start = 21,
- .end = 21,
- },
- [INVTYP] = {
- .area = MAC,
- .name = "invtyp",
- .offset = 0x1,
- .start = 19,
- .end = 19,
- },
- [INTCYOV] = {
- .area = MAC,
- .name = "intcyov",
- .offset = 0x1,
- .start = 18,
- .end = 18,
- },
- [DOMERR] = {
- .area = MAC,
- .name = "domerr",
- .offset = 0x1,
- .start = 17,
- .end = 17,
- },
- [PCFBAGDROP] = {
- .area = MAC,
- .name = "pcfbagdrop",
- .offset = 0x1,
- .start = 16,
- .end = 16,
- },
- [SPCPRIOR] = {
- .area = MAC,
- .name = "spcprior",
- .offset = 0x1,
- .start = 15,
- .end = 12,
- },
- [AGEPRIOR] = {
- .area = MAC,
- .name = "ageprior",
- .offset = 0x1,
- .start = 11,
- .end = 8,
- },
- [PORTDROP] = {
- .area = MAC,
- .name = "portdrop",
- .offset = 0x1,
- .start = 6,
- .end = 6,
- },
- [LENDROP] = {
- .area = MAC,
- .name = "lendrop",
- .offset = 0x1,
- .start = 5,
- .end = 5,
- },
- [BAGDROP] = {
- .area = MAC,
- .name = "bagdrop",
- .offset = 0x1,
- .start = 4,
- .end = 4,
- },
- [POLICEERR] = {
- .area = MAC,
- .name = "policeerr",
- .offset = 0x1,
- .start = 3,
- .end = 3,
- },
- [DRPNONA664ERR] = {
- .area = MAC,
- .name = "drpnona664err",
- .offset = 0x1,
- .start = 2,
- .end = 2,
- },
- [SPCERR] = {
- .area = MAC,
- .name = "spcerr",
- .offset = 0x1,
- .start = 1,
- .end = 1,
- },
- [AGEDRP] = {
- .area = MAC,
- .name = "agedrp",
- .offset = 0x1,
- .start = 0,
- .end = 0,
- },
- /* High-Level Diagnostic Counters */
- [N_N664ERR] = {
- .area = HL1,
- .name = "n_n664err",
- .offset = 0xF,
- .start = 31,
- .end = 0,
- },
- [N_VLANERR] = {
- .area = HL1,
- .name = "n_vlanerr",
- .offset = 0xE,
- .start = 31,
- .end = 0,
- },
- [N_UNRELEASED] = {
- .area = HL1,
- .name = "n_unreleased",
- .offset = 0xD,
- .start = 31,
- .end = 0,
- },
- [N_SIZEERR] = {
- .area = HL1,
- .name = "n_sizeerr",
- .offset = 0xC,
- .start = 31,
- .end = 0,
- },
- [N_CRCERR] = {
- .area = HL1,
- .name = "n_crcerr",
- .offset = 0xB,
- .start = 31,
- .end = 0,
- },
- [N_VLNOTFOUND] = {
- .area = HL1,
- .name = "n_vlnotfound",
- .offset = 0xA,
- .start = 31,
- .end = 0,
- },
- [N_CTPOLERR] = {
- .area = HL1,
- .name = "n_ctpolerr",
- .offset = 0x9,
- .start = 31,
- .end = 0,
- },
- [N_POLERR] = {
- .area = HL1,
- .name = "n_polerr",
- .offset = 0x8,
- .start = 31,
- .end = 0,
- },
- [N_RXFRM] = {
- .area = HL1,
- .name = "n_rxfrm",
- .offset = 0x6,
- .start = 31,
- .end = 0,
- .is_64bit = true,
- },
- [N_RXBYTE] = {
- .area = HL1,
- .name = "n_rxbyte",
- .offset = 0x4,
- .start = 31,
- .end = 0,
- .is_64bit = true,
- },
- [N_TXFRM] = {
- .area = HL1,
- .name = "n_txfrm",
- .offset = 0x2,
- .start = 31,
- .end = 0,
- .is_64bit = true,
- },
- [N_TXBYTE] = {
- .area = HL1,
- .name = "n_txbyte",
- .offset = 0x0,
- .start = 31,
- .end = 0,
- .is_64bit = true,
- },
- [N_QFULL] = {
- .area = HL2,
- .name = "n_qfull",
- .offset = 0x3,
- .start = 31,
- .end = 0,
- },
- [N_PART_DROP] = {
- .area = HL2,
- .name = "n_part_drop",
- .offset = 0x2,
- .start = 31,
- .end = 0,
- },
- [N_EGR_DISABLED] = {
- .area = HL2,
- .name = "n_egr_disabled",
- .offset = 0x1,
- .start = 31,
- .end = 0,
- },
- [N_NOT_REACH] = {
- .area = HL2,
- .name = "n_not_reach",
- .offset = 0x0,
- .start = 31,
- .end = 0,
- },
- /* Ether Stats */
- [N_DROPS_NOLEARN] = {
- .area = ETHER,
- .name = "n_drops_nolearn",
- .offset = 0x16,
- .start = 31,
- .end = 0,
- },
- [N_DROPS_NOROUTE] = {
- .area = ETHER,
- .name = "n_drops_noroute",
- .offset = 0x15,
- .start = 31,
- .end = 0,
- },
- [N_DROPS_ILL_DTAG] = {
- .area = ETHER,
- .name = "n_drops_ill_dtag",
- .offset = 0x14,
- .start = 31,
- .end = 0,
- },
- [N_DROPS_DTAG] = {
- .area = ETHER,
- .name = "n_drops_dtag",
- .offset = 0x13,
- .start = 31,
- .end = 0,
- },
- [N_DROPS_SOTAG] = {
- .area = ETHER,
- .name = "n_drops_sotag",
- .offset = 0x12,
- .start = 31,
- .end = 0,
- },
- [N_DROPS_SITAG] = {
- .area = ETHER,
- .name = "n_drops_sitag",
- .offset = 0x11,
- .start = 31,
- .end = 0,
- },
- [N_DROPS_UTAG] = {
- .area = ETHER,
- .name = "n_drops_utag",
- .offset = 0x10,
- .start = 31,
- .end = 0,
- },
- [N_TX_BYTES_1024_2047] = {
- .area = ETHER,
- .name = "n_tx_bytes_1024_2047",
- .offset = 0x0F,
- .start = 31,
- .end = 0,
- },
- [N_TX_BYTES_512_1023] = {
- .area = ETHER,
- .name = "n_tx_bytes_512_1023",
- .offset = 0x0E,
- .start = 31,
- .end = 0,
- },
- [N_TX_BYTES_256_511] = {
- .area = ETHER,
- .name = "n_tx_bytes_256_511",
- .offset = 0x0D,
- .start = 31,
- .end = 0,
- },
- [N_TX_BYTES_128_255] = {
- .area = ETHER,
- .name = "n_tx_bytes_128_255",
- .offset = 0x0C,
- .start = 31,
- .end = 0,
- },
- [N_TX_BYTES_65_127] = {
- .area = ETHER,
- .name = "n_tx_bytes_65_127",
- .offset = 0x0B,
- .start = 31,
- .end = 0,
- },
- [N_TX_BYTES_64] = {
- .area = ETHER,
- .name = "n_tx_bytes_64",
- .offset = 0x0A,
- .start = 31,
- .end = 0,
- },
- [N_TX_MCAST] = {
- .area = ETHER,
- .name = "n_tx_mcast",
- .offset = 0x09,
- .start = 31,
- .end = 0,
- },
- [N_TX_BCAST] = {
- .area = ETHER,
- .name = "n_tx_bcast",
- .offset = 0x08,
- .start = 31,
- .end = 0,
- },
- [N_RX_BYTES_1024_2047] = {
- .area = ETHER,
- .name = "n_rx_bytes_1024_2047",
- .offset = 0x07,
- .start = 31,
- .end = 0,
- },
- [N_RX_BYTES_512_1023] = {
- .area = ETHER,
- .name = "n_rx_bytes_512_1023",
- .offset = 0x06,
- .start = 31,
- .end = 0,
- },
- [N_RX_BYTES_256_511] = {
- .area = ETHER,
- .name = "n_rx_bytes_256_511",
- .offset = 0x05,
- .start = 31,
- .end = 0,
- },
- [N_RX_BYTES_128_255] = {
- .area = ETHER,
- .name = "n_rx_bytes_128_255",
- .offset = 0x04,
- .start = 31,
- .end = 0,
- },
- [N_RX_BYTES_65_127] = {
- .area = ETHER,
- .name = "n_rx_bytes_65_127",
- .offset = 0x03,
- .start = 31,
- .end = 0,
- },
- [N_RX_BYTES_64] = {
- .area = ETHER,
- .name = "n_rx_bytes_64",
- .offset = 0x02,
- .start = 31,
- .end = 0,
- },
- [N_RX_MCAST] = {
- .area = ETHER,
- .name = "n_rx_mcast",
- .offset = 0x01,
- .start = 31,
- .end = 0,
- },
- [N_RX_BCAST] = {
- .area = ETHER,
- .name = "n_rx_bcast",
- .offset = 0x00,
- .start = 31,
- .end = 0,
- },
- };
- static int sja1105_port_counter_read(struct sja1105_private *priv, int port,
- enum sja1105_counter_index idx, u64 *ctr)
- {
- const struct sja1105_port_counter *c = &sja1105_port_counters[idx];
- size_t size = c->is_64bit ? 8 : 4;
- u8 buf[8] = {0};
- u64 regs;
- int rc;
- regs = priv->info->regs->stats[c->area][port];
- rc = sja1105_xfer_buf(priv, SPI_READ, regs + c->offset, buf, size);
- if (rc)
- return rc;
- sja1105_unpack(buf, ctr, c->start, c->end, size);
- return 0;
- }
- void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
- {
- struct sja1105_private *priv = ds->priv;
- enum sja1105_counter_index max_ctr, i;
- int rc, k = 0;
- if (priv->info->device_id == SJA1105E_DEVICE_ID ||
- priv->info->device_id == SJA1105T_DEVICE_ID)
- max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
- else
- max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
- for (i = 0; i < max_ctr; i++) {
- rc = sja1105_port_counter_read(priv, port, i, &data[k++]);
- if (rc) {
- dev_err(ds->dev,
- "Failed to read port %d counters: %d\n",
- port, rc);
- break;
- }
- }
- }
- void sja1105_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, u8 *data)
- {
- struct sja1105_private *priv = ds->priv;
- enum sja1105_counter_index max_ctr, i;
- char *p = data;
- if (stringset != ETH_SS_STATS)
- return;
- if (priv->info->device_id == SJA1105E_DEVICE_ID ||
- priv->info->device_id == SJA1105T_DEVICE_ID)
- max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
- else
- max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
- for (i = 0; i < max_ctr; i++) {
- strscpy(p, sja1105_port_counters[i].name, ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
- }
- int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
- {
- struct sja1105_private *priv = ds->priv;
- enum sja1105_counter_index max_ctr, i;
- int sset_count = 0;
- if (sset != ETH_SS_STATS)
- return -EOPNOTSUPP;
- if (priv->info->device_id == SJA1105E_DEVICE_ID ||
- priv->info->device_id == SJA1105T_DEVICE_ID)
- max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
- else
- max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
- for (i = 0; i < max_ctr; i++) {
- if (!strlen(sja1105_port_counters[i].name))
- continue;
- sset_count++;
- }
- return sset_count;
- }
|