]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
enetc: Add ethtool statistics
authorClaudiu Manoil <claudiu.manoil@nxp.com>
Tue, 22 Jan 2019 13:29:55 +0000 (15:29 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 25 Jan 2019 05:55:53 +0000 (21:55 -0800)
This adds most h/w statistics counters: non-privileged SI conters, as
well as privileged Port and MAC counters available only to the PF.
Per ring software stats are also included.

Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
drivers/net/ethernet/freescale/enetc/enetc_hw.h

index 41771edada9776d05575c03080279397c99128bd..e79d80e37d502970a8e5c56c90c31a48b3411716 100644 (file)
@@ -89,6 +89,187 @@ static void enetc_get_regs(struct net_device *ndev, struct ethtool_regs *regs,
        }
 }
 
+static const struct {
+       int reg;
+       char name[ETH_GSTRING_LEN];
+} enetc_si_counters[] =  {
+       { ENETC_SIROCT, "SI rx octets" },
+       { ENETC_SIRFRM, "SI rx frames" },
+       { ENETC_SIRUCA, "SI rx u-cast frames" },
+       { ENETC_SIRMCA, "SI rx m-cast frames" },
+       { ENETC_SITOCT, "SI tx octets" },
+       { ENETC_SITFRM, "SI tx frames" },
+       { ENETC_SITUCA, "SI tx u-cast frames" },
+       { ENETC_SITMCA, "SI tx m-cast frames" },
+       { ENETC_RBDCR(0), "Rx ring  0 discarded frames" },
+       { ENETC_RBDCR(1), "Rx ring  1 discarded frames" },
+       { ENETC_RBDCR(2), "Rx ring  2 discarded frames" },
+       { ENETC_RBDCR(3), "Rx ring  3 discarded frames" },
+       { ENETC_RBDCR(4), "Rx ring  4 discarded frames" },
+       { ENETC_RBDCR(5), "Rx ring  5 discarded frames" },
+       { ENETC_RBDCR(6), "Rx ring  6 discarded frames" },
+       { ENETC_RBDCR(7), "Rx ring  7 discarded frames" },
+       { ENETC_RBDCR(8), "Rx ring  8 discarded frames" },
+       { ENETC_RBDCR(9), "Rx ring  9 discarded frames" },
+       { ENETC_RBDCR(10), "Rx ring 10 discarded frames" },
+       { ENETC_RBDCR(11), "Rx ring 11 discarded frames" },
+       { ENETC_RBDCR(12), "Rx ring 12 discarded frames" },
+       { ENETC_RBDCR(13), "Rx ring 13 discarded frames" },
+       { ENETC_RBDCR(14), "Rx ring 14 discarded frames" },
+       { ENETC_RBDCR(15), "Rx ring 15 discarded frames" },
+};
+
+static const struct {
+       int reg;
+       char name[ETH_GSTRING_LEN];
+} enetc_port_counters[] = {
+       { ENETC_PM0_REOCT,  "MAC rx ethernet octets" },
+       { ENETC_PM0_RALN,   "MAC rx alignment errors" },
+       { ENETC_PM0_RXPF,   "MAC rx valid pause frames" },
+       { ENETC_PM0_RFRM,   "MAC rx valid frames" },
+       { ENETC_PM0_RFCS,   "MAC rx fcs errors" },
+       { ENETC_PM0_RVLAN,  "MAC rx VLAN frames" },
+       { ENETC_PM0_RERR,   "MAC rx frame errors" },
+       { ENETC_PM0_RUCA,   "MAC rx unicast frames" },
+       { ENETC_PM0_RMCA,   "MAC rx multicast frames" },
+       { ENETC_PM0_RBCA,   "MAC rx broadcast frames" },
+       { ENETC_PM0_RDRP,   "MAC rx dropped packets" },
+       { ENETC_PM0_RPKT,   "MAC rx packets" },
+       { ENETC_PM0_RUND,   "MAC rx undersized packets" },
+       { ENETC_PM0_R64,    "MAC rx 64 byte packets" },
+       { ENETC_PM0_R127,   "MAC rx 65-127 byte packets" },
+       { ENETC_PM0_R255,   "MAC rx 128-255 byte packets" },
+       { ENETC_PM0_R511,   "MAC rx 256-511 byte packets" },
+       { ENETC_PM0_R1023,  "MAC rx 512-1023 byte packets" },
+       { ENETC_PM0_R1518,  "MAC rx 1024-1518 byte packets" },
+       { ENETC_PM0_R1519X, "MAC rx 1519 to max-octet packets" },
+       { ENETC_PM0_ROVR,   "MAC rx oversized packets" },
+       { ENETC_PM0_RJBR,   "MAC rx jabber packets" },
+       { ENETC_PM0_RFRG,   "MAC rx fragment packets" },
+       { ENETC_PM0_RCNP,   "MAC rx control packets" },
+       { ENETC_PM0_RDRNTP, "MAC rx fifo drop" },
+       { ENETC_PM0_TEOCT,  "MAC tx ethernet octets" },
+       { ENETC_PM0_TOCT,   "MAC tx octets" },
+       { ENETC_PM0_TCRSE,  "MAC tx carrier sense errors" },
+       { ENETC_PM0_TXPF,   "MAC tx valid pause frames" },
+       { ENETC_PM0_TFRM,   "MAC tx frames" },
+       { ENETC_PM0_TFCS,   "MAC tx fcs errors" },
+       { ENETC_PM0_TVLAN,  "MAC tx VLAN frames" },
+       { ENETC_PM0_TERR,   "MAC tx frames" },
+       { ENETC_PM0_TUCA,   "MAC tx unicast frames" },
+       { ENETC_PM0_TMCA,   "MAC tx multicast frames" },
+       { ENETC_PM0_TBCA,   "MAC tx broadcast frames" },
+       { ENETC_PM0_TPKT,   "MAC tx packets" },
+       { ENETC_PM0_TUND,   "MAC tx undersized packets" },
+       { ENETC_PM0_T127,   "MAC tx 65-127 byte packets" },
+       { ENETC_PM0_T1023,  "MAC tx 512-1023 byte packets" },
+       { ENETC_PM0_T1518,  "MAC tx 1024-1518 byte packets" },
+       { ENETC_PM0_TCNP,   "MAC tx control packets" },
+       { ENETC_PM0_TDFR,   "MAC tx deferred packets" },
+       { ENETC_PM0_TMCOL,  "MAC tx multiple collisions" },
+       { ENETC_PM0_TSCOL,  "MAC tx single collisions" },
+       { ENETC_PM0_TLCOL,  "MAC tx late collisions" },
+       { ENETC_PM0_TECOL,  "MAC tx excessive collisions" },
+       { ENETC_UFDMF,      "SI MAC nomatch u-cast discards" },
+       { ENETC_MFDMF,      "SI MAC nomatch m-cast discards" },
+       { ENETC_PBFDSIR,    "SI MAC nomatch b-cast discards" },
+       { ENETC_PUFDVFR,    "SI VLAN nomatch u-cast discards" },
+       { ENETC_PMFDVFR,    "SI VLAN nomatch m-cast discards" },
+       { ENETC_PBFDVFR,    "SI VLAN nomatch b-cast discards" },
+       { ENETC_PFDMSAPR,   "SI pruning discarded frames" },
+       { ENETC_PICDR(0),   "ICM DR0 discarded frames" },
+       { ENETC_PICDR(1),   "ICM DR1 discarded frames" },
+       { ENETC_PICDR(2),   "ICM DR2 discarded frames" },
+       { ENETC_PICDR(3),   "ICM DR3 discarded frames" },
+};
+
+static const char rx_ring_stats[][ETH_GSTRING_LEN] = {
+       "Rx ring %2d frames",
+       "Rx ring %2d alloc errors",
+};
+
+static const char tx_ring_stats[][ETH_GSTRING_LEN] = {
+       "Tx ring %2d frames",
+};
+
+static int enetc_get_sset_count(struct net_device *ndev, int sset)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+       if (sset == ETH_SS_STATS)
+               return ARRAY_SIZE(enetc_si_counters) +
+                       ARRAY_SIZE(tx_ring_stats) * priv->num_tx_rings +
+                       ARRAY_SIZE(rx_ring_stats) * priv->num_rx_rings +
+                       (enetc_si_is_pf(priv->si) ?
+                       ARRAY_SIZE(enetc_port_counters) : 0);
+
+       return -EOPNOTSUPP;
+}
+
+static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       u8 *p = data;
+       int i, j;
+
+       switch (stringset) {
+       case ETH_SS_STATS:
+               for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) {
+                       strlcpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN);
+                       p += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < priv->num_tx_rings; i++) {
+                       for (j = 0; j < ARRAY_SIZE(tx_ring_stats); j++) {
+                               snprintf(p, ETH_GSTRING_LEN, tx_ring_stats[j],
+                                        i);
+                               p += ETH_GSTRING_LEN;
+                       }
+               }
+               for (i = 0; i < priv->num_rx_rings; i++) {
+                       for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++) {
+                               snprintf(p, ETH_GSTRING_LEN, rx_ring_stats[j],
+                                        i);
+                               p += ETH_GSTRING_LEN;
+                       }
+               }
+
+               if (!enetc_si_is_pf(priv->si))
+                       break;
+
+               for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) {
+                       strlcpy(p, enetc_port_counters[i].name,
+                               ETH_GSTRING_LEN);
+                       p += ETH_GSTRING_LEN;
+               }
+               break;
+       }
+}
+
+static void enetc_get_ethtool_stats(struct net_device *ndev,
+                                   struct ethtool_stats *stats, u64 *data)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       struct enetc_hw *hw = &priv->si->hw;
+       int i, o = 0;
+
+       for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++)
+               data[o++] = enetc_rd64(hw, enetc_si_counters[i].reg);
+
+       for (i = 0; i < priv->num_tx_rings; i++)
+               data[o++] = priv->tx_ring[i]->stats.packets;
+
+       for (i = 0; i < priv->num_rx_rings; i++) {
+               data[o++] = priv->rx_ring[i]->stats.packets;
+               data[o++] = priv->rx_ring[i]->stats.rx_alloc_errs;
+       }
+
+       if (!enetc_si_is_pf(priv->si))
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+               data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
+}
+
 static void enetc_get_ringparam(struct net_device *ndev,
                                struct ethtool_ringparam *ring)
 {
@@ -115,6 +296,9 @@ static void enetc_get_ringparam(struct net_device *ndev,
 static const struct ethtool_ops enetc_pf_ethtool_ops = {
        .get_regs_len = enetc_get_reglen,
        .get_regs = enetc_get_regs,
+       .get_sset_count = enetc_get_sset_count,
+       .get_strings = enetc_get_strings,
+       .get_ethtool_stats = enetc_get_ethtool_stats,
        .get_ringparam = enetc_get_ringparam,
        .get_link_ksettings = phy_ethtool_get_link_ksettings,
        .set_link_ksettings = phy_ethtool_set_link_ksettings,
@@ -123,6 +307,9 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = {
 static const struct ethtool_ops enetc_vf_ethtool_ops = {
        .get_regs_len = enetc_get_reglen,
        .get_regs = enetc_get_regs,
+       .get_sset_count = enetc_get_sset_count,
+       .get_strings = enetc_get_strings,
+       .get_ethtool_stats = enetc_get_ethtool_stats,
        .get_ringparam = enetc_get_ringparam,
 };
 
index 351af09f7cab432689887ede1b35e8ca88a48f74..68d3b2b5dfb93735187614a308767415a08bea27 100644 (file)
 #define ENETC_SIPMAR0  0x80
 #define ENETC_SIPMAR1  0x84
 
+/* SI statistics */
+#define ENETC_SIROCT   0x300
+#define ENETC_SIRFRM   0x308
+#define ENETC_SIRUCA   0x310
+#define ENETC_SIRMCA   0x318
+#define ENETC_SITOCT   0x320
+#define ENETC_SITFRM   0x328
+#define ENETC_SITUCA   0x330
+#define ENETC_SITMCA   0x338
+#define ENETC_RBDCR(n) (0x8180 + (n) * 0x200)
+
 /* Control BDR regs */
 #define ENETC_SICBDRMR         0x800
 #define ENETC_SICBDRSR         0x804   /* RO */
@@ -171,6 +182,65 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PM0_IFM_RGAUTO   (BIT(15) | ENETC_PMO_IFM_RG | BIT(1))
 #define ENETC_PM0_IFM_XGMII    BIT(12)
 
+/* MAC counters */
+#define ENETC_PM0_REOCT                0x8100
+#define ENETC_PM0_RALN         0x8110
+#define ENETC_PM0_RXPF         0x8118
+#define ENETC_PM0_RFRM         0x8120
+#define ENETC_PM0_RFCS         0x8128
+#define ENETC_PM0_RVLAN                0x8130
+#define ENETC_PM0_RERR         0x8138
+#define ENETC_PM0_RUCA         0x8140
+#define ENETC_PM0_RMCA         0x8148
+#define ENETC_PM0_RBCA         0x8150
+#define ENETC_PM0_RDRP         0x8158
+#define ENETC_PM0_RPKT         0x8160
+#define ENETC_PM0_RUND         0x8168
+#define ENETC_PM0_R64          0x8170
+#define ENETC_PM0_R127         0x8178
+#define ENETC_PM0_R255         0x8180
+#define ENETC_PM0_R511         0x8188
+#define ENETC_PM0_R1023                0x8190
+#define ENETC_PM0_R1518                0x8198
+#define ENETC_PM0_R1519X       0x81A0
+#define ENETC_PM0_ROVR         0x81A8
+#define ENETC_PM0_RJBR         0x81B0
+#define ENETC_PM0_RFRG         0x81B8
+#define ENETC_PM0_RCNP         0x81C0
+#define ENETC_PM0_RDRNTP       0x81C8
+#define ENETC_PM0_TEOCT                0x8200
+#define ENETC_PM0_TOCT         0x8208
+#define ENETC_PM0_TCRSE                0x8210
+#define ENETC_PM0_TXPF         0x8218
+#define ENETC_PM0_TFRM         0x8220
+#define ENETC_PM0_TFCS         0x8228
+#define ENETC_PM0_TVLAN                0x8230
+#define ENETC_PM0_TERR         0x8238
+#define ENETC_PM0_TUCA         0x8240
+#define ENETC_PM0_TMCA         0x8248
+#define ENETC_PM0_TBCA         0x8250
+#define ENETC_PM0_TPKT         0x8260
+#define ENETC_PM0_TUND         0x8268
+#define ENETC_PM0_T127         0x8278
+#define ENETC_PM0_T1023                0x8290
+#define ENETC_PM0_T1518                0x8298
+#define ENETC_PM0_TCNP         0x82C0
+#define ENETC_PM0_TDFR         0x82D0
+#define ENETC_PM0_TMCOL                0x82D8
+#define ENETC_PM0_TSCOL                0x82E0
+#define ENETC_PM0_TLCOL                0x82E8
+#define ENETC_PM0_TECOL                0x82F0
+
+/* Port counters */
+#define ENETC_PICDR(n)         (0x0700 + (n) * 8) /* n = [0..3] */
+#define ENETC_PBFDSIR          0x0810
+#define ENETC_PFDMSAPR         0x0814
+#define ENETC_UFDMF            0x1680
+#define ENETC_MFDMF            0x1684
+#define ENETC_PUFDVFR          0x1780
+#define ENETC_PMFDVFR          0x1784
+#define ENETC_PBFDVFR          0x1788
+
 /** Global regs, offset: 2_0000h */
 #define ENETC_GLOBAL_BASE      0x20000
 #define ENETC_G_EIPBRR0                0x0bf8
@@ -191,9 +261,27 @@ struct enetc_hw {
 /* general register accessors */
 #define enetc_rd_reg(reg)      ioread32((reg))
 #define enetc_wr_reg(reg, val) iowrite32((val), (reg))
+#ifdef ioread64
+#define enetc_rd_reg64(reg)    ioread64((reg))
+#else
+/* using this to read out stats on 32b systems */
+static inline u64 enetc_rd_reg64(void __iomem *reg)
+{
+       u32 low, high, tmp;
+
+       do {
+               high = ioread32(reg + 4);
+               low = ioread32(reg);
+               tmp = ioread32(reg + 4);
+       } while (high != tmp);
+
+       return le64_to_cpu((__le64)high << 32 | low);
+}
+#endif
 
 #define enetc_rd(hw, off)              enetc_rd_reg((hw)->reg + (off))
 #define enetc_wr(hw, off, val)         enetc_wr_reg((hw)->reg + (off), val)
+#define enetc_rd64(hw, off)            enetc_rd_reg64((hw)->reg + (off))
 /* port register accessors - PF only */
 #define enetc_port_rd(hw, off)         enetc_rd_reg((hw)->port + (off))
 #define enetc_port_wr(hw, off, val)    enetc_wr_reg((hw)->port + (off), val)