All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Clément Léger" <clement.leger@bootlin.com>
To: Andrew Lunn <andrew@lunn.ch>,
	Vivien Didelot <vivien.didelot@gmail.com>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Vladimir Oltean <olteanv@gmail.com>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Geert Uytterhoeven <geert+renesas@glider.be>,
	Magnus Damm <magnus.damm@gmail.com>,
	Heiner Kallweit <hkallweit1@gmail.com>,
	Russell King <linux@armlinux.org.uk>
Cc: "Clément Léger" <clement.leger@bootlin.com>,
	"Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
	"Herve Codina" <herve.codina@bootlin.com>,
	"Miquèl Raynal" <miquel.raynal@bootlin.com>,
	"Milan Stevanovic" <milan.stevanovic@se.com>,
	"Jimmy Lalande" <jimmy.lalande@se.com>,
	"Pascal Eberhard" <pascal.eberhard@se.com>,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, netdev@vger.kernel.org
Subject: [net-next v2 07/12] net: dsa: rzn1-a5psw: add statistics support
Date: Fri, 29 Apr 2022 16:35:00 +0200	[thread overview]
Message-ID: <20220429143505.88208-8-clement.leger@bootlin.com> (raw)
In-Reply-To: <20220429143505.88208-1-clement.leger@bootlin.com>

Add statistics support to the rzn1-a5psw driver by implementing the
following dsa_switch_ops callbacks:
- get_sset_count()
- get_strings()
- get_ethtool_stats()
- get_eth_mac_stats()
- get_eth_ctrl_stats()
- get_rmon_stats()

Signed-off-by: Clément Léger <clement.leger@bootlin.com>
---
 drivers/net/dsa/rzn1_a5psw.c | 178 +++++++++++++++++++++++++++++++++++
 drivers/net/dsa/rzn1_a5psw.h |  46 ++++++++-
 2 files changed, 223 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c
index 2cb0a66a041f..4affdbbf7c79 100644
--- a/drivers/net/dsa/rzn1_a5psw.c
+++ b/drivers/net/dsa/rzn1_a5psw.c
@@ -16,6 +16,61 @@
 
 #include "rzn1_a5psw.h"
 
+struct a5psw_stats {
+	u16 offset;
+	const char name[ETH_GSTRING_LEN];
+};
+
+#define STAT_DESC(_offset, _name) {.offset = _offset, .name = _name}
+
+static const struct a5psw_stats a5psw_stats[] = {
+	STAT_DESC(A5PSW_aFramesTransmittedOK, "aFrameTransmittedOK"),
+	STAT_DESC(A5PSW_aFramesReceivedOK, "aFrameReceivedOK"),
+	STAT_DESC(A5PSW_aFrameCheckSequenceErrors, "aFrameCheckSequenceErrors"),
+	STAT_DESC(A5PSW_aAlignmentErrors, "aAlignmentErrors"),
+	STAT_DESC(A5PSW_aOctetsTransmittedOK, "aOctetsTransmittedOK"),
+	STAT_DESC(A5PSW_aOctetsReceivedOK, "aOctetsReceivedOK"),
+	STAT_DESC(A5PSW_aTxPAUSEMACCtrlFrames, "aTxPAUSEMACCtrlFrames"),
+	STAT_DESC(A5PSW_aRxPAUSEMACCtrlFrames, "aRxPAUSEMACCtrlFrames"),
+	STAT_DESC(A5PSW_ifInErrors, "ifInErrors"),
+	STAT_DESC(A5PSW_ifOutErrors, "ifOutErrors"),
+	STAT_DESC(A5PSW_ifInUcastPkts, "ifInUcastPkts"),
+	STAT_DESC(A5PSW_ifInMulticastPkts, "ifInMulticastPkts"),
+	STAT_DESC(A5PSW_ifInBroadcastPkts, "ifInBroadcastPkts"),
+	STAT_DESC(A5PSW_ifOutDiscards, "ifOutDiscards"),
+	STAT_DESC(A5PSW_ifOutUcastPkts, "ifOutUcastPkts"),
+	STAT_DESC(A5PSW_ifOutMulticastPkts, "ifOutMulticastPkts"),
+	STAT_DESC(A5PSW_ifOutBroadcastPkts, "ifOutBroadcastPkts"),
+	STAT_DESC(A5PSW_etherStatsDropEvents, "etherStatsDropEvents"),
+	STAT_DESC(A5PSW_etherStatsOctets, "etherStatsOctets"),
+	STAT_DESC(A5PSW_etherStatsPkts, "etherStatsPkts"),
+	STAT_DESC(A5PSW_etherStatsUndersizePkts, "etherStatsUndersizePkts"),
+	STAT_DESC(A5PSW_etherStatsOversizePkts, "etherStatsOversizePkts"),
+	STAT_DESC(A5PSW_etherStatsPkts64Octets, "etherStatsPkts64Octets"),
+	STAT_DESC(A5PSW_etherStatsPkts65to127Octets,
+		  "etherStatsPkts65to127Octets"),
+	STAT_DESC(A5PSW_etherStatsPkts128to255Octets,
+		  "etherStatsPkts128to255Octets"),
+	STAT_DESC(A5PSW_etherStatsPkts256to511Octets,
+		  "etherStatsPkts256to511Octets"),
+	STAT_DESC(A5PSW_etherStatsPkts512to1023Octets,
+		  "etherStatsPkts512to1023Octets"),
+	STAT_DESC(A5PSW_etherStatsPkts1024to1518Octets,
+		  "etherStatsPkts1024to1518Octets"),
+	STAT_DESC(A5PSW_etherStatsPkts1519toXOctets,
+		  "etherStatsPkts1519toXOctets"),
+	STAT_DESC(A5PSW_etherStatsJabbers, "etherStatsJabbers"),
+	STAT_DESC(A5PSW_etherStatsFragments, "etherStatsFragments"),
+	STAT_DESC(A5PSW_VLANReceived, "VLANReceived"),
+	STAT_DESC(A5PSW_VLANTransmitted, "VLANTransmitted"),
+	STAT_DESC(A5PSW_aDeferred, "aDeferred"),
+	STAT_DESC(A5PSW_aMultipleCollisions, "aMultipleCollisions"),
+	STAT_DESC(A5PSW_aSingleCollisions, "aSingleCollisions"),
+	STAT_DESC(A5PSW_aLateCollisions, "aLateCollisions"),
+	STAT_DESC(A5PSW_aExcessiveCollisions, "aExcessiveCollisions"),
+	STAT_DESC(A5PSW_aCarrierSenseErrors, "aCarrierSenseErrors"),
+};
+
 static void a5psw_reg_writel(struct a5psw *a5psw, int offset, u32 value)
 {
 	writel(value, a5psw->base + offset);
@@ -322,6 +377,123 @@ static void a5psw_port_fast_age(struct dsa_switch *ds, int port)
 	a5psw_port_fdb_flush(a5psw, port);
 }
 
