From: Wei Fang <wei.fang@nxp.com>
To: claudiu.manoil@nxp.com, vladimir.oltean@nxp.com,
xiaoning.wang@nxp.com, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, f.fainelli@gmail.com, frank.li@nxp.com,
chleroy@kernel.org, horms@kernel.org, linux@armlinux.org.uk,
maxime.chevallier@bootlin.com, andrew@lunn.ch, olteanv@gmail.com
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev
Subject: [PATCH v8 net-next 15/15] net: dsa: netc: add support for ethtool private statistics
Date: Mon, 18 May 2026 16:25:06 +0800 [thread overview]
Message-ID: <20260518082506.1318236-16-wei.fang@nxp.com> (raw)
In-Reply-To: <20260518082506.1318236-1-wei.fang@nxp.com>
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).
Note that although rtnl_link_stats64 provides some standard statistics
such as rx octets, rx frame errors, rx dropped packets, and tx packets,
these are overall port statistics. The NETC switch supports preemption
on each port, and each port has two MACs (eMAC and pMAC). The driver
private statistics are used to obtain statistics for each MAC, allowing
users to perform analysis and debugging.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/dsa/netc/netc_ethtool.c | 101 ++++++++++++++++++++++++++
drivers/net/dsa/netc/netc_main.c | 3 +
drivers/net/dsa/netc/netc_switch.h | 9 +++
drivers/net/dsa/netc/netc_switch_hw.h | 52 +++++++++++++
4 files changed, 165 insertions(+)
diff --git a/drivers/net/dsa/netc/netc_ethtool.c b/drivers/net/dsa/netc/netc_ethtool.c
index ac8940b5a85c..e6028851a6d0 100644
--- a/drivers/net/dsa/netc/netc_ethtool.c
+++ b/drivers/net/dsa/netc/netc_ethtool.c
@@ -19,6 +19,50 @@ 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_BPDCR, "bridge port discard frames" },
+};
+
+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 +232,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 f3ab0c7646da..fa7dd307ce13 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 ed83201d128b..4fbd12825b67 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 f4e8ef983c21..1d976882a6cc 100644
--- a/drivers/net/dsa/netc/netc_switch_hw.h
+++ b/drivers/net/dsa/netc/netc_switch_hw.h
@@ -98,6 +98,14 @@
#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_PTCTMSDUR(a) (0x208 + (a) * 0x20)
#define PTCTMSDUR_MAXSDU GENMASK(15, 0)
#define PTCTMSDUR_SDU_TYPE GENMASK(17, 16)
@@ -105,6 +113,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)
@@ -153,6 +164,8 @@ enum netc_stg_stage {
NETC_STG_STATE_FORWARDING,
};
+#define NETC_BPDCR 0x580
+
/* Definition of Switch ethernet MAC port registers */
#define NETC_PMAC_OFFSET 0x400
#define NETC_PM_CMD_CFG(a) (0x1008 + (a) * 0x400)
@@ -187,6 +200,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)
@@ -199,12 +215,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)
@@ -247,6 +278,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)
@@ -256,15 +290,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)
@@ -304,6 +353,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
prev parent reply other threads:[~2026-05-18 8:25 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-18 8:24 [PATCH v8 net-next 00/15] Add preliminary NETC switch support for i.MX94 Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 01/15] dt-bindings: net: dsa: update the description of 'dsa,member' property Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 02/15] dt-bindings: net: dsa: add NETC switch Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 03/15] net: enetc: add pre-boot initialization for i.MX94 switch Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 04/15] net: enetc: add basic operations to the FDB table Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 05/15] net: enetc: add support for the "Add" operation to VLAN filter table Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 06/15] net: enetc: add support for the "Update" operation to buffer pool table Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 07/15] net: enetc: add support for "Add" and "Delete" operations to IPFT Wei Fang
2026-05-18 8:24 ` [PATCH v8 net-next 08/15] net: enetc: add multiple command BD rings support Wei Fang
2026-05-18 8:25 ` [PATCH v8 net-next 09/15] net: dsa: add NETC switch tag support Wei Fang
2026-05-18 8:25 ` [PATCH v8 net-next 10/15] net: dsa: netc: introduce NXP NETC switch driver for i.MX94 Wei Fang
2026-05-18 8:25 ` [PATCH v8 net-next 11/15] net: dsa: netc: add phylink MAC operations Wei Fang
2026-05-18 8:25 ` [PATCH v8 net-next 12/15] net: dsa: netc: add FDB, STP, MTU, port setup and host flooding support Wei Fang
2026-05-18 8:25 ` [PATCH v8 net-next 13/15] net: dsa: netc: initialize buffer pool table and implement flow-control Wei Fang
2026-05-18 8:25 ` [PATCH v8 net-next 14/15] net: dsa: netc: add support for the standardized counters Wei Fang
2026-05-18 8:25 ` Wei Fang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260518082506.1318236-16-wei.fang@nxp.com \
--to=wei.fang@nxp.com \
--cc=andrew+netdev@lunn.ch \
--cc=andrew@lunn.ch \
--cc=chleroy@kernel.org \
--cc=claudiu.manoil@nxp.com \
--cc=conor+dt@kernel.org \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=edumazet@google.com \
--cc=f.fainelli@gmail.com \
--cc=frank.li@nxp.com \
--cc=horms@kernel.org \
--cc=imx@lists.linux.dev \
--cc=krzk+dt@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maxime.chevallier@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=robh@kernel.org \
--cc=vladimir.oltean@nxp.com \
--cc=xiaoning.wang@nxp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox