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
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev
Subject: [PATCH net-next 5/5] net: enetc: add unstructured counters for ENETC v4
Date: Wed, 8 Apr 2026 13:58:49 +0800 [thread overview]
Message-ID: <20260408055849.1314033-6-wei.fang@nxp.com> (raw)
In-Reply-To: <20260408055849.1314033-1-wei.fang@nxp.com>
Like ENETC v1, ENETC v4 also has many non-standard counters, so these
counters are added to improve statistical coverage.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
.../net/ethernet/freescale/enetc/enetc4_hw.h | 72 +++++++
.../ethernet/freescale/enetc/enetc_ethtool.c | 187 +++++++++++++++---
2 files changed, 234 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 392992a646fb..f18437556a0e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -64,6 +64,9 @@
#define ENETC4_PPAUONTR 0x108
#define ENETC4_PPAUOFFTR 0x10c
+/* Port ingress congestion DRa (a=0,1,2,3) discard count register */
+#define ENETC4_PICDRDCR(a) ((a) * 0x10 + 0x140)
+
/* Port Station interface promiscuous MAC mode register */
#define ENETC4_PSIPMMR 0x200
#define PSIPMMR_SI_MAC_UP(a) BIT(a) /* a = SI index */
@@ -72,6 +75,12 @@
/* Port Station interface promiscuous VLAN mode register */
#define ENETC4_PSIPVMR 0x204
+/* Port broadcast frames dropped due to MAC filtering register */
+#define ENETC4_PBFDSIR 0x208
+
+/* Port frame drop MAC source address pruning register */
+#define ENETC4_PFDMSAPR 0x20c
+
/* Port RSS key register n. n = 0,1,2,...,9 */
#define ENETC4_PRSSKR(n) ((n) * 0x4 + 0x250)
@@ -79,6 +88,12 @@
#define ENETC4_PSIMAFCAPR 0x280
#define PSIMAFCAPR_NUM_MAC_AFTE GENMASK(11, 0)
+/* Port unicast frames dropped due to MAC filtering register */
+#define ENETC4_PUFDMFR 0x284
+
+/* Port multicast frames dropped due to MAC filtering register */
+#define ENETC4_PMFDMFR 0x288
+
/* Port station interface VLAN filtering capability register */
#define ENETC4_PSIVLANFCAPR 0x2c0
#define PSIVLANFCAPR_NUM_VLAN_FTE GENMASK(11, 0)
@@ -87,6 +102,15 @@
#define ENETC4_PSIVLANFMR 0x2c4
#define PSIVLANFMR_VS BIT(0)
+/* Port unicast frames dropped VLAN filtering register */
+#define ENETC4_PUFDVFR 0x2d0
+
+/* Port multicast frames dropped VLAN filtering register */
+#define ENETC4_PMFDVFR 0x2d4
+
+/* Port broadcast frames dropped VLAN filtering register */
+#define ENETC4_PBFDVFR 0x2d8
+
/* Port Station interface a primary MAC address registers */
#define ENETC4_PSIPMAR0(a) ((a) * 0x80 + 0x2000)
#define ENETC4_PSIPMAR1(a) ((a) * 0x80 + 0x2004)
@@ -141,6 +165,18 @@
#define ENETC4_PSR 0x4104
#define PSR_RX_BUSY BIT(1)
+/* Port Rx discard count register */
+#define ENETC4_PRXDCR 0x41c0
+
+/* Port Rx discard count read-reset register */
+#define ENETC4_PRXDCRRR 0x41c4
+
+/* Port Rx discard count reason register 0 */
+#define ENETC4_PRXDCRR0 0x41c8
+
+/* Port Rx discard count reason register 1 */
+#define ENETC4_PRXDCRR1 0x41cc
+
/* Port traffic class a transmit maximum SDU register */
#define ENETC4_PTCTMSDUR(a) ((a) * 0x20 + 0x4208)
#define PTCTMSDUR_MAXSDU GENMASK(15, 0)
@@ -199,6 +235,9 @@
/* Port MAC 0/1 Receive Ethernet Octets Counter */
#define ENETC4_PM_REOCT(mac) (0x5100 + (mac) * 0x400)
+/* Port MAC 0/1 Receive Octets Counter */
+#define ENETC4_PM_ROCT(mac) (0x5108 + (mac) * 0x400)
+
/* Port MAC 0/1 Receive Alignment Error Counter Register */
#define ENETC4_PM_RALN(mac) (0x5110 + (mac) * 0x400)
@@ -211,12 +250,27 @@
/* Port MAC 0/1 Receive Frame Check Sequence Error Counter */
#define ENETC4_PM_RFCS(mac) (0x5128 + (mac) * 0x400)
+/* Port MAC 0/1 Receive VLAN Frame Counter */
+#define ENETC4_PM_RVLAN(mac) (0x5130 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Frame Error Counter */
+#define ENETC4_PM_RERR(mac) (0x5138 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Unicast Frame Counter */
+#define ENETC4_PM_RUCA(mac) (0x5140 + (mac) * 0x400)
+
/* Port MAC 0/1 Receive Multicast Frame Counter */
#define ENETC4_PM_RMCA(mac) (0x5148 + (mac) * 0x400)
/* Port MAC 0/1 Receive Broadcast Frame Counter */
#define ENETC4_PM_RBCA(mac) (0x5150 + (mac) * 0x400)
+/* Port MAC 0/1 Receive Dropped Packets Counter */
+#define ENETC4_PM_RDRP(mac) (0x5158 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Packets Counter */
+#define ENETC4_PM_RPKT(mac) (0x5160 + (mac) * 0x400)
+
/* Port MAC 0/1 Receive Undersized Packet Counter */
#define ENETC4_PM_RUND(mac) (0x5168 + (mac) * 0x400)
@@ -259,21 +313,36 @@
/* Port MAC 0/1 Transmit Ethernet Octets Counter */
#define ENETC4_PM_TEOCT(mac) (0x5200 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Octets Counter */
+#define ENETC4_PM_TOCT(mac) (0x5208 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Valid Pause Frame Counter */
#define ENETC4_PM_TXPF(mac) (0x5218 + (mac) * 0x400)
/* Port MAC 0/1 Transmit Frame Counter */
#define ENETC4_PM_TFRM(mac) (0x5220 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Frame Check Sequence Error Counter */
+#define ENETC4_PM_TFCS(mac) (0x5228 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit VLAN Frame Counter */
+#define ENETC4_PM_TVLAN(mac) (0x5230 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Frame Error Counter */
#define ENETC4_PM_TERR(mac) (0x5238 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Unicast Frame Counter */
+#define ENETC4_PM_TUCA(mac) (0x5240 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Multicast Frame Counter */
#define ENETC4_PM_TMCA(mac) (0x5248 + (mac) * 0x400)
/* Port MAC 0/1 Transmit Broadcast Frame Counter */
#define ENETC4_PM_TBCA(mac) (0x5250 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Packets Counter */
+#define ENETC4_PM_TPKT(mac) (0x5260 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Undersized Packet Counter */
#define ENETC4_PM_TUND(mac) (0x5268 + (mac) * 0x400)
@@ -316,6 +385,9 @@
/* Port MAC 0/1 Transmit Excessive Collisions Counter */
#define ENETC4_PM_TECOL(mac) (0x52f0 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Invalid Octets Counter */
+#define ENETC4_PM_TIOCT(mac) (0x52f8 + (mac) * 0x400)
+
/* Port MAC 0 Interface Mode Control Register */
#define ENETC4_PM_IF_MODE(mac) (0x5300 + (mac) * 0x400)
#define PM_IF_MODE_IFMODE GENMASK(2, 0)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index bdc5916e4400..71f376ef1be1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -177,6 +177,65 @@ static const struct {
{ ENETC_PICDR(3), "ICM DR3 discarded frames" },
};
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc4_emac_counters[] = {
+ { ENETC4_PM_ROCT(0), "eMAC rx octets" },
+ { ENETC4_PM_RVLAN(0), "eMAC rx VLAN frames" },
+ { ENETC4_PM_RERR(0), "eMAC rx frame errors" },
+ { ENETC4_PM_RUCA(0), "eMAC rx unicast frames" },
+ { ENETC4_PM_RDRP(0), "eMAC rx dropped packets" },
+ { ENETC4_PM_RPKT(0), "eMAC rx packets" },
+ { ENETC4_PM_TOCT(0), "eMAC tx octets" },
+ { ENETC4_PM_TVLAN(0), "eMAC tx VLAN frames" },
+ { ENETC4_PM_TFCS(0), "eMAC tx fcs errors" },
+ { ENETC4_PM_TUCA(0), "eMAC tx unicast frames" },
+ { ENETC4_PM_TPKT(0), "eMAC tx packets" },
+ { ENETC4_PM_TUND(0), "eMAC tx undersized packets" },
+ { ENETC4_PM_TIOCT(0), "eMAC tx invalid octets" },
+};
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc4_pmac_counters[] = {
+ { ENETC4_PM_ROCT(1), "pMAC rx octets" },
+ { ENETC4_PM_RVLAN(1), "pMAC rx VLAN frames" },
+ { ENETC4_PM_RERR(1), "pMAC rx frame errors" },
+ { ENETC4_PM_RUCA(1), "pMAC rx unicast frames" },
+ { ENETC4_PM_RDRP(1), "pMAC rx dropped packets" },
+ { ENETC4_PM_RPKT(1), "pMAC rx packets" },
+ { ENETC4_PM_TOCT(1), "pMAC tx octets" },
+ { ENETC4_PM_TVLAN(1), "pMAC tx VLAN frames" },
+ { ENETC4_PM_TFCS(1), "pMAC tx fcs errors" },
+ { ENETC4_PM_TUCA(1), "pMAC tx unicast frames" },
+ { ENETC4_PM_TPKT(1), "pMAC tx packets" },
+ { ENETC4_PM_TUND(1), "pMAC tx undersized packets" },
+ { ENETC4_PM_TIOCT(1), "pMAC tx invalid octets" },
+};
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc4_port_counters[] = {
+ { ENETC4_PICDRDCR(0), "ICM DR0 discarded frames" },
+ { ENETC4_PICDRDCR(1), "ICM DR1 discarded frames" },
+ { ENETC4_PICDRDCR(2), "ICM DR2 discarded frames" },
+ { ENETC4_PICDRDCR(3), "ICM DR3 discarded frames" },
+ { ENETC4_PUFDMFR, "MAC filter discarded unicast" },
+ { ENETC4_PMFDMFR, "MAC filter discarded multicast" },
+ { ENETC4_PBFDSIR, "MAC filter discarded broadcast" },
+ { ENETC4_PFDMSAPR, "MAC SA pruning discarded frames" },
+ { ENETC4_PUFDVFR, "VLAN filter discarded unicast" },
+ { ENETC4_PMFDVFR, "VLAN filter discarded multicast" },
+ { ENETC4_PBFDVFR, "VLAN filter discarded broadcast" },
+ { ENETC4_PRXDCR, "MAC rx discarded frames" },
+ { ENETC4_PRXDCRRR, "MAC rx discard read-reset" },
+ { ENETC4_PRXDCRR0, "MAC rx discard reason 0" },
+ { ENETC4_PRXDCRR1, "MAC rx discard reason 1" },
+};
+
static const char rx_ring_stats[][ETH_GSTRING_LEN] = {
"Rx ring %2d frames",
"Rx ring %2d alloc errors",
@@ -211,15 +270,62 @@ static int enetc_get_sset_count(struct net_device *ndev, int sset)
if (!enetc_si_is_pf(si))
return len;
- len += ARRAY_SIZE(enetc_port_counters);
- len += ARRAY_SIZE(enetc_emac_counters);
+ if (is_enetc_rev1(si)) {
+ len += ARRAY_SIZE(enetc_port_counters);
+ len += ARRAY_SIZE(enetc_emac_counters);
+ if (si->hw_features & ENETC_SI_F_QBU)
+ len += ARRAY_SIZE(enetc_pmac_counters);
+ } else {
+ len += ARRAY_SIZE(enetc4_port_counters);
- if (si->hw_features & ENETC_SI_F_QBU)
- len += ARRAY_SIZE(enetc_pmac_counters);
+ if (enetc_is_pseudo_mac(si))
+ return len;
+
+ len += ARRAY_SIZE(enetc4_emac_counters);
+ if (si->hw_features & ENETC_SI_F_QBU)
+ len += ARRAY_SIZE(enetc4_pmac_counters);
+ }
return len;
}
+static void enetc_get_pf_strings(struct enetc_si *si, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+ ethtool_cpy(&data, enetc_port_counters[i].name);
+
+ for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
+ ethtool_cpy(&data, enetc_emac_counters[i].name);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
+ ethtool_cpy(&data, enetc_pmac_counters[i].name);
+}
+
+static void enetc4_get_pf_strings(struct enetc_si *si, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_port_counters); i++)
+ ethtool_cpy(&data, enetc4_port_counters[i].name);
+
+ if (enetc_is_pseudo_mac(si))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_emac_counters); i++)
+ ethtool_cpy(&data, enetc4_emac_counters[i].name);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_pmac_counters); i++)
+ ethtool_cpy(&data, enetc4_pmac_counters[i].name);
+}
+
static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -240,20 +346,52 @@ static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
if (!enetc_si_is_pf(si))
break;
- for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
- ethtool_cpy(&data, enetc_port_counters[i].name);
+ if (is_enetc_rev1(si))
+ enetc_get_pf_strings(si, data);
+ else
+ enetc4_get_pf_strings(si, data);
- for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
- ethtool_cpy(&data, enetc_emac_counters[i].name);
+ break;
+ }
+}
- if (!(si->hw_features & ENETC_SI_F_QBU))
- break;
+static void enetc_pf_get_ethtool_stats(struct enetc_si *si, int *o, u64 *data)
+{
+ struct enetc_hw *hw = &si->hw;
+ int i;
- for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
- ethtool_cpy(&data, enetc_pmac_counters[i].name);
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+ data[(*o)++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
- break;
- }
+ for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc_emac_counters[i].reg);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc_pmac_counters[i].reg);
+}
+
+static void enetc4_pf_get_ethtool_stats(struct enetc_si *si, int *o, u64 *data)
+{
+ struct enetc_hw *hw = &si->hw;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_port_counters); i++)
+ data[(*o)++] = enetc_port_rd(hw, enetc4_port_counters[i].reg);
+
+ if (enetc_is_pseudo_mac(si))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_emac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc4_emac_counters[i].reg);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_pmac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc4_pmac_counters[i].reg);
}
static void enetc_get_ethtool_stats(struct net_device *ndev,
@@ -288,17 +426,10 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
if (!enetc_si_is_pf(si))
return;
- for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
- data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
-
- for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
- data[o++] = enetc_port_rd64(hw, enetc_emac_counters[i].reg);
-
- if (!(si->hw_features & ENETC_SI_F_QBU))
- return;
-
- for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
- data[o++] = enetc_port_rd64(hw, enetc_pmac_counters[i].reg);
+ if (is_enetc_rev1(si))
+ enetc_pf_get_ethtool_stats(si, &o, data);
+ else
+ enetc4_pf_get_ethtool_stats(si, &o, data);
}
static void enetc_pause_stats(struct enetc_si *si, int mac,
@@ -1438,6 +1569,9 @@ const struct ethtool_ops enetc4_ppm_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
+ .get_sset_count = enetc_get_sset_count,
+ .get_strings = enetc_get_strings,
+ .get_ethtool_stats = enetc_get_ethtool_stats,
.get_eth_mac_stats = enetc_ppm_get_eth_mac_stats,
.get_rx_ring_count = enetc_get_rx_ring_count,
.get_rxfh_key_size = enetc_get_rxfh_key_size,
@@ -1480,6 +1614,9 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
+ .get_sset_count = enetc_get_sset_count,
+ .get_strings = enetc_get_strings,
+ .get_ethtool_stats = enetc_get_ethtool_stats,
.get_pause_stats = enetc_get_pause_stats,
.get_rmon_stats = enetc_get_rmon_stats,
.get_eth_ctrl_stats = enetc_get_eth_ctrl_stats,
--
2.34.1
prev parent reply other threads:[~2026-04-08 6:24 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-08 5:58 [PATCH net-next 0/5] net: enetc: improve statistics for v1 and add statistics for v4 Wei Fang
2026-04-08 5:58 ` [PATCH net-next 1/5] net: enetc: add support for the standardized counters Wei Fang
2026-04-08 5:58 ` [PATCH net-next 2/5] net: enetc: show RX drop counters only for assigned RX rings Wei Fang
2026-04-08 5:58 ` [PATCH net-next 3/5] net: enetc: remove standardized counters from enetc_pm_counters Wei Fang
2026-04-08 5:58 ` [PATCH net-next 4/5] net: enetc: add unstructured pMAC counters for ENETC v1 Wei Fang
2026-04-08 5:58 ` 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=20260408055849.1314033-6-wei.fang@nxp.com \
--to=wei.fang@nxp.com \
--cc=andrew+netdev@lunn.ch \
--cc=claudiu.manoil@nxp.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=imx@lists.linux.dev \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--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