diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/net/dsa/sja1105/sja1105_ethtool.c | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/net/dsa/sja1105/sja1105_ethtool.c')
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_ethtool.c | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105_ethtool.c b/drivers/net/dsa/sja1105/sja1105_ethtool.c new file mode 100644 index 000000000..decc6c931 --- /dev/null +++ b/drivers/net/dsa/sja1105/sja1105_ethtool.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> + */ +#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; +} |