bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch net-next v12 10/13] net: dsa: microchip: add support for ethtool port counters
@ 2022-05-02 16:09 Arun Ramadoss
  0 siblings, 0 replies; only message in thread
From: Arun Ramadoss @ 2022-05-02 16:09 UTC (permalink / raw)
  To: bpf, linux-kernel, devicetree, netdev
  Cc: KP Singh, John Fastabend, Yonghong Song, Song Liu,
	Martin KaFai Lau, Andrii Nakryiko, Daniel Borkmann,
	Alexei Starovoitov, Russell King, Krzysztof Kozlowski,
	Rob Herring, Paolo Abeni, Jakub Kicinski, Eric Dumazet,
	David S. Miller, Vladimir Oltean, Florian Fainelli,
	Vivien Didelot, Andrew Lunn, UNGLinuxDriver, Woojung Huh

From: Prasanna Vengateshan <prasanna.vengateshan@microchip.com>

Added support for get_eth_**_stats() (phy/mac/ctrl) and
get_stats64()

Reused the KSZ common APIs for get_ethtool_stats() & get_sset_count()
along with relevant lan937x hooks for KSZ common layer and added
support for get_strings()

Signed-off-by: Prasanna Vengateshan <prasanna.vengateshan@microchip.com>
Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/microchip/lan937x_dev.c  | 107 +++++++++++++++++++++-
 drivers/net/dsa/microchip/lan937x_dev.h  |  47 ++++++++++
 drivers/net/dsa/microchip/lan937x_main.c | 109 +++++++++++++++++++++++
 3 files changed, 262 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/microchip/lan937x_dev.c b/drivers/net/dsa/microchip/lan937x_dev.c
index 4612642e8f5e..b154bc52f64a 100644
--- a/drivers/net/dsa/microchip/lan937x_dev.c
+++ b/drivers/net/dsa/microchip/lan937x_dev.c
@@ -16,6 +16,45 @@
 #include "ksz_common.h"
 #include "lan937x_dev.h"
 
+const struct mib_names lan937x_mib_names[] = {
+	{ 0x00, "rx_hi" },
+	{ 0x01, "rx_undersize" },
+	{ 0x02, "rx_fragments" },
+	{ 0x03, "rx_oversize" },
+	{ 0x04, "rx_jabbers" },
+	{ 0x05, "rx_symbol_err" },
+	{ 0x06, "rx_crc_err" },
+	{ 0x07, "rx_align_err" },
+	{ 0x08, "rx_mac_ctrl" },
+	{ 0x09, "rx_pause" },
+	{ 0x0A, "rx_bcast" },
+	{ 0x0B, "rx_mcast" },
+	{ 0x0C, "rx_ucast" },
+	{ 0x0D, "rx_64_or_less" },
+	{ 0x0E, "rx_65_127" },
+	{ 0x0F, "rx_128_255" },
+	{ 0x10, "rx_256_511" },
+	{ 0x11, "rx_512_1023" },
+	{ 0x12, "rx_1024_1522" },
+	{ 0x13, "rx_1523_2000" },
+	{ 0x14, "rx_2001" },
+	{ 0x15, "tx_hi" },
+	{ 0x16, "tx_late_col" },
+	{ 0x17, "tx_pause" },
+	{ 0x18, "tx_bcast" },
+	{ 0x19, "tx_mcast" },
+	{ 0x1A, "tx_ucast" },
+	{ 0x1B, "tx_deferred" },
+	{ 0x1C, "tx_total_col" },
+	{ 0x1D, "tx_exc_col" },
+	{ 0x1E, "tx_single_col" },
+	{ 0x1F, "tx_mult_col" },
+	{ 0x80, "rx_total" },
+	{ 0x81, "tx_total" },
+	{ 0x82, "rx_discards" },
+	{ 0x83, "tx_discards" },
+};
+
 int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
 {
 	return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
@@ -93,6 +132,53 @@ static void lan937x_flush_dyn_mac_table(struct ksz_device *dev, int port)
 	}
 }
 
+static void lan937x_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
+			      u64 *cnt)
+{
+	unsigned int val;
+	u32 data;
+	int ret;
+
+	/* Enable MIB Counter read */
+	data = MIB_COUNTER_READ;
+	data |= (addr << MIB_COUNTER_INDEX_S);
+	lan937x_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT, data);
+
+	ret = regmap_read_poll_timeout(dev->regmap[2],
+				       PORT_CTRL_ADDR(port,
+						      REG_PORT_MIB_CTRL_STAT),
+				       val, !(val & MIB_COUNTER_READ),
+				       10, 1000);
+	if (ret) {
+		dev_err(dev->dev, "Failed to get MIB\n");
+		return;
+	}
+
+	/* count resets upon read */
+	lan937x_pread32(dev, port, REG_PORT_MIB_DATA, &data);
+	*cnt += data;
+}
+
+void lan937x_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+		       u64 *dropped, u64 *cnt)
+{
+	addr = lan937x_mib_names[addr].index;
+	lan937x_r_mib_cnt(dev, port, addr, cnt);
+}
+
+static void lan937x_port_init_cnt(struct ksz_device *dev, int port)
+{
+	struct ksz_port_mib *mib = &dev->ports[port].mib;
+
+	/* flush all enabled port MIB counters */
+	mutex_lock(&mib->cnt_mutex);
+	lan937x_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT,
+			 MIB_COUNTER_FLUSH_FREEZE);
+	ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
+	lan937x_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT, 0);
+	mutex_unlock(&mib->cnt_mutex);
+}
+
 int lan937x_reset_switch(struct ksz_device *dev)
 {
 	u32 data32;
@@ -573,7 +659,7 @@ static int lan937x_mdio_register(struct ksz_device *dev)
 
 static int lan937x_switch_init(struct ksz_device *dev)
 {
-	int ret;
+	int i, ret;
 
 	dev->ds->ops = &lan937x_switch_ops;
 
@@ -584,12 +670,27 @@ static int lan937x_switch_init(struct ksz_device *dev)
 
 	dev->port_mask = (1 << dev->port_cnt) - 1;
 
+	dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
+	dev->mib_cnt = ARRAY_SIZE(lan937x_mib_names);
+
 	dev->ports = devm_kzalloc(dev->dev,
 				  dev->port_cnt * sizeof(struct ksz_port),
 				  GFP_KERNEL);
 	if (!dev->ports)
 		return -ENOMEM;
 
+	for (i = 0; i < dev->port_cnt; i++) {
+		spin_lock_init(&dev->ports[i].mib.stats64_lock);
+		mutex_init(&dev->ports[i].mib.cnt_mutex);
+		dev->ports[i].mib.counters =
+			devm_kzalloc(dev->dev,
+				     sizeof(u64) * (dev->mib_cnt + 1),
+				     GFP_KERNEL);
+
+		if (!dev->ports[i].mib.counters)
+			return -ENOMEM;
+	}
+
 	/* set the real number of ports */
 	dev->ds->num_ports = dev->port_cnt;
 	return 0;
@@ -626,6 +727,10 @@ const struct ksz_dev_ops lan937x_dev_ops = {
 	.cfg_port_member = lan937x_cfg_port_member,
 	.flush_dyn_mac_table = lan937x_flush_dyn_mac_table,
 	.port_setup = lan937x_port_setup,
+	.r_mib_cnt = lan937x_r_mib_cnt,
+	.r_mib_pkt = lan937x_r_mib_pkt,
+	.port_init_cnt = lan937x_port_init_cnt,
+	.r_mib_stat64 = ksz_r_mib_stats64,
 	.shutdown = lan937x_reset_switch,
 	.detect = lan937x_switch_detect,
 	.init = lan937x_init,
diff --git a/drivers/net/dsa/microchip/lan937x_dev.h b/drivers/net/dsa/microchip/lan937x_dev.h
index 0141d417c446..147800550162 100644
--- a/drivers/net/dsa/microchip/lan937x_dev.h
+++ b/drivers/net/dsa/microchip/lan937x_dev.h
@@ -38,8 +38,55 @@ void lan937x_config_interface(struct ksz_device *dev, int port,
 			      bool tx_pause, bool rx_pause);
 void lan937x_mac_config(struct ksz_device *dev, int port,
 			phy_interface_t interface);
+void lan937x_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+		       u64 *dropped, u64 *cnt);
+
+struct mib_names {
+	int index;
+	char string[ETH_GSTRING_LEN];
+};
+
+enum lan937x_mib_list {
+	lan937x_mib_rx_hi_pri_byte = 0,
+	lan937x_mib_rx_undersize,
+	lan937x_mib_rx_fragments,
+	lan937x_mib_rx_oversize,
+	lan937x_mib_rx_jabbers,
+	lan937x_mib_rx_sym_err,
+	lan937x_mib_rx_crc_err,
+	lan937x_mib_rx_align_err,
+	lan937x_mib_rx_mac_ctrl,
+	lan937x_mib_rx_pause,
+	lan937x_mib_rx_bcast,
+	lan937x_mib_rx_mcast,
+	lan937x_mib_rx_ucast,
+	lan937x_mib_rx_64_or_less,
+	lan937x_mib_rx_65_127,
+	lan937x_mib_rx_128_255,
+	lan937x_mib_rx_256_511,
+	lan937x_mib_rx_512_1023,
+	lan937x_mib_rx_1024_1522,
+	lan937x_mib_rx_1523_2000,
+	lan937x_mib_rx_2001,
+	lan937x_mib_tx_hi_pri_byte,
+	lan937x_mib_tx_late_col,
+	lan937x_mib_tx_pause,
+	lan937x_mib_tx_bcast,
+	lan937x_mib_tx_mcast,
+	lan937x_mib_tx_ucast,
+	lan937x_mib_tx_deferred,
+	lan937x_mib_tx_total_col,
+	lan937x_mib_tx_exc_col,
+	lan937x_mib_tx_single_col,
+	lan937x_mib_tx_mult_col,
+	lan937x_mib_rx_total,
+	lan937x_mib_tx_total,
+	lan937x_mib_rx_discard,
+	lan937x_mib_tx_discard,
+};
 
 extern const struct dsa_switch_ops lan937x_switch_ops;
 extern const struct ksz_dev_ops lan937x_dev_ops;
+extern const struct mib_names lan937x_mib_names[];
 
 #endif
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 38d5311bf21f..6d0b0d62b8e1 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -45,6 +45,20 @@ static int lan937x_phy_write16(struct dsa_switch *ds, int addr, int reg,
 	return lan937x_internal_phy_write(dev, addr, reg, val);
 }
 
+static void lan937x_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+				u8 *buf)
+{
+	struct ksz_device *dev = ds->priv;
+	int i;
+
+	if (stringset != ETH_SS_STATS)
+		return;
+
+	for (i = 0; i < dev->mib_cnt; i++)
+		memcpy(buf + i * ETH_GSTRING_LEN, lan937x_mib_names[i].string,
+		       ETH_GSTRING_LEN);
+}
+
 static void lan937x_port_stp_state_set(struct dsa_switch *ds, int port,
 				       u8 state)
 {
@@ -215,6 +229,8 @@ static int lan937x_setup(struct dsa_switch *ds)
 	/* start switch */
 	lan937x_cfg(dev, REG_SW_OPERATION, SW_START, true);
 
+	ksz_init_mib_timer(dev);
+
 	return 0;
 }
 
@@ -320,12 +336,105 @@ static void lan937x_phylink_get_caps(struct dsa_switch *ds, int port,
 	}
 }
 