+static u64 a5psw_read_stat(struct a5psw *a5psw, u32 offset, int port)
+{
+	u32 reg_lo, reg_hi;
+
+	reg_lo = a5psw_reg_readl(a5psw, offset + A5PSW_PORT_OFFSET(port));
+	/* A5PSW_STATS_HIWORD is latched on stat read */
+	reg_hi = a5psw_reg_readl(a5psw, A5PSW_STATS_HIWORD);
+
+	return ((u64)reg_hi << 32) | reg_lo;
+}
+
+static void a5psw_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+			      uint8_t *data)
+{
+	unsigned int u;
+
+	if (stringset != ETH_SS_STATS)
+		return;
+
+	for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++) {
+		memcpy(data + u * ETH_GSTRING_LEN, a5psw_stats[u].name,
+		       ETH_GSTRING_LEN);
+	}
+}
+
+static void a5psw_get_ethtool_stats(struct dsa_switch *ds, int port,
+				    uint64_t *data)
+{
+	struct a5psw *a5psw = ds->priv;
+	unsigned int u;
+
+	for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++)
+		data[u] = a5psw_read_stat(a5psw, a5psw_stats[u].offset, port);
+}
+
+static int a5psw_get_sset_count(struct dsa_switch *ds, int port, int sset)
+{
+	if (sset != ETH_SS_STATS)
+		return 0;
+
+	return ARRAY_SIZE(a5psw_stats);
+}
+
+static void a5psw_get_eth_mac_stats(struct dsa_switch *ds, int port,
+				    struct ethtool_eth_mac_stats *mac_stats)
+{
+	struct a5psw *a5psw = ds->priv;
+
+#define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
+	mac_stats->FramesTransmittedOK = RD(aFramesTransmittedOK);
+	mac_stats->SingleCollisionFrames = RD(aSingleCollisions);
+	mac_stats->MultipleCollisionFrames = RD(aMultipleCollisions);
+	mac_stats->FramesReceivedOK = RD(aFramesReceivedOK);
+	mac_stats->FrameCheckSequenceErrors = RD(aFrameCheckSequenceErrors);
+	mac_stats->AlignmentErrors = RD(aAlignmentErrors);
+	mac_stats->OctetsTransmittedOK = RD(aOctetsTransmittedOK);
+	mac_stats->FramesWithDeferredXmissions = RD(aDeferred);
+	mac_stats->LateCollisions = RD(aLateCollisions);
+	mac_stats->FramesAbortedDueToXSColls = RD(aExcessiveCollisions);
+	mac_stats->FramesLostDueToIntMACXmitError = RD(ifOutErrors);
+	mac_stats->CarrierSenseErrors = RD(aCarrierSenseErrors);
+	mac_stats->OctetsReceivedOK = RD(aOctetsReceivedOK);
+	mac_stats->FramesLostDueToIntMACRcvError = RD(ifInErrors);
+	mac_stats->MulticastFramesXmittedOK = RD(ifOutMulticastPkts);
+	mac_stats->BroadcastFramesXmittedOK = RD(ifOutBroadcastPkts);
+	mac_stats->FramesWithExcessiveDeferral = RD(aDeferred);
+	mac_stats->MulticastFramesReceivedOK = RD(ifInMulticastPkts);
+	mac_stats->BroadcastFramesReceivedOK = RD(ifInBroadcastPkts);
+#undef RD
+}
+
+static const struct ethtool_rmon_hist_range a5psw_rmon_ranges[] = {
+	{ 0, 64 },
+	{ 65, 127 },
+	{ 128, 255 },
+	{ 256, 511 },
+	{ 512, 1023 },
+	{ 1024, 1518 },
+	{ 1519, A5PSW_MAX_MTU },
+	{}
+};
+
+static void a5psw_get_rmon_stats(struct dsa_switch *ds, int port,
+				 struct ethtool_rmon_stats *rmon_stats,
+				 const struct ethtool_rmon_hist_range **ranges)
+{
+	struct a5psw *a5psw = ds->priv;
+
+#define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
+	rmon_stats->undersize_pkts = RD(etherStatsUndersizePkts);
+	rmon_stats->oversize_pkts = RD(etherStatsOversizePkts);
+	rmon_stats->fragments = RD(etherStatsFragments);
+	rmon_stats->jabbers = RD(etherStatsJabbers);
+	rmon_stats->hist[0] = RD(etherStatsPkts64Octets);
+	rmon_stats->hist[1] = RD(etherStatsPkts65to127Octets);
+	rmon_stats->hist[2] = RD(etherStatsPkts128to255Octets);
+	rmon_stats->hist[3] = RD(etherStatsPkts256to511Octets);
+	rmon_stats->hist[4] = RD(etherStatsPkts512to1023Octets);
+	rmon_stats->hist[5] = RD(etherStatsPkts1024to1518Octets);
+	rmon_stats->hist[6] = RD(etherStatsPkts1519toXOctets);
+#undef RD
+
+	*ranges = a5psw_rmon_ranges;
+}
+
+static void a5psw_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
+				     struct ethtool_eth_ctrl_stats *ctrl_stats)
+{
+	struct a5psw *a5psw = ds->priv;
+	u64 stat;
+
+	stat = a5psw_read_stat(a5psw, A5PSW_aTxPAUSEMACCtrlFrames, port);
+	ctrl_stats->MACControlFramesTransmitted = stat;
+	stat = a5psw_read_stat(a5psw, A5PSW_aRxPAUSEMACCtrlFrames, port);
+	ctrl_stats->MACControlFramesReceived = stat;
+}
+
 static int a5psw_setup(struct dsa_switch *ds)
 {
 	struct a5psw *a5psw = ds->priv;
@@ -410,6 +582,12 @@ const struct dsa_switch_ops a5psw_switch_ops = {
 	.phylink_mac_link_up = a5psw_phylink_mac_link_up,
 	.port_change_mtu = a5psw_port_change_mtu,
 	.port_max_mtu = a5psw_port_max_mtu,
+	.get_sset_count = a5psw_get_sset_count,
+	.get_strings = a5psw_get_strings,
+	.get_ethtool_stats = a5psw_get_ethtool_stats,
+	.get_eth_mac_stats = a5psw_get_eth_mac_stats,
+	.get_eth_ctrl_stats = a5psw_get_eth_ctrl_stats,
+	.get_rmon_stats = a5psw_get_rmon_stats,
 	.set_ageing_time = a5psw_set_ageing_time,
 	.port_bridge_join = a5psw_port_bridge_join,
 	.port_bridge_leave = a5psw_port_bridge_leave,
diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h
index 25446d4eb13a..7be8c6da240b 100644
--- a/drivers/net/dsa/rzn1_a5psw.h
+++ b/drivers/net/dsa/rzn1_a5psw.h
@@ -146,7 +146,50 @@
 
 #define A5PSW_STATS_HIWORD		0x900
 
-#define A5PSW_DUMMY_WORKAROUND		0x5000
+/* Stats */
+#define A5PSW_aFramesTransmittedOK		0x868
+#define A5PSW_aFramesReceivedOK			0x86C
+#define A5PSW_aFrameCheckSequenceErrors		0x870
+#define A5PSW_aAlignmentErrors			0x874
+#define A5PSW_aOctetsTransmittedOK		0x878
+#define A5PSW_aOctetsReceivedOK			0x87C
+#define A5PSW_aTxPAUSEMACCtrlFrames		0x880
+#define A5PSW_aRxPAUSEMACCtrlFrames		0x884
+	/* If */
+#define A5PSW_ifInErrors			0x888
+#define A5PSW_ifOutErrors			0x88C
+#define A5PSW_ifInUcastPkts			0x890
+#define A5PSW_ifInMulticastPkts			0x894
+#define A5PSW_ifInBroadcastPkts			0x898
+#define A5PSW_ifOutDiscards			0x89C
+#define A5PSW_ifOutUcastPkts			0x8A0
+#define A5PSW_ifOutMulticastPkts		0x8A4
+#define A5PSW_ifOutBroadcastPkts		0x8A8
+	/* Ether */
+#define A5PSW_etherStatsDropEvents		0x8AC
+#define A5PSW_etherStatsOctets			0x8B0
+#define A5PSW_etherStatsPkts			0x8B4
+#define A5PSW_etherStatsUndersizePkts		0x8B8
+#define A5PSW_etherStatsOversizePkts		0x8BC
+#define A5PSW_etherStatsPkts64Octets		0x8C0
+#define A5PSW_etherStatsPkts65to127Octets	0x8C4
+#define A5PSW_etherStatsPkts128to255Octets	0x8C8
+#define A5PSW_etherStatsPkts256to511Octets	0x8CC
+#define A5PSW_etherStatsPkts512to1023Octets	0x8D0
+#define A5PSW_etherStatsPkts1024to1518Octets	0x8D4
+#define A5PSW_etherStatsPkts1519toXOctets	0x8D8
+#define A5PSW_etherStatsJabbers			0x8DC
+#define A5PSW_etherStatsFragments		0x8E0
+
+#define A5PSW_VLANReceived			0x8E8
+#define A5PSW_VLANTransmitted			0x8EC
+
+#define A5PSW_aDeferred				0x910
+#define A5PSW_aMultipleCollisions		0x914
+#define A5PSW_aSingleCollisions			0x918
+#define A5PSW_aLateCollisions			0x91C
+#define A5PSW_aExcessiveCollisions		0x920
+#define A5PSW_aCarrierSenseErrors		0x924
 
 #define A5PSW_VLAN_TAG(prio, id)	(((prio) << 12) | (id))
 #define A5PSW_PORTS_NUM			5
@@ -179,6 +222,7 @@
  * @mdio_freq: MDIO bus frequency requested
  * @pcs: Array of PCS connected to the switch ports (not for the CPU)
  * @ds: DSA switch struct
+ * @stats_lock: lock to access statistics (shared HI counter)
  * @lk_lock: Lock for the lookup table
  * @reg_lock: Lock for register read-modify-write operation
  * @bridged_ports: List of ports that are bridged and should be flooded
-- 
2.34.1


  parent reply	other threads:[~2022-04-29 14:38 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-29 14:34 [net-next v2 00/12] add support for Renesas RZ/N1 ethernet subsystem devices Clément Léger
2022-04-29 14:34 ` [net-next v2 01/12] net: dsa: add support for ethtool get_rmon_stats() Clément Léger
2022-04-29 16:15   ` Florian Fainelli
2022-04-29 14:34 ` [net-next v2 02/12] net: dsa: add Renesas RZ/N1 switch tag driver Clément Léger
2022-04-29 16:22   ` Florian Fainelli
2022-05-02 13:43     ` Clément Léger
2022-04-29 14:34 ` [net-next v2 03/12] dt-bindings: net: pcs: add bindings for Renesas RZ/N1 MII converter Clément Léger
2022-04-29 14:34 ` [net-next v2 04/12] net: pcs: add Renesas MII converter driver Clément Léger
2022-04-29 14:43   ` Clément Léger
2022-05-03 15:53   ` Geert Uytterhoeven
2022-04-29 14:34 ` [net-next v2 05/12] dt-bindings: net: dsa: add bindings for Renesas RZ/N1 Advanced 5 port switch Clément Léger
2022-04-29 14:34 ` [net-next v2 06/12] net: dsa: rzn1-a5psw: add Renesas RZ/N1 advanced 5 port switch driver Clément Léger
2022-04-29 14:35 ` Clément Léger [this message]
2022-04-29 14:35 ` [net-next v2 08/12] net: dsa: rzn1-a5psw: add FDB support Clément Léger
2022-04-29 14:35 ` [net-next v2 09/12] ARM: dts: r9a06g032: describe MII converter Clément Léger
2022-04-29 14:35 ` [net-next v2 10/12] ARM: dts: r9a06g032: describe GMAC2 Clément Léger
2022-04-29 14:35 ` [net-next v2 11/12] ARM: dts: r9a06g032: describe switch Clément Léger
2022-04-29 14:35 ` [net-next v2 12/12] MAINTAINERS: add Renesas RZ/N1 switch related driver entry Clément Léger
2022-04-29 19:32 ` [net-next v2 00/12] add support for Renesas RZ/N1 ethernet subsystem devices Jakub Kicinski
2022-05-02  6:51   ` Clément Léger
2022-05-02 12:27     ` Geert Uytterhoeven
2022-05-02 15:08       ` Clément Léger
2022-05-02 15:31         ` Geert Uytterhoeven

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=20220429143505.88208-8-clement.leger@bootlin.com \
    --to=clement.leger@bootlin.com \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=devicetree@vger.kernel.org \
    --cc=edumazet@google.com \
    --cc=f.fainelli@gmail.com \
    --cc=geert+renesas@glider.be \
    --cc=herve.codina@bootlin.com \
    --cc=hkallweit1@gmail.com \
    --cc=jimmy.lalande@se.com \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=magnus.damm@gmail.com \
    --cc=milan.stevanovic@se.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=pascal.eberhard@se.com \
    --cc=robh+dt@kernel.org \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=vivien.didelot@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.