]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: enetc: add unstructured counters for ENETC v4
authorWei Fang <wei.fang@nxp.com>
Wed, 8 Apr 2026 05:58:49 +0000 (13:58 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 20:03:48 +0000 (13:03 -0700)
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>
Link: https://patch.msgid.link/20260408055849.1314033-6-wei.fang@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/freescale/enetc/enetc4_hw.h
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c

index 392992a646fbc4c5634233c5f0810a92b545aa4a..f18437556a0ee24197e7229c3ca81791e1618906 100644 (file)
@@ -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 */
 /* 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)
 
 #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)
 #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)
 #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)
 /* 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)
 
 /* 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)
 
 /* 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)
 
 /* 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)
index bdc5916e4400d3137a3ef9a8b3b8e3bdc8633a13..71f376ef1be1c9f5a9d2e1c7b4d7cae680618ce0 100644 (file)
@@ -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,