+static void lan937x_get_eth_phy_stats(struct dsa_switch *ds, int port,
+				      struct ethtool_eth_phy_stats *phy_stats)
+{
+	struct ksz_device *dev = ds->priv;
+	struct ksz_port_mib *mib = &dev->ports[port].mib;
+	u64 *cnt;
+
+	mutex_lock(&mib->cnt_mutex);
+
+	cnt = &mib->counters[lan937x_mib_rx_sym_err];
+	lan937x_r_mib_pkt(dev, port, lan937x_mib_rx_sym_err, NULL, cnt);
+
+	phy_stats->SymbolErrorDuringCarrier = *cnt;
+
+	mutex_unlock(&mib->cnt_mutex);
+}
+
+static void lan937x_get_eth_mac_stats(struct dsa_switch *ds, int port,
+				      struct ethtool_eth_mac_stats *mac_stats)
+{
+	struct ksz_device *dev = ds->priv;
+	struct ksz_port_mib *mib = &dev->ports[port].mib;
+	u64 *ctr = mib->counters;
+
+	mutex_lock(&mib->cnt_mutex);
+
+	while (mib->cnt_ptr < dev->mib_cnt) {
+		lan937x_r_mib_pkt(dev, port, mib->cnt_ptr,
+				  NULL, &mib->counters[mib->cnt_ptr]);
+		++mib->cnt_ptr;
+	}
+
+	mac_stats->FramesTransmittedOK = ctr[lan937x_mib_tx_mcast] +
+					 ctr[lan937x_mib_tx_bcast] +
+					 ctr[lan937x_mib_tx_ucast] +
+					 ctr[lan937x_mib_tx_pause];
+
+	mac_stats->SingleCollisionFrames = ctr[lan937x_mib_tx_single_col];
+	mac_stats->MultipleCollisionFrames = ctr[lan937x_mib_tx_mult_col];
+
+	mac_stats->FramesReceivedOK = ctr[lan937x_mib_rx_mcast] +
+				      ctr[lan937x_mib_rx_bcast] +
+				      ctr[lan937x_mib_rx_ucast] +
+				      ctr[lan937x_mib_rx_pause];
+
+	mac_stats->FrameCheckSequenceErrors = ctr[lan937x_mib_rx_crc_err];
+	mac_stats->AlignmentErrors = ctr[lan937x_mib_rx_align_err];
+	mac_stats->OctetsTransmittedOK = ctr[lan937x_mib_tx_total];
+	mac_stats->FramesWithDeferredXmissions = ctr[lan937x_mib_tx_deferred];
+	mac_stats->LateCollisions = ctr[lan937x_mib_tx_late_col];
+	mac_stats->FramesAbortedDueToXSColls = ctr[lan937x_mib_tx_exc_col];
+	mac_stats->FramesLostDueToIntMACXmitError = ctr[lan937x_mib_tx_discard];
+
+	mac_stats->OctetsReceivedOK = ctr[lan937x_mib_rx_total];
+	mac_stats->FramesLostDueToIntMACRcvError = ctr[lan937x_mib_rx_discard];
+	mac_stats->MulticastFramesXmittedOK = ctr[lan937x_mib_tx_mcast];
+	mac_stats->BroadcastFramesXmittedOK = ctr[lan937x_mib_tx_bcast];
+
+	mac_stats->MulticastFramesReceivedOK = ctr[lan937x_mib_rx_mcast];
+	mac_stats->BroadcastFramesReceivedOK = ctr[lan937x_mib_rx_bcast];
+	mac_stats->InRangeLengthErrors = ctr[lan937x_mib_rx_fragments];
+
+	mib->cnt_ptr = 0;
+	mutex_unlock(&mib->cnt_mutex);
+}
+
+static void lan937x_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
+				       struct ethtool_eth_ctrl_stats *ctrl_sts)
+{
+	struct ksz_device *dev = ds->priv;
+	struct ksz_port_mib *mib = &dev->ports[port].mib;
+	u64 *cnt;
+
+	mutex_lock(&mib->cnt_mutex);
+
+	cnt = &mib->counters[lan937x_mib_rx_pause];
+	lan937x_r_mib_pkt(dev, port, lan937x_mib_rx_pause, NULL, cnt);
+	ctrl_sts->MACControlFramesReceived = *cnt;
+
+	cnt = &mib->counters[lan937x_mib_tx_pause];
+	lan937x_r_mib_pkt(dev, port, lan937x_mib_tx_pause, NULL, cnt);
+	ctrl_sts->MACControlFramesTransmitted = *cnt;
+
+	mutex_unlock(&mib->cnt_mutex);
+}
+
 const struct dsa_switch_ops lan937x_switch_ops = {
 	.get_tag_protocol = lan937x_get_tag_protocol,
 	.setup = lan937x_setup,
 	.phy_read = lan937x_phy_read16,
 	.phy_write = lan937x_phy_write16,
 	.port_enable = ksz_enable_port,
+	.get_strings = lan937x_get_strings,
+	.get_ethtool_stats = ksz_get_ethtool_stats,
+	.get_sset_count = ksz_sset_count,
+	.get_eth_ctrl_stats = lan937x_get_eth_ctrl_stats,
+	.get_eth_mac_stats = lan937x_get_eth_mac_stats,
+	.get_eth_phy_stats = lan937x_get_eth_phy_stats,
+	.get_stats64 = ksz_get_stats64,
 	.port_bridge_join = ksz_port_bridge_join,
 	.port_bridge_leave = ksz_port_bridge_leave,
 	.port_stp_state_set = lan937x_port_stp_state_set,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-02 16:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-02 16:09 [Patch net-next v12 10/13] net: dsa: microchip: add support for ethtool port counters Arun Ramadoss

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).