Implement the ethtool private statistics interface to expose additional port-level and MAC-level counters that are not covered by the standard IEEE 802.3 statistics. The pMAC counters are only reported when the port supports Frame Preemption (802.1Qbu/802.3br). Signed-off-by: Wei Fang --- drivers/net/dsa/netc/netc_ethtool.c | 107 ++++++++++++++++++++++++++ drivers/net/dsa/netc/netc_main.c | 3 + drivers/net/dsa/netc/netc_switch.h | 9 +++ drivers/net/dsa/netc/netc_switch_hw.h | 58 ++++++++++++++ 4 files changed, 177 insertions(+) diff --git a/drivers/net/dsa/netc/netc_ethtool.c b/drivers/net/dsa/netc/netc_ethtool.c index ac8940b5a85c..8d04db534347 100644 --- a/drivers/net/dsa/netc/netc_ethtool.c +++ b/drivers/net/dsa/netc/netc_ethtool.c @@ -19,6 +19,56 @@ static const struct ethtool_rmon_hist_range netc_rmon_ranges[] = { { } }; +static const struct netc_port_stat netc_port_counters[] = { + { NETC_PTGSLACR, "port gate late arrival frames" }, + { NETC_PSDFTCR, "port SDF transmit frames" }, + { NETC_PSDFDDCR, "port SDF drop duplicate frames" }, + { NETC_PRXDCR, "port rx discard frames" }, + { NETC_PRXDCRRR, "port rx discard read-reset" }, + { NETC_PRXDCRR0, "port rx discard reason 0" }, + { NETC_PRXDCRR1, "port rx discard reason 1" }, + { NETC_PTXDCR, "port tx discard frames" }, + { NETC_PTXDCRRR, "port tx discard read-reset" }, + { NETC_PTXDCRR0, "port tx discard reason 0" }, + { NETC_PTXDCRR1, "port tx discard reason 1" }, + { NETC_BPDCR, "bridge port discard frames" }, + { NETC_BPDCRRR, "bridge port discard read-reset" }, + { NETC_BPDCRR0, "bridge port discard reason 0" }, + { NETC_BPDCRR1, "bridge port discard reason 1" }, +}; + +static const struct netc_port_stat netc_emac_counters[] = { + { NETC_PM_ROCT(0), "eMAC rx octets" }, + { NETC_PM_RVLAN(0), "eMAC rx VLAN frames" }, + { NETC_PM_RERR(0), "eMAC rx frame errors" }, + { NETC_PM_RUCA(0), "eMAC rx unicast frames" }, + { NETC_PM_RDRP(0), "eMAC rx dropped packets" }, + { NETC_PM_RPKT(0), "eMAC rx packets" }, + { NETC_PM_TOCT(0), "eMAC tx octets" }, + { NETC_PM_TVLAN(0), "eMAC tx VLAN frames" }, + { NETC_PM_TFCS(0), "eMAC tx FCS errors" }, + { NETC_PM_TUCA(0), "eMAC tx unicast frames" }, + { NETC_PM_TPKT(0), "eMAC tx packets" }, + { NETC_PM_TUND(0), "eMAC tx undersized packets" }, + { NETC_PM_TIOCT(0), "eMAC tx invalid octets" }, +}; + +static const struct netc_port_stat netc_pmac_counters[] = { + { NETC_PM_ROCT(1), "pMAC rx octets" }, + { NETC_PM_RVLAN(1), "pMAC rx VLAN frames" }, + { NETC_PM_RERR(1), "pMAC rx frame errors" }, + { NETC_PM_RUCA(1), "pMAC rx unicast frames" }, + { NETC_PM_RDRP(1), "pMAC rx dropped packets" }, + { NETC_PM_RPKT(1), "pMAC rx packets" }, + { NETC_PM_TOCT(1), "pMAC tx octets" }, + { NETC_PM_TVLAN(1), "pMAC tx VLAN frames" }, + { NETC_PM_TFCS(1), "pMAC tx FCS errors" }, + { NETC_PM_TUCA(1), "pMAC tx unicast frames" }, + { NETC_PM_TPKT(1), "pMAC tx packets" }, + { NETC_PM_TUND(1), "pMAC tx undersized packets" }, + { NETC_PM_TIOCT(1), "pMAC tx invalid octets" }, +}; + static void netc_port_pause_stats(struct netc_port *np, int mac, struct ethtool_pause_stats *stats) { @@ -188,3 +238,60 @@ void netc_port_get_eth_mac_stats(struct dsa_switch *ds, int port, break; } } + +int netc_port_get_sset_count(struct dsa_switch *ds, int port, int sset) +{ + struct netc_port *np = NETC_PORT(ds, port); + int size; + + if (sset != ETH_SS_STATS) + return -EOPNOTSUPP; + + size = ARRAY_SIZE(netc_port_counters) + + ARRAY_SIZE(netc_emac_counters); + + if (np->caps.pmac) + size += ARRAY_SIZE(netc_pmac_counters); + + return size; +} + +void netc_port_get_strings(struct dsa_switch *ds, int port, + u32 sset, u8 *data) +{ + struct netc_port *np = NETC_PORT(ds, port); + int i; + + if (sset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(netc_port_counters); i++) + ethtool_cpy(&data, netc_port_counters[i].name); + + for (i = 0; i < ARRAY_SIZE(netc_emac_counters); i++) + ethtool_cpy(&data, netc_emac_counters[i].name); + + if (!np->caps.pmac) + return; + + for (i = 0; i < ARRAY_SIZE(netc_pmac_counters); i++) + ethtool_cpy(&data, netc_pmac_counters[i].name); +} + +void netc_port_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) +{ + struct netc_port *np = NETC_PORT(ds, port); + int i; + + for (i = 0; i < ARRAY_SIZE(netc_port_counters); i++) + *data++ = netc_port_rd(np, netc_port_counters[i].reg); + + for (i = 0; i < ARRAY_SIZE(netc_emac_counters); i++) + *data++ = netc_port_rd64(np, netc_emac_counters[i].reg); + + if (!np->caps.pmac) + return; + + for (i = 0; i < ARRAY_SIZE(netc_pmac_counters); i++) + *data++ = netc_port_rd64(np, netc_pmac_counters[i].reg); +} diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c index d79bd18b7e6e..fed2b1dcb856 100644 --- a/drivers/net/dsa/netc/netc_main.c +++ b/drivers/net/dsa/netc/netc_main.c @@ -1491,6 +1491,9 @@ static const struct dsa_switch_ops netc_switch_ops = { .get_rmon_stats = netc_port_get_rmon_stats, .get_eth_ctrl_stats = netc_port_get_eth_ctrl_stats, .get_eth_mac_stats = netc_port_get_eth_mac_stats, + .get_sset_count = netc_port_get_sset_count, + .get_strings = netc_port_get_strings, + .get_ethtool_stats = netc_port_get_ethtool_stats, }; static int netc_switch_probe(struct pci_dev *pdev, diff --git a/drivers/net/dsa/netc/netc_switch.h b/drivers/net/dsa/netc/netc_switch.h index 40e54af0c356..740e1f307c45 100644 --- a/drivers/net/dsa/netc/netc_switch.h +++ b/drivers/net/dsa/netc/netc_switch.h @@ -94,6 +94,11 @@ struct netc_fdb_entry { struct hlist_node node; }; +struct netc_port_stat { + int reg; + char name[ETH_GSTRING_LEN] __nonstring; +}; + struct netc_switch { struct pci_dev *pdev; struct device *dev; @@ -160,5 +165,9 @@ void netc_port_get_eth_ctrl_stats(struct dsa_switch *ds, int port, struct ethtool_eth_ctrl_stats *ctrl_stats); void netc_port_get_eth_mac_stats(struct dsa_switch *ds, int port, struct ethtool_eth_mac_stats *mac_stats); +int netc_port_get_sset_count(struct dsa_switch *ds, int port, int sset); +void netc_port_get_strings(struct dsa_switch *ds, int port, + u32 sset, u8 *data); +void netc_port_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data); #endif diff --git a/drivers/net/dsa/netc/netc_switch_hw.h b/drivers/net/dsa/netc/netc_switch_hw.h index f8d436ad9623..1b016e7dd03e 100644 --- a/drivers/net/dsa/netc/netc_switch_hw.h +++ b/drivers/net/dsa/netc/netc_switch_hw.h @@ -87,6 +87,17 @@ #define PSR_TX_BUSY BIT(0) #define PSR_RX_BUSY BIT(1) +#define NETC_PTGSLACR 0x130 + +#define NETC_PRXDCR 0x1c0 +#define NETC_PRXDCRRR 0x1c4 +#define NETC_PRXDCRR0 0x1c8 +#define NETC_PRXDCRR1 0x1cc +#define NETC_PTXDCR 0x1e0 +#define NETC_PTXDCRRR 0x1e4 +#define NETC_PTXDCRR0 0x1e8 +#define NETC_PTXDCRR1 0x1ec + #define NETC_PTCTMSDUR(a) (0x208 + (a) * 0x20) #define PTCTMSDUR_MAXSDU GENMASK(15, 0) #define PTCTMSDUR_SDU_TYPE GENMASK(17, 16) @@ -94,6 +105,9 @@ #define SDU_TYPE_MPDU 1 #define SDU_TYPE_MSDU 2 +#define NETC_PSDFTCR 0x4c4 +#define NETC_PSDFDDCR 0x4c8 + #define NETC_BPCR 0x500 #define BPCR_DYN_LIMIT GENMASK(15, 0) #define BPCR_MLO GENMASK(22, 20) @@ -142,6 +156,11 @@ enum netc_stg_stage { NETC_STG_STATE_FORWARDING, }; +#define NETC_BPDCR 0x580 +#define NETC_BPDCRRR 0x584 +#define NETC_BPDCRR0 0x588 +#define NETC_BPDCRR1 0x58c + /* Definition of Switch ethernet MAC port registers */ #define NETC_PMAC_OFFSET 0x400 #define NETC_PM_CMD_CFG(a) (0x1008 + (a) * 0x400) @@ -176,6 +195,9 @@ enum netc_stg_stage { /* Port MAC 0/1 Receive Ethernet Octets Counter */ #define NETC_PM_REOCT(a) (0x1100 + (a) * 0x400) +/* Port MAC 0/1 Receive Octets Counter */ +#define NETC_PM_ROCT(a) (0x1108 + (a) * 0x400) + /* Port MAC 0/1 Receive Alignment Error Counter Register */ #define NETC_PM_RALN(a) (0x1110 + (a) * 0x400) @@ -188,12 +210,27 @@ enum netc_stg_stage { /* Port MAC 0/1 Receive Frame Check Sequence Error Counter */ #define NETC_PM_RFCS(a) (0x1128 + (a) * 0x400) +/* Port MAC 0/1 Receive VLAN Frame Counter */ +#define NETC_PM_RVLAN(a) (0x1130 + (a) * 0x400) + +/* Port MAC 0/1 Receive Frame Error Counter */ +#define NETC_PM_RERR(a) (0x1138 + (a) * 0x400) + +/* Port MAC 0/1 Receive Unicast Frame Counter */ +#define NETC_PM_RUCA(a) (0x1140 + (a) * 0x400) + /* Port MAC 0/1 Receive Multicast Frame Counter */ #define NETC_PM_RMCA(a) (0x1148 + (a) * 0x400) /* Port MAC 0/1 Receive Broadcast Frame Counter */ #define NETC_PM_RBCA(a) (0x1150 + (a) * 0x400) +/* Port MAC 0/1 Receive Dropped Packets Counter */ +#define NETC_PM_RDRP(a) (0x1158 + (a) * 0x400) + +/* Port MAC 0/1 Receive Packets Counter */ +#define NETC_PM_RPKT(a) (0x1160 + (a) * 0x400) + /* Port MAC 0/1 Receive Undersized Packet Counter */ #define NETC_PM_RUND(a) (0x1168 + (a) * 0x400) @@ -236,6 +273,9 @@ enum netc_stg_stage { /* Port MAC 0/1 Transmit Ethernet Octets Counter */ #define NETC_PM_TEOCT(a) (0x1200 + (a) * 0x400) +/* Port MAC 0/1 Transmit Octets Counter */ +#define NETC_PM_TOCT(a) (0x1208 + (a) * 0x400) + /* Port MAC 0/1 Transmit Excessive Deferral Packet Counter */ #define NETC_PM_TEDFR(a) (0x1210 + (a) * 0x400) @@ -245,15 +285,30 @@ enum netc_stg_stage { /* Port MAC 0/1 Transmit Frame Counter */ #define NETC_PM_TFRM(a) (0x1220 + (a) * 0x400) +/* Port MAC 0/1 Transmit Frame Check Sequence Error Counter */ +#define NETC_PM_TFCS(a) (0x1228 + (a) * 0x400) + +/* Port MAC 0/1 Transmit VLAN Frame Counter */ +#define NETC_PM_TVLAN(a) (0x1230 + (a) * 0x400) + /* Port MAC 0/1 Transmit Frame Error Counter */ #define NETC_PM_TERR(a) (0x1238 + (a) * 0x400) +/* Port MAC 0/1 Transmit Unicast Frame Counter */ +#define NETC_PM_TUCA(a) (0x1240 + (a) * 0x400) + /* Port MAC 0/1 Transmit Multicast Frame Counter */ #define NETC_PM_TMCA(a) (0x1248 + (a) * 0x400) /* Port MAC 0/1 Transmit Broadcast Frame Counter */ #define NETC_PM_TBCA(a) (0x1250 + (a) * 0x400) +/* Port MAC 0/1 Transmit Packets Counter */ +#define NETC_PM_TPKT(a) (0x1260 + (a) * 0x400) + +/* Port MAC 0/1 Transmit Undersized Packet Counter */ +#define NETC_PM_TUND(a) (0x1268 + (a) * 0x400) + /* Port MAC 0/1 Transmit 64-Octet Packet Counter */ #define NETC_PM_T64(a) (0x1270 + (a) * 0x400) @@ -293,6 +348,9 @@ enum netc_stg_stage { /* Port MAC 0/1 Transmit Excessive Collisions Counter */ #define NETC_PM_TECOL(a) (0x12f0 + (a) * 0x400) +/* Port MAC 0/1 Transmit Invalid Octets Counter */ +#define NETC_PM_TIOCT(a) (0x12f8 + (a) * 0x400) + #define NETC_PEMDIOCR 0x1c00 #define NETC_EMDIO_BASE NETC_PEMDIOCR -- 2.34.1