All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net 0/8] Fixes for Ocelot driver statistics
@ 2022-08-16 13:53 Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 1/8] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters Vladimir Oltean
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

This series contains bug fixes for the ocelot drivers (both switchdev
and DSA). Some concern the counters exposed to ethtool -S, and others to
the counters exposed to ifconfig. I'm aware that the changes are fairly
large, but I wanted to prioritize on a proper approach to addressing the
issues rather than a quick hack.

Some of the noticed problems:
- bad register offsets for some counters
- unhandled concurrency leading to corrupted counters
- unhandled 32-bit wraparound of ifconfig counters

The issues on the ocelot switchdev driver were noticed through code
inspection, I do not have the hardware to test.

This patch set necessarily converts ocelot->stats_lock from a mutex to a
spinlock. I know this affects Colin Foster's development with the SPI
controlled VSC7512. I have other changes prepared for net-next that
convert this back into a mutex (along with other changes in this area).

Vladimir Oltean (8):
  net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters
  net: mscc: ocelot: fix incorrect ndo_get_stats64 packet counters
  net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter
  net: mscc: ocelot: turn stats_lock into a spinlock
  net: mscc: ocelot: fix race between ndo_get_stats64 and
    ocelot_check_stats_work
  net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset
  net: mscc: ocelot: report ndo_get_stats64 from the
    wraparound-resistant ocelot->stats

 drivers/net/dsa/ocelot/felix_vsc9959.c     | 558 +++++++++++++++++----
 drivers/net/dsa/ocelot/seville_vsc9953.c   | 553 ++++++++++++++++----
 drivers/net/ethernet/mscc/ocelot.c         |  62 ++-
 drivers/net/ethernet/mscc/ocelot_net.c     |  55 +-
 drivers/net/ethernet/mscc/ocelot_vsc7514.c | 468 +++++++++++++----
 drivers/net/ethernet/mscc/vsc7514_regs.c   |  84 +++-
 include/soc/mscc/ocelot.h                  | 179 ++++++-
 7 files changed, 1581 insertions(+), 378 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH net 1/8] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 " Vladimir Oltean
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

What the driver actually reports as 256-511 is in fact 512-1023, and the
TX packets in the 256-511 bucket are not reported. Fix that.

Fixes: 56051948773e ("net: dsa: ocelot: add driver for Felix switch family")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index b4034b78c0ca..5859ef3b242c 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -602,7 +602,8 @@ static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
 	{ .offset = 0x87,	.name = "tx_frames_below_65_octets", },
 	{ .offset = 0x88,	.name = "tx_frames_65_to_127_octets", },
 	{ .offset = 0x89,	.name = "tx_frames_128_255_octets", },
-	{ .offset = 0x8B,	.name = "tx_frames_256_511_octets", },
+	{ .offset = 0x8A,	.name = "tx_frames_256_511_octets", },
+	{ .offset = 0x8B,	.name = "tx_frames_512_1023_octets", },
 	{ .offset = 0x8C,	.name = "tx_frames_1024_1526_octets", },
 	{ .offset = 0x8D,	.name = "tx_frames_over_1526_octets", },
 	{ .offset = 0x8E,	.name = "tx_yellow_prio_0", },
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 packet counters
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 1/8] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-17  6:26   ` Colin Foster
  2022-08-16 13:53 ` [PATCH net 3/8] net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter Vladimir Oltean
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

Reading stats using the SYS_COUNT_* register definitions is only used by
ocelot_get_stats64() from the ocelot switchdev driver, however,
currently the bucket definitions are incorrect.

Separately, on both RX and TX, we have the following problems:
- a 256-1023 bucket which actually tracks the 256-511 packets
- the 1024-1526 bucket actually tracks the 512-1023 packets
- the 1527-max bucket actually tracks the 1024-1526 packets

=> nobody tracks the packets from the real 1527-max bucket

Additionally, the RX_PAUSE, RX_CONTROL, RX_LONGS and RX_CLASSIFIED_DROPS
all track the wrong thing. However this doesn't seem to have any
consequence, since ocelot_get_stats64() doesn't use these.

Even though this problem only manifests itself for the switchdev driver,
we cannot split the fix for ocelot and for DSA, since it requires fixing
the bucket definitions from enum ocelot_reg, which makes us necessarily
adapt the structures from felix and seville as well.

Fixes: 84705fc16552 ("net: dsa: felix: introduce support for Seville VSC9953 switch")
Fixes: 56051948773e ("net: dsa: ocelot: add driver for Felix switch family")
Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c   | 20 ++++++++++++--------
 drivers/net/dsa/ocelot/seville_vsc9953.c | 16 +++++++++-------
 drivers/net/ethernet/mscc/ocelot_net.c   |  6 ++++--
 drivers/net/ethernet/mscc/vsc7514_regs.c | 24 +++++++++++++-----------
 include/soc/mscc/ocelot.h                |  6 ++++--
 5 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 5859ef3b242c..e1ebe21cad00 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -281,19 +281,23 @@ static const u32 vsc9959_sys_regmap[] = {
 	REG(SYS_COUNT_RX_64,			0x000024),
 	REG(SYS_COUNT_RX_65_127,		0x000028),
 	REG(SYS_COUNT_RX_128_255,		0x00002c),
-	REG(SYS_COUNT_RX_256_1023,		0x000030),
-	REG(SYS_COUNT_RX_1024_1526,		0x000034),
-	REG(SYS_COUNT_RX_1527_MAX,		0x000038),
-	REG(SYS_COUNT_RX_LONGS,			0x000044),
+	REG(SYS_COUNT_RX_256_511,		0x000030),
+	REG(SYS_COUNT_RX_512_1023,		0x000034),
+	REG(SYS_COUNT_RX_1024_1526,		0x000038),
+	REG(SYS_COUNT_RX_1527_MAX,		0x00003c),
+	REG(SYS_COUNT_RX_PAUSE,			0x000040),
+	REG(SYS_COUNT_RX_CONTROL,		0x000044),
+	REG(SYS_COUNT_RX_LONGS,			0x000048),
 	REG(SYS_COUNT_TX_OCTETS,		0x000200),
 	REG(SYS_COUNT_TX_COLLISION,		0x000210),
 	REG(SYS_COUNT_TX_DROPS,			0x000214),
 	REG(SYS_COUNT_TX_64,			0x00021c),
 	REG(SYS_COUNT_TX_65_127,		0x000220),
-	REG(SYS_COUNT_TX_128_511,		0x000224),
-	REG(SYS_COUNT_TX_512_1023,		0x000228),
-	REG(SYS_COUNT_TX_1024_1526,		0x00022c),
-	REG(SYS_COUNT_TX_1527_MAX,		0x000230),
+	REG(SYS_COUNT_TX_128_255,		0x000224),
+	REG(SYS_COUNT_TX_256_511,		0x000228),
+	REG(SYS_COUNT_TX_512_1023,		0x00022c),
+	REG(SYS_COUNT_TX_1024_1526,		0x000230),
+	REG(SYS_COUNT_TX_1527_MAX,		0x000234),
 	REG(SYS_COUNT_TX_AGING,			0x000278),
 	REG(SYS_RESET_CFG,			0x000e00),
 	REG(SYS_SR_ETYPE_CFG,			0x000e04),
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index ea0649211356..ebe9ddbbe2b7 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -277,19 +277,21 @@ static const u32 vsc9953_sys_regmap[] = {
 	REG(SYS_COUNT_RX_64,			0x000024),
 	REG(SYS_COUNT_RX_65_127,		0x000028),
 	REG(SYS_COUNT_RX_128_255,		0x00002c),
-	REG(SYS_COUNT_RX_256_1023,		0x000030),
-	REG(SYS_COUNT_RX_1024_1526,		0x000034),
-	REG(SYS_COUNT_RX_1527_MAX,		0x000038),
+	REG(SYS_COUNT_RX_256_511,		0x000030),
+	REG(SYS_COUNT_RX_512_1023,		0x000034),
+	REG(SYS_COUNT_RX_1024_1526,		0x000038),
+	REG(SYS_COUNT_RX_1527_MAX,		0x00003c),
 	REG(SYS_COUNT_RX_LONGS,			0x000048),
 	REG(SYS_COUNT_TX_OCTETS,		0x000100),
 	REG(SYS_COUNT_TX_COLLISION,		0x000110),
 	REG(SYS_COUNT_TX_DROPS,			0x000114),
 	REG(SYS_COUNT_TX_64,			0x00011c),
 	REG(SYS_COUNT_TX_65_127,		0x000120),
-	REG(SYS_COUNT_TX_128_511,		0x000124),
-	REG(SYS_COUNT_TX_512_1023,		0x000128),
-	REG(SYS_COUNT_TX_1024_1526,		0x00012c),
-	REG(SYS_COUNT_TX_1527_MAX,		0x000130),
+	REG(SYS_COUNT_TX_128_255,		0x000124),
+	REG(SYS_COUNT_TX_256_511,		0x000128),
+	REG(SYS_COUNT_TX_512_1023,		0x00012c),
+	REG(SYS_COUNT_TX_1024_1526,		0x000130),
+	REG(SYS_COUNT_TX_1527_MAX,		0x000134),
 	REG(SYS_COUNT_TX_AGING,			0x000178),
 	REG(SYS_RESET_CFG,			0x000318),
 	REG_RESERVED(SYS_SR_ETYPE_CFG),
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 5e6136e80282..9d8cea16245e 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -739,7 +739,8 @@ static void ocelot_get_stats64(struct net_device *dev,
 			    ocelot_read(ocelot, SYS_COUNT_RX_64) +
 			    ocelot_read(ocelot, SYS_COUNT_RX_65_127) +
 			    ocelot_read(ocelot, SYS_COUNT_RX_128_255) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_256_1023) +
+			    ocelot_read(ocelot, SYS_COUNT_RX_256_511) +
+			    ocelot_read(ocelot, SYS_COUNT_RX_512_1023) +
 			    ocelot_read(ocelot, SYS_COUNT_RX_1024_1526) +
 			    ocelot_read(ocelot, SYS_COUNT_RX_1527_MAX);
 	stats->multicast = ocelot_read(ocelot, SYS_COUNT_RX_MULTICAST);
@@ -749,7 +750,8 @@ static void ocelot_get_stats64(struct net_device *dev,
 	stats->tx_bytes = ocelot_read(ocelot, SYS_COUNT_TX_OCTETS);
 	stats->tx_packets = ocelot_read(ocelot, SYS_COUNT_TX_64) +
 			    ocelot_read(ocelot, SYS_COUNT_TX_65_127) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_128_511) +
+			    ocelot_read(ocelot, SYS_COUNT_TX_128_255) +
+			    ocelot_read(ocelot, SYS_COUNT_TX_256_511) +
 			    ocelot_read(ocelot, SYS_COUNT_TX_512_1023) +
 			    ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) +
 			    ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX);
diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c
index c2af4eb8ca5d..38ab20b48cd4 100644
--- a/drivers/net/ethernet/mscc/vsc7514_regs.c
+++ b/drivers/net/ethernet/mscc/vsc7514_regs.c
@@ -180,13 +180,14 @@ const u32 vsc7514_sys_regmap[] = {
 	REG(SYS_COUNT_RX_64,				0x000024),
 	REG(SYS_COUNT_RX_65_127,			0x000028),
 	REG(SYS_COUNT_RX_128_255,			0x00002c),
-	REG(SYS_COUNT_RX_256_1023,			0x000030),
-	REG(SYS_COUNT_RX_1024_1526,			0x000034),
-	REG(SYS_COUNT_RX_1527_MAX,			0x000038),
-	REG(SYS_COUNT_RX_PAUSE,				0x00003c),
-	REG(SYS_COUNT_RX_CONTROL,			0x000040),
-	REG(SYS_COUNT_RX_LONGS,				0x000044),
-	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x000048),
+	REG(SYS_COUNT_RX_256_511,			0x000030),
+	REG(SYS_COUNT_RX_512_1023,			0x000034),
+	REG(SYS_COUNT_RX_1024_1526,			0x000038),
+	REG(SYS_COUNT_RX_1527_MAX,			0x00003c),
+	REG(SYS_COUNT_RX_PAUSE,				0x000040),
+	REG(SYS_COUNT_RX_CONTROL,			0x000044),
+	REG(SYS_COUNT_RX_LONGS,				0x000048),
+	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x00004c),
 	REG(SYS_COUNT_TX_OCTETS,			0x000100),
 	REG(SYS_COUNT_TX_UNICAST,			0x000104),
 	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
@@ -196,10 +197,11 @@ const u32 vsc7514_sys_regmap[] = {
 	REG(SYS_COUNT_TX_PAUSE,				0x000118),
 	REG(SYS_COUNT_TX_64,				0x00011c),
 	REG(SYS_COUNT_TX_65_127,			0x000120),
-	REG(SYS_COUNT_TX_128_511,			0x000124),
-	REG(SYS_COUNT_TX_512_1023,			0x000128),
-	REG(SYS_COUNT_TX_1024_1526,			0x00012c),
-	REG(SYS_COUNT_TX_1527_MAX,			0x000130),
+	REG(SYS_COUNT_TX_128_255,			0x000124),
+	REG(SYS_COUNT_TX_256_511,			0x000128),
+	REG(SYS_COUNT_TX_512_1023,			0x00012c),
+	REG(SYS_COUNT_TX_1024_1526,			0x000130),
+	REG(SYS_COUNT_TX_1527_MAX,			0x000134),
 	REG(SYS_COUNT_TX_AGING,				0x000170),
 	REG(SYS_RESET_CFG,				0x000508),
 	REG(SYS_CMID,					0x00050c),
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index ac151ecc7f19..e7e5b06deb2d 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -335,7 +335,8 @@ enum ocelot_reg {
 	SYS_COUNT_RX_64,
 	SYS_COUNT_RX_65_127,
 	SYS_COUNT_RX_128_255,
-	SYS_COUNT_RX_256_1023,
+	SYS_COUNT_RX_256_511,
+	SYS_COUNT_RX_512_1023,
 	SYS_COUNT_RX_1024_1526,
 	SYS_COUNT_RX_1527_MAX,
 	SYS_COUNT_RX_PAUSE,
@@ -351,7 +352,8 @@ enum ocelot_reg {
 	SYS_COUNT_TX_PAUSE,
 	SYS_COUNT_TX_64,
 	SYS_COUNT_TX_65_127,
-	SYS_COUNT_TX_128_511,
+	SYS_COUNT_TX_128_255,
+	SYS_COUNT_TX_256_511,
 	SYS_COUNT_TX_512_1023,
 	SYS_COUNT_TX_1024_1526,
 	SYS_COUNT_TX_1527_MAX,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 3/8] net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 1/8] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 " Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 4/8] net: mscc: ocelot: turn stats_lock into a spinlock Vladimir Oltean
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

This register, used as part of stats->tx_dropped in
ocelot_get_stats64(), has a wrong address. At the address currently
given, there is actually the c_tx_green_prio_6 counter.

Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/vsc7514_regs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c
index 38ab20b48cd4..8ff935f7f150 100644
--- a/drivers/net/ethernet/mscc/vsc7514_regs.c
+++ b/drivers/net/ethernet/mscc/vsc7514_regs.c
@@ -202,7 +202,7 @@ const u32 vsc7514_sys_regmap[] = {
 	REG(SYS_COUNT_TX_512_1023,			0x00012c),
 	REG(SYS_COUNT_TX_1024_1526,			0x000130),
 	REG(SYS_COUNT_TX_1527_MAX,			0x000134),
-	REG(SYS_COUNT_TX_AGING,				0x000170),
+	REG(SYS_COUNT_TX_AGING,				0x000178),
 	REG(SYS_RESET_CFG,				0x000508),
 	REG(SYS_CMID,					0x00050c),
 	REG(SYS_VLAN_ETYPE_CFG,				0x000510),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 4/8] net: mscc: ocelot: turn stats_lock into a spinlock
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
                   ` (2 preceding siblings ...)
  2022-08-16 13:53 ` [PATCH net 3/8] net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 5/8] net: mscc: ocelot: fix race between ndo_get_stats64 and ocelot_check_stats_work Vladimir Oltean
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

ocelot_get_stats64() currently runs unlocked and therefore may collide
with ocelot_port_update_stats() which indirectly accesses the same
counters. However, ocelot_get_stats64() runs in atomic context, and we
cannot simply take the sleepable ocelot->stats_lock mutex. We need to
convert it to an atomic spinlock first. Do that as a preparatory change.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c |  4 ++--
 drivers/net/ethernet/mscc/ocelot.c     | 11 +++++------
 include/soc/mscc/ocelot.h              |  2 +-
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index e1ebe21cad00..46fd6cd0d8f3 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -2171,7 +2171,7 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,
 static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
 				      struct felix_stream_filter_counters *counters)
 {
-	mutex_lock(&ocelot->stats_lock);
+	spin_lock(&ocelot->stats_lock);
 
 	ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index),
 		   SYS_STAT_CFG_STAT_VIEW_M,
@@ -2188,7 +2188,7 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
 		     SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),
 		     SYS_STAT_CFG);
 
-	mutex_unlock(&ocelot->stats_lock);
+	spin_unlock(&ocelot->stats_lock);
 }
 
 static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index d4649e4ee0e7..c67f162f8ab5 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1906,13 +1906,13 @@ static void ocelot_check_stats_work(struct work_struct *work)
 					     stats_work);
 	int i, err;
 
-	mutex_lock(&ocelot->stats_lock);
+	spin_lock(&ocelot->stats_lock);
 	for (i = 0; i < ocelot->num_phys_ports; i++) {
 		err = ocelot_port_update_stats(ocelot, i);
 		if (err)
 			break;
 	}
-	mutex_unlock(&ocelot->stats_lock);
+	spin_unlock(&ocelot->stats_lock);
 
 	if (err)
 		dev_err(ocelot->dev, "Error %d updating ethtool stats\n",  err);
@@ -1925,7 +1925,7 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
 {
 	int i, err;
 
-	mutex_lock(&ocelot->stats_lock);
+	spin_lock(&ocelot->stats_lock);
 
 	/* check and update now */
 	err = ocelot_port_update_stats(ocelot, port);
@@ -1934,7 +1934,7 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
 	for (i = 0; i < ocelot->num_stats; i++)
 		*data++ = ocelot->stats[port * ocelot->num_stats + i];
 
-	mutex_unlock(&ocelot->stats_lock);
+	spin_unlock(&ocelot->stats_lock);
 
 	if (err)
 		dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err);
@@ -3363,7 +3363,7 @@ int ocelot_init(struct ocelot *ocelot)
 	if (!ocelot->stats)
 		return -ENOMEM;
 
-	mutex_init(&ocelot->stats_lock);
+	spin_lock_init(&ocelot->stats_lock);
 	mutex_init(&ocelot->ptp_lock);
 	mutex_init(&ocelot->mact_lock);
 	mutex_init(&ocelot->fwd_domain_lock);
@@ -3511,7 +3511,6 @@ void ocelot_deinit(struct ocelot *ocelot)
 	cancel_delayed_work(&ocelot->stats_work);
 	destroy_workqueue(ocelot->stats_queue);
 	destroy_workqueue(ocelot->owq);
-	mutex_destroy(&ocelot->stats_lock);
 }
 EXPORT_SYMBOL(ocelot_deinit);
 
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index e7e5b06deb2d..72b9474391da 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -752,7 +752,7 @@ struct ocelot {
 	struct ocelot_psfp_list		psfp;
 
 	/* Workqueue to check statistics for overflow with its lock */
-	struct mutex			stats_lock;
+	spinlock_t			stats_lock;
 	u64				*stats;
 	struct delayed_work		stats_work;
 	struct workqueue_struct		*stats_queue;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 5/8] net: mscc: ocelot: fix race between ndo_get_stats64 and ocelot_check_stats_work
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
                   ` (3 preceding siblings ...)
  2022-08-16 13:53 ` [PATCH net 4/8] net: mscc: ocelot: turn stats_lock into a spinlock Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable Vladimir Oltean
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

The 2 methods can run concurrently, and one will change the window of
counters (SYS_STAT_CFG_STAT_VIEW) that the other sees. The fix is
similar to what commit 7fbf6795d127 ("net: mscc: ocelot: fix mutex lock
error during ethtool stats read") has done for ethtool -S.

Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_net.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 9d8cea16245e..6b9d37138844 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -726,6 +726,8 @@ static void ocelot_get_stats64(struct net_device *dev,
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
 
+	spin_lock(&ocelot->stats_lock);
+
 	/* Configure the port to read the stats from */
 	ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port),
 		     SYS_STAT_CFG);
@@ -758,6 +760,8 @@ static void ocelot_get_stats64(struct net_device *dev,
 	stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) +
 			    ocelot_read(ocelot, SYS_COUNT_TX_AGING);
 	stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION);
+
+	spin_unlock(&ocelot->stats_lock);
 }
 
 static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
                   ` (4 preceding siblings ...)
  2022-08-16 13:53 ` [PATCH net 5/8] net: mscc: ocelot: fix race between ndo_get_stats64 and ocelot_check_stats_work Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-17  6:46   ` Colin Foster
  2022-08-16 13:53 ` [PATCH net 7/8] net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset Vladimir Oltean
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

The ocelot counters are 32-bit and require periodic reading, every 2
seconds, by ocelot_port_update_stats(), so that wraparounds are
detected.

Currently, the counters reported by ocelot_get_stats64() come from the
32-bit hardware counters directly, rather than from the 64-bit
accumulated ocelot->stats, and this is a problem for their integrity.

The strategy is to make ocelot_get_stats64() able to cherry-pick
individual stats from ocelot->stats the way in which it currently reads
them out from SYS_COUNT_* registers. But currently it can't, because
ocelot->stats is an opaque u64 array that's used only to feed data into
ethtool -S.

To solve that problem, we need to make ocelot->stats indexable, and
associate each element with an element of struct ocelot_stat_layout used
by ethtool -S.

This makes ocelot_stat_layout a fat (and possibly sparse) array, so we
need to change the way in which we access it. We no longer need
OCELOT_STAT_END as a sentinel, because we know the array's size
(OCELOT_NUM_STATS). We just need to skip the array elements that were
left unpopulated for the switch revision (ocelot, felix, seville).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c     | 468 ++++++++++++++++-----
 drivers/net/dsa/ocelot/seville_vsc9953.c   | 468 ++++++++++++++++-----
 drivers/net/ethernet/mscc/ocelot.c         |  40 +-
 drivers/net/ethernet/mscc/ocelot_vsc7514.c | 468 ++++++++++++++++-----
 include/soc/mscc/ocelot.h                  | 105 ++++-
 5 files changed, 1243 insertions(+), 306 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 46fd6cd0d8f3..c9f270f24b1c 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -551,101 +551,379 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = {
 	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4),
 };
 
-static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
-	{ .offset = 0x00,	.name = "rx_octets", },
-	{ .offset = 0x01,	.name = "rx_unicast", },
-	{ .offset = 0x02,	.name = "rx_multicast", },
-	{ .offset = 0x03,	.name = "rx_broadcast", },
-	{ .offset = 0x04,	.name = "rx_shorts", },
-	{ .offset = 0x05,	.name = "rx_fragments", },
-	{ .offset = 0x06,	.name = "rx_jabbers", },
-	{ .offset = 0x07,	.name = "rx_crc_align_errs", },
-	{ .offset = 0x08,	.name = "rx_sym_errs", },
-	{ .offset = 0x09,	.name = "rx_frames_below_65_octets", },
-	{ .offset = 0x0A,	.name = "rx_frames_65_to_127_octets", },
-	{ .offset = 0x0B,	.name = "rx_frames_128_to_255_octets", },
-	{ .offset = 0x0C,	.name = "rx_frames_256_to_511_octets", },
-	{ .offset = 0x0D,	.name = "rx_frames_512_to_1023_octets", },
-	{ .offset = 0x0E,	.name = "rx_frames_1024_to_1526_octets", },
-	{ .offset = 0x0F,	.name = "rx_frames_over_1526_octets", },
-	{ .offset = 0x10,	.name = "rx_pause", },
-	{ .offset = 0x11,	.name = "rx_control", },
-	{ .offset = 0x12,	.name = "rx_longs", },
-	{ .offset = 0x13,	.name = "rx_classified_drops", },
-	{ .offset = 0x14,	.name = "rx_red_prio_0", },
-	{ .offset = 0x15,	.name = "rx_red_prio_1", },
-	{ .offset = 0x16,	.name = "rx_red_prio_2", },
-	{ .offset = 0x17,	.name = "rx_red_prio_3", },
-	{ .offset = 0x18,	.name = "rx_red_prio_4", },
-	{ .offset = 0x19,	.name = "rx_red_prio_5", },
-	{ .offset = 0x1A,	.name = "rx_red_prio_6", },
-	{ .offset = 0x1B,	.name = "rx_red_prio_7", },
-	{ .offset = 0x1C,	.name = "rx_yellow_prio_0", },
-	{ .offset = 0x1D,	.name = "rx_yellow_prio_1", },
-	{ .offset = 0x1E,	.name = "rx_yellow_prio_2", },
-	{ .offset = 0x1F,	.name = "rx_yellow_prio_3", },
-	{ .offset = 0x20,	.name = "rx_yellow_prio_4", },
-	{ .offset = 0x21,	.name = "rx_yellow_prio_5", },
-	{ .offset = 0x22,	.name = "rx_yellow_prio_6", },
-	{ .offset = 0x23,	.name = "rx_yellow_prio_7", },
-	{ .offset = 0x24,	.name = "rx_green_prio_0", },
-	{ .offset = 0x25,	.name = "rx_green_prio_1", },
-	{ .offset = 0x26,	.name = "rx_green_prio_2", },
-	{ .offset = 0x27,	.name = "rx_green_prio_3", },
-	{ .offset = 0x28,	.name = "rx_green_prio_4", },
-	{ .offset = 0x29,	.name = "rx_green_prio_5", },
-	{ .offset = 0x2A,	.name = "rx_green_prio_6", },
-	{ .offset = 0x2B,	.name = "rx_green_prio_7", },
-	{ .offset = 0x80,	.name = "tx_octets", },
-	{ .offset = 0x81,	.name = "tx_unicast", },
-	{ .offset = 0x82,	.name = "tx_multicast", },
-	{ .offset = 0x83,	.name = "tx_broadcast", },
-	{ .offset = 0x84,	.name = "tx_collision", },
-	{ .offset = 0x85,	.name = "tx_drops", },
-	{ .offset = 0x86,	.name = "tx_pause", },
-	{ .offset = 0x87,	.name = "tx_frames_below_65_octets", },
-	{ .offset = 0x88,	.name = "tx_frames_65_to_127_octets", },
-	{ .offset = 0x89,	.name = "tx_frames_128_255_octets", },
-	{ .offset = 0x8A,	.name = "tx_frames_256_511_octets", },
-	{ .offset = 0x8B,	.name = "tx_frames_512_1023_octets", },
-	{ .offset = 0x8C,	.name = "tx_frames_1024_1526_octets", },
-	{ .offset = 0x8D,	.name = "tx_frames_over_1526_octets", },
-	{ .offset = 0x8E,	.name = "tx_yellow_prio_0", },
-	{ .offset = 0x8F,	.name = "tx_yellow_prio_1", },
-	{ .offset = 0x90,	.name = "tx_yellow_prio_2", },
-	{ .offset = 0x91,	.name = "tx_yellow_prio_3", },
-	{ .offset = 0x92,	.name = "tx_yellow_prio_4", },
-	{ .offset = 0x93,	.name = "tx_yellow_prio_5", },
-	{ .offset = 0x94,	.name = "tx_yellow_prio_6", },
-	{ .offset = 0x95,	.name = "tx_yellow_prio_7", },
-	{ .offset = 0x96,	.name = "tx_green_prio_0", },
-	{ .offset = 0x97,	.name = "tx_green_prio_1", },
-	{ .offset = 0x98,	.name = "tx_green_prio_2", },
-	{ .offset = 0x99,	.name = "tx_green_prio_3", },
-	{ .offset = 0x9A,	.name = "tx_green_prio_4", },
-	{ .offset = 0x9B,	.name = "tx_green_prio_5", },
-	{ .offset = 0x9C,	.name = "tx_green_prio_6", },
-	{ .offset = 0x9D,	.name = "tx_green_prio_7", },
-	{ .offset = 0x9E,	.name = "tx_aged", },
-	{ .offset = 0x100,	.name = "drop_local", },
-	{ .offset = 0x101,	.name = "drop_tail", },
-	{ .offset = 0x102,	.name = "drop_yellow_prio_0", },
-	{ .offset = 0x103,	.name = "drop_yellow_prio_1", },
-	{ .offset = 0x104,	.name = "drop_yellow_prio_2", },
-	{ .offset = 0x105,	.name = "drop_yellow_prio_3", },
-	{ .offset = 0x106,	.name = "drop_yellow_prio_4", },
-	{ .offset = 0x107,	.name = "drop_yellow_prio_5", },
-	{ .offset = 0x108,	.name = "drop_yellow_prio_6", },
-	{ .offset = 0x109,	.name = "drop_yellow_prio_7", },
-	{ .offset = 0x10A,	.name = "drop_green_prio_0", },
-	{ .offset = 0x10B,	.name = "drop_green_prio_1", },
-	{ .offset = 0x10C,	.name = "drop_green_prio_2", },
-	{ .offset = 0x10D,	.name = "drop_green_prio_3", },
-	{ .offset = 0x10E,	.name = "drop_green_prio_4", },
-	{ .offset = 0x10F,	.name = "drop_green_prio_5", },
-	{ .offset = 0x110,	.name = "drop_green_prio_6", },
-	{ .offset = 0x111,	.name = "drop_green_prio_7", },
-	OCELOT_STAT_END
+static const struct ocelot_stat_layout vsc9959_stats_layout[OCELOT_NUM_STATS] = {
+	[OCELOT_STAT_RX_OCTETS] = {
+		.name = "rx_octets",
+		.offset = 0x00,
+	},
+	[OCELOT_STAT_RX_UNICAST] = {
+		.name = "rx_unicast",
+		.offset = 0x01,
+	},
+	[OCELOT_STAT_RX_MULTICAST] = {
+		.name = "rx_multicast",
+		.offset = 0x02,
+	},
+	[OCELOT_STAT_RX_BROADCAST] = {
+		.name = "rx_broadcast",
+		.offset = 0x03,
+	},
+	[OCELOT_STAT_RX_SHORTS] = {
+		.name = "rx_shorts",
+		.offset = 0x04,
+	},
+	[OCELOT_STAT_RX_FRAGMENTS] = {
+		.name = "rx_fragments",
+		.offset = 0x05,
+	},
+	[OCELOT_STAT_RX_JABBERS] = {
+		.name = "rx_jabbers",
+		.offset = 0x06,
+	},
+	[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
+		.name = "rx_crc_align_errs",
+		.offset = 0x07,
+	},
+	[OCELOT_STAT_RX_SYM_ERRS] = {
+		.name = "rx_sym_errs",
+		.offset = 0x08,
+	},
+	[OCELOT_STAT_RX_64] = {
+		.name = "rx_frames_below_65_octets",
+		.offset = 0x09,
+	},
+	[OCELOT_STAT_RX_65_127] = {
+		.name = "rx_frames_65_to_127_octets",
+		.offset = 0x0A,
+	},
+	[OCELOT_STAT_RX_128_255] = {
+		.name = "rx_frames_128_to_255_octets",
+		.offset = 0x0B,
+	},
+	[OCELOT_STAT_RX_256_511] = {
+		.name = "rx_frames_256_to_511_octets",
+		.offset = 0x0C,
+	},
+	[OCELOT_STAT_RX_512_1023] = {
+		.name = "rx_frames_512_to_1023_octets",
+		.offset = 0x0D,
+	},
+	[OCELOT_STAT_RX_1024_1526] = {
+		.name = "rx_frames_1024_to_1526_octets",
+		.offset = 0x0E,
+	},
+	[OCELOT_STAT_RX_1527_MAX] = {
+		.name = "rx_frames_over_1526_octets",
+		.offset = 0x0F,
+	},
+	[OCELOT_STAT_RX_PAUSE] = {
+		.name = "rx_pause",
+		.offset = 0x10,
+	},
+	[OCELOT_STAT_RX_CONTROL] = {
+		.name = "rx_control",
+		.offset = 0x11,
+	},
+	[OCELOT_STAT_RX_LONGS] = {
+		.name = "rx_longs",
+		.offset = 0x12,
+	},
+	[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
+		.name = "rx_classified_drops",
+		.offset = 0x13,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_0] = {
+		.name = "rx_red_prio_0",
+		.offset = 0x14,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_1] = {
+		.name = "rx_red_prio_1",
+		.offset = 0x15,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_2] = {
+		.name = "rx_red_prio_2",
+		.offset = 0x16,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_3] = {
+		.name = "rx_red_prio_3",
+		.offset = 0x17,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_4] = {
+		.name = "rx_red_prio_4",
+		.offset = 0x18,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_5] = {
+		.name = "rx_red_prio_5",
+		.offset = 0x19,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_6] = {
+		.name = "rx_red_prio_6",
+		.offset = 0x1A,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_7] = {
+		.name = "rx_red_prio_7",
+		.offset = 0x1B,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
+		.name = "rx_yellow_prio_0",
+		.offset = 0x1C,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
+		.name = "rx_yellow_prio_1",
+		.offset = 0x1D,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
+		.name = "rx_yellow_prio_2",
+		.offset = 0x1E,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
+		.name = "rx_yellow_prio_3",
+		.offset = 0x1F,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
+		.name = "rx_yellow_prio_4",
+		.offset = 0x20,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
+		.name = "rx_yellow_prio_5",
+		.offset = 0x21,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
+		.name = "rx_yellow_prio_6",
+		.offset = 0x22,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
+		.name = "rx_yellow_prio_7",
+		.offset = 0x23,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_0] = {
+		.name = "rx_green_prio_0",
+		.offset = 0x24,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_1] = {
+		.name = "rx_green_prio_1",
+		.offset = 0x25,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_2] = {
+		.name = "rx_green_prio_2",
+		.offset = 0x26,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_3] = {
+		.name = "rx_green_prio_3",
+		.offset = 0x27,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_4] = {
+		.name = "rx_green_prio_4",
+		.offset = 0x28,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_5] = {
+		.name = "rx_green_prio_5",
+		.offset = 0x29,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_6] = {
+		.name = "rx_green_prio_6",
+		.offset = 0x2A,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_7] = {
+		.name = "rx_green_prio_7",
+		.offset = 0x2B,
+	},
+	[OCELOT_STAT_TX_OCTETS] = {
+		.name = "tx_octets",
+		.offset = 0x80,
+	},
+	[OCELOT_STAT_TX_UNICAST] = {
+		.name = "tx_unicast",
+		.offset = 0x81,
+	},
+	[OCELOT_STAT_TX_MULTICAST] = {
+		.name = "tx_multicast",
+		.offset = 0x82,
+	},
+	[OCELOT_STAT_TX_BROADCAST] = {
+		.name = "tx_broadcast",
+		.offset = 0x83,
+	},
+	[OCELOT_STAT_TX_COLLISION] = {
+		.name = "tx_collision",
+		.offset = 0x84,
+	},
+	[OCELOT_STAT_TX_DROPS] = {
+		.name = "tx_drops",
+		.offset = 0x85,
+	},
+	[OCELOT_STAT_TX_PAUSE] = {
+		.name = "tx_pause",
+		.offset = 0x86,
+	},
+	[OCELOT_STAT_TX_64] = {
+		.name = "tx_frames_below_65_octets",
+		.offset = 0x87,
+	},
+	[OCELOT_STAT_TX_65_127] = {
+		.name = "tx_frames_65_to_127_octets",
+		.offset = 0x88,
+	},
+	[OCELOT_STAT_TX_128_255] = {
+		.name = "tx_frames_128_255_octets",
+		.offset = 0x89,
+	},
+	[OCELOT_STAT_TX_256_511] = {
+		.name = "tx_frames_256_511_octets",
+		.offset = 0x8A,
+	},
+	[OCELOT_STAT_TX_512_1023] = {
+		.name = "tx_frames_512_1023_octets",
+		.offset = 0x8B,
+	},
+	[OCELOT_STAT_TX_1024_1526] = {
+		.name = "tx_frames_1024_1526_octets",
+		.offset = 0x8C,
+	},
+	[OCELOT_STAT_TX_1527_MAX] = {
+		.name = "tx_frames_over_1526_octets",
+		.offset = 0x8D,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
+		.name = "tx_yellow_prio_0",
+		.offset = 0x8E,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
+		.name = "tx_yellow_prio_1",
+		.offset = 0x8F,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
+		.name = "tx_yellow_prio_2",
+		.offset = 0x90,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
+		.name = "tx_yellow_prio_3",
+		.offset = 0x91,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
+		.name = "tx_yellow_prio_4",
+		.offset = 0x92,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
+		.name = "tx_yellow_prio_5",
+		.offset = 0x93,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
+		.name = "tx_yellow_prio_6",
+		.offset = 0x94,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
+		.name = "tx_yellow_prio_7",
+		.offset = 0x95,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_0] = {
+		.name = "tx_green_prio_0",
+		.offset = 0x96,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_1] = {
+		.name = "tx_green_prio_1",
+		.offset = 0x97,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_2] = {
+		.name = "tx_green_prio_2",
+		.offset = 0x98,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_3] = {
+		.name = "tx_green_prio_3",
+		.offset = 0x99,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_4] = {
+		.name = "tx_green_prio_4",
+		.offset = 0x9A,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_5] = {
+		.name = "tx_green_prio_5",
+		.offset = 0x9B,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_6] = {
+		.name = "tx_green_prio_6",
+		.offset = 0x9C,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_7] = {
+		.name = "tx_green_prio_7",
+		.offset = 0x9D,
+	},
+	[OCELOT_STAT_TX_AGED] = {
+		.name = "tx_aged",
+		.offset = 0x9E,
+	},
+	[OCELOT_STAT_DROP_LOCAL] = {
+		.name = "drop_local",
+		.offset = 0x100,
+	},
+	[OCELOT_STAT_DROP_TAIL] = {
+		.name = "drop_tail",
+		.offset = 0x101,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
+		.name = "drop_yellow_prio_0",
+		.offset = 0x102,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
+		.name = "drop_yellow_prio_1",
+		.offset = 0x103,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
+		.name = "drop_yellow_prio_2",
+		.offset = 0x104,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
+		.name = "drop_yellow_prio_3",
+		.offset = 0x105,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
+		.name = "drop_yellow_prio_4",
+		.offset = 0x106,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
+		.name = "drop_yellow_prio_5",
+		.offset = 0x107,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
+		.name = "drop_yellow_prio_6",
+		.offset = 0x108,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
+		.name = "drop_yellow_prio_7",
+		.offset = 0x109,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
+		.name = "drop_green_prio_0",
+		.offset = 0x10A,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
+		.name = "drop_green_prio_1",
+		.offset = 0x10B,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
+		.name = "drop_green_prio_2",
+		.offset = 0x10C,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
+		.name = "drop_green_prio_3",
+		.offset = 0x10D,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
+		.name = "drop_green_prio_4",
+		.offset = 0x10E,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
+		.name = "drop_green_prio_5",
+		.offset = 0x10F,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
+		.name = "drop_green_prio_6",
+		.offset = 0x110,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
+		.name = "drop_green_prio_7",
+		.offset = 0x111,
+	},
 };
 
 static const struct vcap_field vsc9959_vcap_es0_keys[] = {
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index ebe9ddbbe2b7..fe5d4642d0bc 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -545,101 +545,379 @@ static const struct reg_field vsc9953_regfields[REGFIELD_MAX] = {
 	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 11, 4),
 };
 
-static const struct ocelot_stat_layout vsc9953_stats_layout[] = {
-	{ .offset = 0x00,	.name = "rx_octets", },
-	{ .offset = 0x01,	.name = "rx_unicast", },
-	{ .offset = 0x02,	.name = "rx_multicast", },
-	{ .offset = 0x03,	.name = "rx_broadcast", },
-	{ .offset = 0x04,	.name = "rx_shorts", },
-	{ .offset = 0x05,	.name = "rx_fragments", },
-	{ .offset = 0x06,	.name = "rx_jabbers", },
-	{ .offset = 0x07,	.name = "rx_crc_align_errs", },
-	{ .offset = 0x08,	.name = "rx_sym_errs", },
-	{ .offset = 0x09,	.name = "rx_frames_below_65_octets", },
-	{ .offset = 0x0A,	.name = "rx_frames_65_to_127_octets", },
-	{ .offset = 0x0B,	.name = "rx_frames_128_to_255_octets", },
-	{ .offset = 0x0C,	.name = "rx_frames_256_to_511_octets", },
-	{ .offset = 0x0D,	.name = "rx_frames_512_to_1023_octets", },
-	{ .offset = 0x0E,	.name = "rx_frames_1024_to_1526_octets", },
-	{ .offset = 0x0F,	.name = "rx_frames_over_1526_octets", },
-	{ .offset = 0x10,	.name = "rx_pause", },
-	{ .offset = 0x11,	.name = "rx_control", },
-	{ .offset = 0x12,	.name = "rx_longs", },
-	{ .offset = 0x13,	.name = "rx_classified_drops", },
-	{ .offset = 0x14,	.name = "rx_red_prio_0", },
-	{ .offset = 0x15,	.name = "rx_red_prio_1", },
-	{ .offset = 0x16,	.name = "rx_red_prio_2", },
-	{ .offset = 0x17,	.name = "rx_red_prio_3", },
-	{ .offset = 0x18,	.name = "rx_red_prio_4", },
-	{ .offset = 0x19,	.name = "rx_red_prio_5", },
-	{ .offset = 0x1A,	.name = "rx_red_prio_6", },
-	{ .offset = 0x1B,	.name = "rx_red_prio_7", },
-	{ .offset = 0x1C,	.name = "rx_yellow_prio_0", },
-	{ .offset = 0x1D,	.name = "rx_yellow_prio_1", },
-	{ .offset = 0x1E,	.name = "rx_yellow_prio_2", },
-	{ .offset = 0x1F,	.name = "rx_yellow_prio_3", },
-	{ .offset = 0x20,	.name = "rx_yellow_prio_4", },
-	{ .offset = 0x21,	.name = "rx_yellow_prio_5", },
-	{ .offset = 0x22,	.name = "rx_yellow_prio_6", },
-	{ .offset = 0x23,	.name = "rx_yellow_prio_7", },
-	{ .offset = 0x24,	.name = "rx_green_prio_0", },
-	{ .offset = 0x25,	.name = "rx_green_prio_1", },
-	{ .offset = 0x26,	.name = "rx_green_prio_2", },
-	{ .offset = 0x27,	.name = "rx_green_prio_3", },
-	{ .offset = 0x28,	.name = "rx_green_prio_4", },
-	{ .offset = 0x29,	.name = "rx_green_prio_5", },
-	{ .offset = 0x2A,	.name = "rx_green_prio_6", },
-	{ .offset = 0x2B,	.name = "rx_green_prio_7", },
-	{ .offset = 0x40,	.name = "tx_octets", },
-	{ .offset = 0x41,	.name = "tx_unicast", },
-	{ .offset = 0x42,	.name = "tx_multicast", },
-	{ .offset = 0x43,	.name = "tx_broadcast", },
-	{ .offset = 0x44,	.name = "tx_collision", },
-	{ .offset = 0x45,	.name = "tx_drops", },
-	{ .offset = 0x46,	.name = "tx_pause", },
-	{ .offset = 0x47,	.name = "tx_frames_below_65_octets", },
-	{ .offset = 0x48,	.name = "tx_frames_65_to_127_octets", },
-	{ .offset = 0x49,	.name = "tx_frames_128_255_octets", },
-	{ .offset = 0x4A,	.name = "tx_frames_256_511_octets", },
-	{ .offset = 0x4B,	.name = "tx_frames_512_1023_octets", },
-	{ .offset = 0x4C,	.name = "tx_frames_1024_1526_octets", },
-	{ .offset = 0x4D,	.name = "tx_frames_over_1526_octets", },
-	{ .offset = 0x4E,	.name = "tx_yellow_prio_0", },
-	{ .offset = 0x4F,	.name = "tx_yellow_prio_1", },
-	{ .offset = 0x50,	.name = "tx_yellow_prio_2", },
-	{ .offset = 0x51,	.name = "tx_yellow_prio_3", },
-	{ .offset = 0x52,	.name = "tx_yellow_prio_4", },
-	{ .offset = 0x53,	.name = "tx_yellow_prio_5", },
-	{ .offset = 0x54,	.name = "tx_yellow_prio_6", },
-	{ .offset = 0x55,	.name = "tx_yellow_prio_7", },
-	{ .offset = 0x56,	.name = "tx_green_prio_0", },
-	{ .offset = 0x57,	.name = "tx_green_prio_1", },
-	{ .offset = 0x58,	.name = "tx_green_prio_2", },
-	{ .offset = 0x59,	.name = "tx_green_prio_3", },
-	{ .offset = 0x5A,	.name = "tx_green_prio_4", },
-	{ .offset = 0x5B,	.name = "tx_green_prio_5", },
-	{ .offset = 0x5C,	.name = "tx_green_prio_6", },
-	{ .offset = 0x5D,	.name = "tx_green_prio_7", },
-	{ .offset = 0x5E,	.name = "tx_aged", },
-	{ .offset = 0x80,	.name = "drop_local", },
-	{ .offset = 0x81,	.name = "drop_tail", },
-	{ .offset = 0x82,	.name = "drop_yellow_prio_0", },
-	{ .offset = 0x83,	.name = "drop_yellow_prio_1", },
-	{ .offset = 0x84,	.name = "drop_yellow_prio_2", },
-	{ .offset = 0x85,	.name = "drop_yellow_prio_3", },
-	{ .offset = 0x86,	.name = "drop_yellow_prio_4", },
-	{ .offset = 0x87,	.name = "drop_yellow_prio_5", },
-	{ .offset = 0x88,	.name = "drop_yellow_prio_6", },
-	{ .offset = 0x89,	.name = "drop_yellow_prio_7", },
-	{ .offset = 0x8A,	.name = "drop_green_prio_0", },
-	{ .offset = 0x8B,	.name = "drop_green_prio_1", },
-	{ .offset = 0x8C,	.name = "drop_green_prio_2", },
-	{ .offset = 0x8D,	.name = "drop_green_prio_3", },
-	{ .offset = 0x8E,	.name = "drop_green_prio_4", },
-	{ .offset = 0x8F,	.name = "drop_green_prio_5", },
-	{ .offset = 0x90,	.name = "drop_green_prio_6", },
-	{ .offset = 0x91,	.name = "drop_green_prio_7", },
-	OCELOT_STAT_END
+static const struct ocelot_stat_layout vsc9953_stats_layout[OCELOT_NUM_STATS] = {
+	[OCELOT_STAT_RX_OCTETS] = {
+		.name = "rx_octets",
+		.offset = 0x00,
+	},
+	[OCELOT_STAT_RX_UNICAST] = {
+		.name = "rx_unicast",
+		.offset = 0x01,
+	},
+	[OCELOT_STAT_RX_MULTICAST] = {
+		.name = "rx_multicast",
+		.offset = 0x02,
+	},
+	[OCELOT_STAT_RX_BROADCAST] = {
+		.name = "rx_broadcast",
+		.offset = 0x03,
+	},
+	[OCELOT_STAT_RX_SHORTS] = {
+		.name = "rx_shorts",
+		.offset = 0x04,
+	},
+	[OCELOT_STAT_RX_FRAGMENTS] = {
+		.name = "rx_fragments",
+		.offset = 0x05,
+	},
+	[OCELOT_STAT_RX_JABBERS] = {
+		.name = "rx_jabbers",
+		.offset = 0x06,
+	},
+	[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
+		.name = "rx_crc_align_errs",
+		.offset = 0x07,
+	},
+	[OCELOT_STAT_RX_SYM_ERRS] = {
+		.name = "rx_sym_errs",
+		.offset = 0x08,
+	},
+	[OCELOT_STAT_RX_64] = {
+		.name = "rx_frames_below_65_octets",
+		.offset = 0x09,
+	},
+	[OCELOT_STAT_RX_65_127] = {
+		.name = "rx_frames_65_to_127_octets",
+		.offset = 0x0A,
+	},
+	[OCELOT_STAT_RX_128_255] = {
+		.name = "rx_frames_128_to_255_octets",
+		.offset = 0x0B,
+	},
+	[OCELOT_STAT_RX_256_511] = {
+		.name = "rx_frames_256_to_511_octets",
+		.offset = 0x0C,
+	},
+	[OCELOT_STAT_RX_512_1023] = {
+		.name = "rx_frames_512_to_1023_octets",
+		.offset = 0x0D,
+	},
+	[OCELOT_STAT_RX_1024_1526] = {
+		.name = "rx_frames_1024_to_1526_octets",
+		.offset = 0x0E,
+	},
+	[OCELOT_STAT_RX_1527_MAX] = {
+		.name = "rx_frames_over_1526_octets",
+		.offset = 0x0F,
+	},
+	[OCELOT_STAT_RX_PAUSE] = {
+		.name = "rx_pause",
+		.offset = 0x10,
+	},
+	[OCELOT_STAT_RX_CONTROL] = {
+		.name = "rx_control",
+		.offset = 0x11,
+	},
+	[OCELOT_STAT_RX_LONGS] = {
+		.name = "rx_longs",
+		.offset = 0x12,
+	},
+	[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
+		.name = "rx_classified_drops",
+		.offset = 0x13,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_0] = {
+		.name = "rx_red_prio_0",
+		.offset = 0x14,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_1] = {
+		.name = "rx_red_prio_1",
+		.offset = 0x15,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_2] = {
+		.name = "rx_red_prio_2",
+		.offset = 0x16,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_3] = {
+		.name = "rx_red_prio_3",
+		.offset = 0x17,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_4] = {
+		.name = "rx_red_prio_4",
+		.offset = 0x18,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_5] = {
+		.name = "rx_red_prio_5",
+		.offset = 0x19,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_6] = {
+		.name = "rx_red_prio_6",
+		.offset = 0x1A,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_7] = {
+		.name = "rx_red_prio_7",
+		.offset = 0x1B,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
+		.name = "rx_yellow_prio_0",
+		.offset = 0x1C,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
+		.name = "rx_yellow_prio_1",
+		.offset = 0x1D,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
+		.name = "rx_yellow_prio_2",
+		.offset = 0x1E,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
+		.name = "rx_yellow_prio_3",
+		.offset = 0x1F,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
+		.name = "rx_yellow_prio_4",
+		.offset = 0x20,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
+		.name = "rx_yellow_prio_5",
+		.offset = 0x21,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
+		.name = "rx_yellow_prio_6",
+		.offset = 0x22,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
+		.name = "rx_yellow_prio_7",
+		.offset = 0x23,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_0] = {
+		.name = "rx_green_prio_0",
+		.offset = 0x24,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_1] = {
+		.name = "rx_green_prio_1",
+		.offset = 0x25,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_2] = {
+		.name = "rx_green_prio_2",
+		.offset = 0x26,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_3] = {
+		.name = "rx_green_prio_3",
+		.offset = 0x27,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_4] = {
+		.name = "rx_green_prio_4",
+		.offset = 0x28,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_5] = {
+		.name = "rx_green_prio_5",
+		.offset = 0x29,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_6] = {
+		.name = "rx_green_prio_6",
+		.offset = 0x2A,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_7] = {
+		.name = "rx_green_prio_7",
+		.offset = 0x2B,
+	},
+	[OCELOT_STAT_TX_OCTETS] = {
+		.name = "tx_octets",
+		.offset = 0x40,
+	},
+	[OCELOT_STAT_TX_UNICAST] = {
+		.name = "tx_unicast",
+		.offset = 0x41,
+	},
+	[OCELOT_STAT_TX_MULTICAST] = {
+		.name = "tx_multicast",
+		.offset = 0x42,
+	},
+	[OCELOT_STAT_TX_BROADCAST] = {
+		.name = "tx_broadcast",
+		.offset = 0x43,
+	},
+	[OCELOT_STAT_TX_COLLISION] = {
+		.name = "tx_collision",
+		.offset = 0x44,
+	},
+	[OCELOT_STAT_TX_DROPS] = {
+		.name = "tx_drops",
+		.offset = 0x45,
+	},
+	[OCELOT_STAT_TX_PAUSE] = {
+		.name = "tx_pause",
+		.offset = 0x46,
+	},
+	[OCELOT_STAT_TX_64] = {
+		.name = "tx_frames_below_65_octets",
+		.offset = 0x47,
+	},
+	[OCELOT_STAT_TX_65_127] = {
+		.name = "tx_frames_65_to_127_octets",
+		.offset = 0x48,
+	},
+	[OCELOT_STAT_TX_128_255] = {
+		.name = "tx_frames_128_255_octets",
+		.offset = 0x49,
+	},
+	[OCELOT_STAT_TX_256_511] = {
+		.name = "tx_frames_256_511_octets",
+		.offset = 0x4A,
+	},
+	[OCELOT_STAT_TX_512_1023] = {
+		.name = "tx_frames_512_1023_octets",
+		.offset = 0x4B,
+	},
+	[OCELOT_STAT_TX_1024_1526] = {
+		.name = "tx_frames_1024_1526_octets",
+		.offset = 0x4C,
+	},
+	[OCELOT_STAT_TX_1527_MAX] = {
+		.name = "tx_frames_over_1526_octets",
+		.offset = 0x4D,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
+		.name = "tx_yellow_prio_0",
+		.offset = 0x4E,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
+		.name = "tx_yellow_prio_1",
+		.offset = 0x4F,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
+		.name = "tx_yellow_prio_2",
+		.offset = 0x50,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
+		.name = "tx_yellow_prio_3",
+		.offset = 0x51,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
+		.name = "tx_yellow_prio_4",
+		.offset = 0x52,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
+		.name = "tx_yellow_prio_5",
+		.offset = 0x53,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
+		.name = "tx_yellow_prio_6",
+		.offset = 0x54,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
+		.name = "tx_yellow_prio_7",
+		.offset = 0x55,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_0] = {
+		.name = "tx_green_prio_0",
+		.offset = 0x56,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_1] = {
+		.name = "tx_green_prio_1",
+		.offset = 0x57,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_2] = {
+		.name = "tx_green_prio_2",
+		.offset = 0x58,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_3] = {
+		.name = "tx_green_prio_3",
+		.offset = 0x59,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_4] = {
+		.name = "tx_green_prio_4",
+		.offset = 0x5A,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_5] = {
+		.name = "tx_green_prio_5",
+		.offset = 0x5B,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_6] = {
+		.name = "tx_green_prio_6",
+		.offset = 0x5C,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_7] = {
+		.name = "tx_green_prio_7",
+		.offset = 0x5D,
+	},
+	[OCELOT_STAT_TX_AGED] = {
+		.name = "tx_aged",
+		.offset = 0x5E,
+	},
+	[OCELOT_STAT_DROP_LOCAL] = {
+		.name = "drop_local",
+		.offset = 0x80,
+	},
+	[OCELOT_STAT_DROP_TAIL] = {
+		.name = "drop_tail",
+		.offset = 0x81,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
+		.name = "drop_yellow_prio_0",
+		.offset = 0x82,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
+		.name = "drop_yellow_prio_1",
+		.offset = 0x83,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
+		.name = "drop_yellow_prio_2",
+		.offset = 0x84,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
+		.name = "drop_yellow_prio_3",
+		.offset = 0x85,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
+		.name = "drop_yellow_prio_4",
+		.offset = 0x86,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
+		.name = "drop_yellow_prio_5",
+		.offset = 0x87,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
+		.name = "drop_yellow_prio_6",
+		.offset = 0x88,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
+		.name = "drop_yellow_prio_7",
+		.offset = 0x89,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
+		.name = "drop_green_prio_0",
+		.offset = 0x8A,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
+		.name = "drop_green_prio_1",
+		.offset = 0x8B,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
+		.name = "drop_green_prio_2",
+		.offset = 0x8C,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
+		.name = "drop_green_prio_3",
+		.offset = 0x8D,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
+		.name = "drop_green_prio_4",
+		.offset = 0x8E,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
+		.name = "drop_green_prio_5",
+		.offset = 0x8F,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
+		.name = "drop_green_prio_6",
+		.offset = 0x90,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
+		.name = "drop_green_prio_7",
+		.offset = 0x91,
+	},
 };
 
 static const struct vcap_field vsc9953_vcap_es0_keys[] = {
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index c67f162f8ab5..68991b021c56 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1860,16 +1860,20 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
 	if (sset != ETH_SS_STATS)
 		return;
 
-	for (i = 0; i < ocelot->num_stats; i++)
+	for (i = 0; i < OCELOT_NUM_STATS; i++) {
+		if (ocelot->stats_layout[i].name[0] == '\0')
+			continue;
+
 		memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name,
 		       ETH_GSTRING_LEN);
+	}
 }
 EXPORT_SYMBOL(ocelot_get_strings);
 
 /* Caller must hold &ocelot->stats_lock */
 static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
 {
-	unsigned int idx = port * ocelot->num_stats;
+	unsigned int idx = port * OCELOT_NUM_STATS;
 	struct ocelot_stats_region *region;
 	int err, j;
 
@@ -1930,9 +1934,15 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
 	/* check and update now */
 	err = ocelot_port_update_stats(ocelot, port);
 
-	/* Copy all counters */
-	for (i = 0; i < ocelot->num_stats; i++)
-		*data++ = ocelot->stats[port * ocelot->num_stats + i];
+	/* Copy all supported counters */
+	for (i = 0; i < OCELOT_NUM_STATS; i++) {
+		int index = port * OCELOT_NUM_STATS + i;
+
+		if (ocelot->stats_layout[i].name[0] == '\0')
+			continue;
+
+		*data++ = ocelot->stats[index];
+	}
 
 	spin_unlock(&ocelot->stats_lock);
 
@@ -1943,10 +1953,16 @@ EXPORT_SYMBOL(ocelot_get_ethtool_stats);
 
 int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
 {
+	int i, num_stats = 0;
+
 	if (sset != ETH_SS_STATS)
 		return -EOPNOTSUPP;
 
-	return ocelot->num_stats;
+	for (i = 0; i < OCELOT_NUM_STATS; i++)
+		if (ocelot->stats_layout[i].name[0] != '\0')
+			num_stats++;
+
+	return num_stats;
 }
 EXPORT_SYMBOL(ocelot_get_sset_count);
 
@@ -1958,7 +1974,10 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
 
 	INIT_LIST_HEAD(&ocelot->stats_regions);
 
-	for (i = 0; i < ocelot->num_stats; i++) {
+	for (i = 0; i < OCELOT_NUM_STATS; i++) {
+		if (ocelot->stats_layout[i].name[0] == '\0')
+			continue;
+
 		if (region && ocelot->stats_layout[i].offset == last + 1) {
 			region->count++;
 		} else {
@@ -3340,7 +3359,6 @@ static void ocelot_detect_features(struct ocelot *ocelot)
 
 int ocelot_init(struct ocelot *ocelot)
 {
-	const struct ocelot_stat_layout *stat;
 	char queue_name[32];
 	int i, ret;
 	u32 port;
@@ -3353,12 +3371,8 @@ int ocelot_init(struct ocelot *ocelot)
 		}
 	}
 
-	ocelot->num_stats = 0;
-	for_each_stat(ocelot, stat)
-		ocelot->num_stats++;
-
 	ocelot->stats = devm_kcalloc(ocelot->dev,
-				     ocelot->num_phys_ports * ocelot->num_stats,
+				     ocelot->num_phys_ports * OCELOT_NUM_STATS,
 				     sizeof(u64), GFP_KERNEL);
 	if (!ocelot->stats)
 		return -ENOMEM;
diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
index 961f803aca19..9ff910560043 100644
--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
@@ -96,101 +96,379 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = {
 	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4),
 };
 
-static const struct ocelot_stat_layout ocelot_stats_layout[] = {
-	{ .name = "rx_octets", .offset = 0x00, },
-	{ .name = "rx_unicast", .offset = 0x01, },
-	{ .name = "rx_multicast", .offset = 0x02, },
-	{ .name = "rx_broadcast", .offset = 0x03, },
-	{ .name = "rx_shorts", .offset = 0x04, },
-	{ .name = "rx_fragments", .offset = 0x05, },
-	{ .name = "rx_jabbers", .offset = 0x06, },
-	{ .name = "rx_crc_align_errs", .offset = 0x07, },
-	{ .name = "rx_sym_errs", .offset = 0x08, },
-	{ .name = "rx_frames_below_65_octets", .offset = 0x09, },
-	{ .name = "rx_frames_65_to_127_octets", .offset = 0x0A, },
-	{ .name = "rx_frames_128_to_255_octets", .offset = 0x0B, },
-	{ .name = "rx_frames_256_to_511_octets", .offset = 0x0C, },
-	{ .name = "rx_frames_512_to_1023_octets", .offset = 0x0D, },
-	{ .name = "rx_frames_1024_to_1526_octets", .offset = 0x0E, },
-	{ .name = "rx_frames_over_1526_octets", .offset = 0x0F, },
-	{ .name = "rx_pause", .offset = 0x10, },
-	{ .name = "rx_control", .offset = 0x11, },
-	{ .name = "rx_longs", .offset = 0x12, },
-	{ .name = "rx_classified_drops", .offset = 0x13, },
-	{ .name = "rx_red_prio_0", .offset = 0x14, },
-	{ .name = "rx_red_prio_1", .offset = 0x15, },
-	{ .name = "rx_red_prio_2", .offset = 0x16, },
-	{ .name = "rx_red_prio_3", .offset = 0x17, },
-	{ .name = "rx_red_prio_4", .offset = 0x18, },
-	{ .name = "rx_red_prio_5", .offset = 0x19, },
-	{ .name = "rx_red_prio_6", .offset = 0x1A, },
-	{ .name = "rx_red_prio_7", .offset = 0x1B, },
-	{ .name = "rx_yellow_prio_0", .offset = 0x1C, },
-	{ .name = "rx_yellow_prio_1", .offset = 0x1D, },
-	{ .name = "rx_yellow_prio_2", .offset = 0x1E, },
-	{ .name = "rx_yellow_prio_3", .offset = 0x1F, },
-	{ .name = "rx_yellow_prio_4", .offset = 0x20, },
-	{ .name = "rx_yellow_prio_5", .offset = 0x21, },
-	{ .name = "rx_yellow_prio_6", .offset = 0x22, },
-	{ .name = "rx_yellow_prio_7", .offset = 0x23, },
-	{ .name = "rx_green_prio_0", .offset = 0x24, },
-	{ .name = "rx_green_prio_1", .offset = 0x25, },
-	{ .name = "rx_green_prio_2", .offset = 0x26, },
-	{ .name = "rx_green_prio_3", .offset = 0x27, },
-	{ .name = "rx_green_prio_4", .offset = 0x28, },
-	{ .name = "rx_green_prio_5", .offset = 0x29, },
-	{ .name = "rx_green_prio_6", .offset = 0x2A, },
-	{ .name = "rx_green_prio_7", .offset = 0x2B, },
-	{ .name = "tx_octets", .offset = 0x40, },
-	{ .name = "tx_unicast", .offset = 0x41, },
-	{ .name = "tx_multicast", .offset = 0x42, },
-	{ .name = "tx_broadcast", .offset = 0x43, },
-	{ .name = "tx_collision", .offset = 0x44, },
-	{ .name = "tx_drops", .offset = 0x45, },
-	{ .name = "tx_pause", .offset = 0x46, },
-	{ .name = "tx_frames_below_65_octets", .offset = 0x47, },
-	{ .name = "tx_frames_65_to_127_octets", .offset = 0x48, },
-	{ .name = "tx_frames_128_255_octets", .offset = 0x49, },
-	{ .name = "tx_frames_256_511_octets", .offset = 0x4A, },
-	{ .name = "tx_frames_512_1023_octets", .offset = 0x4B, },
-	{ .name = "tx_frames_1024_1526_octets", .offset = 0x4C, },
-	{ .name = "tx_frames_over_1526_octets", .offset = 0x4D, },
-	{ .name = "tx_yellow_prio_0", .offset = 0x4E, },
-	{ .name = "tx_yellow_prio_1", .offset = 0x4F, },
-	{ .name = "tx_yellow_prio_2", .offset = 0x50, },
-	{ .name = "tx_yellow_prio_3", .offset = 0x51, },
-	{ .name = "tx_yellow_prio_4", .offset = 0x52, },
-	{ .name = "tx_yellow_prio_5", .offset = 0x53, },
-	{ .name = "tx_yellow_prio_6", .offset = 0x54, },
-	{ .name = "tx_yellow_prio_7", .offset = 0x55, },
-	{ .name = "tx_green_prio_0", .offset = 0x56, },
-	{ .name = "tx_green_prio_1", .offset = 0x57, },
-	{ .name = "tx_green_prio_2", .offset = 0x58, },
-	{ .name = "tx_green_prio_3", .offset = 0x59, },
-	{ .name = "tx_green_prio_4", .offset = 0x5A, },
-	{ .name = "tx_green_prio_5", .offset = 0x5B, },
-	{ .name = "tx_green_prio_6", .offset = 0x5C, },
-	{ .name = "tx_green_prio_7", .offset = 0x5D, },
-	{ .name = "tx_aged", .offset = 0x5E, },
-	{ .name = "drop_local", .offset = 0x80, },
-	{ .name = "drop_tail", .offset = 0x81, },
-	{ .name = "drop_yellow_prio_0", .offset = 0x82, },
-	{ .name = "drop_yellow_prio_1", .offset = 0x83, },
-	{ .name = "drop_yellow_prio_2", .offset = 0x84, },
-	{ .name = "drop_yellow_prio_3", .offset = 0x85, },
-	{ .name = "drop_yellow_prio_4", .offset = 0x86, },
-	{ .name = "drop_yellow_prio_5", .offset = 0x87, },
-	{ .name = "drop_yellow_prio_6", .offset = 0x88, },
-	{ .name = "drop_yellow_prio_7", .offset = 0x89, },
-	{ .name = "drop_green_prio_0", .offset = 0x8A, },
-	{ .name = "drop_green_prio_1", .offset = 0x8B, },
-	{ .name = "drop_green_prio_2", .offset = 0x8C, },
-	{ .name = "drop_green_prio_3", .offset = 0x8D, },
-	{ .name = "drop_green_prio_4", .offset = 0x8E, },
-	{ .name = "drop_green_prio_5", .offset = 0x8F, },
-	{ .name = "drop_green_prio_6", .offset = 0x90, },
-	{ .name = "drop_green_prio_7", .offset = 0x91, },
-	OCELOT_STAT_END
+static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
+	[OCELOT_STAT_RX_OCTETS] = {
+		.name = "rx_octets",
+		.offset = 0x00,
+	},
+	[OCELOT_STAT_RX_UNICAST] = {
+		.name = "rx_unicast",
+		.offset = 0x01,
+	},
+	[OCELOT_STAT_RX_MULTICAST] = {
+		.name = "rx_multicast",
+		.offset = 0x02,
+	},
+	[OCELOT_STAT_RX_BROADCAST] = {
+		.name = "rx_broadcast",
+		.offset = 0x03,
+	},
+	[OCELOT_STAT_RX_SHORTS] = {
+		.name = "rx_shorts",
+		.offset = 0x04,
+	},
+	[OCELOT_STAT_RX_FRAGMENTS] = {
+		.name = "rx_fragments",
+		.offset = 0x05,
+	},
+	[OCELOT_STAT_RX_JABBERS] = {
+		.name = "rx_jabbers",
+		.offset = 0x06,
+	},
+	[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
+		.name = "rx_crc_align_errs",
+		.offset = 0x07,
+	},
+	[OCELOT_STAT_RX_SYM_ERRS] = {
+		.name = "rx_sym_errs",
+		.offset = 0x08,
+	},
+	[OCELOT_STAT_RX_64] = {
+		.name = "rx_frames_below_65_octets",
+		.offset = 0x09,
+	},
+	[OCELOT_STAT_RX_65_127] = {
+		.name = "rx_frames_65_to_127_octets",
+		.offset = 0x0A,
+	},
+	[OCELOT_STAT_RX_128_255] = {
+		.name = "rx_frames_128_to_255_octets",
+		.offset = 0x0B,
+	},
+	[OCELOT_STAT_RX_256_511] = {
+		.name = "rx_frames_256_to_511_octets",
+		.offset = 0x0C,
+	},
+	[OCELOT_STAT_RX_512_1023] = {
+		.name = "rx_frames_512_to_1023_octets",
+		.offset = 0x0D,
+	},
+	[OCELOT_STAT_RX_1024_1526] = {
+		.name = "rx_frames_1024_to_1526_octets",
+		.offset = 0x0E,
+	},
+	[OCELOT_STAT_RX_1527_MAX] = {
+		.name = "rx_frames_over_1526_octets",
+		.offset = 0x0F,
+	},
+	[OCELOT_STAT_RX_PAUSE] = {
+		.name = "rx_pause",
+		.offset = 0x10,
+	},
+	[OCELOT_STAT_RX_CONTROL] = {
+		.name = "rx_control",
+		.offset = 0x11,
+	},
+	[OCELOT_STAT_RX_LONGS] = {
+		.name = "rx_longs",
+		.offset = 0x12,
+	},
+	[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
+		.name = "rx_classified_drops",
+		.offset = 0x13,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_0] = {
+		.name = "rx_red_prio_0",
+		.offset = 0x14,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_1] = {
+		.name = "rx_red_prio_1",
+		.offset = 0x15,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_2] = {
+		.name = "rx_red_prio_2",
+		.offset = 0x16,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_3] = {
+		.name = "rx_red_prio_3",
+		.offset = 0x17,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_4] = {
+		.name = "rx_red_prio_4",
+		.offset = 0x18,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_5] = {
+		.name = "rx_red_prio_5",
+		.offset = 0x19,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_6] = {
+		.name = "rx_red_prio_6",
+		.offset = 0x1A,
+	},
+	[OCELOT_STAT_RX_RED_PRIO_7] = {
+		.name = "rx_red_prio_7",
+		.offset = 0x1B,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
+		.name = "rx_yellow_prio_0",
+		.offset = 0x1C,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
+		.name = "rx_yellow_prio_1",
+		.offset = 0x1D,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
+		.name = "rx_yellow_prio_2",
+		.offset = 0x1E,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
+		.name = "rx_yellow_prio_3",
+		.offset = 0x1F,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
+		.name = "rx_yellow_prio_4",
+		.offset = 0x20,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
+		.name = "rx_yellow_prio_5",
+		.offset = 0x21,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
+		.name = "rx_yellow_prio_6",
+		.offset = 0x22,
+	},
+	[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
+		.name = "rx_yellow_prio_7",
+		.offset = 0x23,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_0] = {
+		.name = "rx_green_prio_0",
+		.offset = 0x24,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_1] = {
+		.name = "rx_green_prio_1",
+		.offset = 0x25,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_2] = {
+		.name = "rx_green_prio_2",
+		.offset = 0x26,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_3] = {
+		.name = "rx_green_prio_3",
+		.offset = 0x27,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_4] = {
+		.name = "rx_green_prio_4",
+		.offset = 0x28,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_5] = {
+		.name = "rx_green_prio_5",
+		.offset = 0x29,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_6] = {
+		.name = "rx_green_prio_6",
+		.offset = 0x2A,
+	},
+	[OCELOT_STAT_RX_GREEN_PRIO_7] = {
+		.name = "rx_green_prio_7",
+		.offset = 0x2B,
+	},
+	[OCELOT_STAT_TX_OCTETS] = {
+		.name = "tx_octets",
+		.offset = 0x40,
+	},
+	[OCELOT_STAT_TX_UNICAST] = {
+		.name = "tx_unicast",
+		.offset = 0x41,
+	},
+	[OCELOT_STAT_TX_MULTICAST] = {
+		.name = "tx_multicast",
+		.offset = 0x42,
+	},
+	[OCELOT_STAT_TX_BROADCAST] = {
+		.name = "tx_broadcast",
+		.offset = 0x43,
+	},
+	[OCELOT_STAT_TX_COLLISION] = {
+		.name = "tx_collision",
+		.offset = 0x44,
+	},
+	[OCELOT_STAT_TX_DROPS] = {
+		.name = "tx_drops",
+		.offset = 0x45,
+	},
+	[OCELOT_STAT_TX_PAUSE] = {
+		.name = "tx_pause",
+		.offset = 0x46,
+	},
+	[OCELOT_STAT_TX_64] = {
+		.name = "tx_frames_below_65_octets",
+		.offset = 0x47,
+	},
+	[OCELOT_STAT_TX_65_127] = {
+		.name = "tx_frames_65_to_127_octets",
+		.offset = 0x48,
+	},
+	[OCELOT_STAT_TX_128_255] = {
+		.name = "tx_frames_128_255_octets",
+		.offset = 0x49,
+	},
+	[OCELOT_STAT_TX_256_511] = {
+		.name = "tx_frames_256_511_octets",
+		.offset = 0x4A,
+	},
+	[OCELOT_STAT_TX_512_1023] = {
+		.name = "tx_frames_512_1023_octets",
+		.offset = 0x4B,
+	},
+	[OCELOT_STAT_TX_1024_1526] = {
+		.name = "tx_frames_1024_1526_octets",
+		.offset = 0x4C,
+	},
+	[OCELOT_STAT_TX_1527_MAX] = {
+		.name = "tx_frames_over_1526_octets",
+		.offset = 0x4D,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
+		.name = "tx_yellow_prio_0",
+		.offset = 0x4E,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
+		.name = "tx_yellow_prio_1",
+		.offset = 0x4F,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
+		.name = "tx_yellow_prio_2",
+		.offset = 0x50,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
+		.name = "tx_yellow_prio_3",
+		.offset = 0x51,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
+		.name = "tx_yellow_prio_4",
+		.offset = 0x52,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
+		.name = "tx_yellow_prio_5",
+		.offset = 0x53,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
+		.name = "tx_yellow_prio_6",
+		.offset = 0x54,
+	},
+	[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
+		.name = "tx_yellow_prio_7",
+		.offset = 0x55,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_0] = {
+		.name = "tx_green_prio_0",
+		.offset = 0x56,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_1] = {
+		.name = "tx_green_prio_1",
+		.offset = 0x57,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_2] = {
+		.name = "tx_green_prio_2",
+		.offset = 0x58,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_3] = {
+		.name = "tx_green_prio_3",
+		.offset = 0x59,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_4] = {
+		.name = "tx_green_prio_4",
+		.offset = 0x5A,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_5] = {
+		.name = "tx_green_prio_5",
+		.offset = 0x5B,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_6] = {
+		.name = "tx_green_prio_6",
+		.offset = 0x5C,
+	},
+	[OCELOT_STAT_TX_GREEN_PRIO_7] = {
+		.name = "tx_green_prio_7",
+		.offset = 0x5D,
+	},
+	[OCELOT_STAT_TX_AGED] = {
+		.name = "tx_aged",
+		.offset = 0x5E,
+	},
+	[OCELOT_STAT_DROP_LOCAL] = {
+		.name = "drop_local",
+		.offset = 0x80,
+	},
+	[OCELOT_STAT_DROP_TAIL] = {
+		.name = "drop_tail",
+		.offset = 0x81,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
+		.name = "drop_yellow_prio_0",
+		.offset = 0x82,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
+		.name = "drop_yellow_prio_1",
+		.offset = 0x83,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
+		.name = "drop_yellow_prio_2",
+		.offset = 0x84,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
+		.name = "drop_yellow_prio_3",
+		.offset = 0x85,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
+		.name = "drop_yellow_prio_4",
+		.offset = 0x86,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
+		.name = "drop_yellow_prio_5",
+		.offset = 0x87,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
+		.name = "drop_yellow_prio_6",
+		.offset = 0x88,
+	},
+	[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
+		.name = "drop_yellow_prio_7",
+		.offset = 0x89,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
+		.name = "drop_green_prio_0",
+		.offset = 0x8A,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
+		.name = "drop_green_prio_1",
+		.offset = 0x8B,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
+		.name = "drop_green_prio_2",
+		.offset = 0x8C,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
+		.name = "drop_green_prio_3",
+		.offset = 0x8D,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
+		.name = "drop_green_prio_4",
+		.offset = 0x8E,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
+		.name = "drop_green_prio_5",
+		.offset = 0x8F,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
+		.name = "drop_green_prio_6",
+		.offset = 0x90,
+	},
+	[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
+		.name = "drop_green_prio_7",
+		.offset = 0x91,
+	},
 };
 
 static void ocelot_pll5_init(struct ocelot *ocelot)
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 72b9474391da..2428bc64cb1d 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -105,11 +105,6 @@
 #define REG_RESERVED_ADDR		0xffffffff
 #define REG_RESERVED(reg)		REG(reg, REG_RESERVED_ADDR)
 
-#define for_each_stat(ocelot, stat)				\
-	for ((stat) = (ocelot)->stats_layout;			\
-	     ((stat)->name[0] != '\0');				\
-	     (stat)++)
-
 enum ocelot_target {
 	ANA = 1,
 	QS,
@@ -540,13 +535,108 @@ enum ocelot_ptp_pins {
 	TOD_ACC_PIN
 };
 
+enum ocelot_stat {
+	OCELOT_STAT_RX_OCTETS,
+	OCELOT_STAT_RX_UNICAST,
+	OCELOT_STAT_RX_MULTICAST,
+	OCELOT_STAT_RX_BROADCAST,
+	OCELOT_STAT_RX_SHORTS,
+	OCELOT_STAT_RX_FRAGMENTS,
+	OCELOT_STAT_RX_JABBERS,
+	OCELOT_STAT_RX_CRC_ALIGN_ERRS,
+	OCELOT_STAT_RX_SYM_ERRS,
+	OCELOT_STAT_RX_64,
+	OCELOT_STAT_RX_65_127,
+	OCELOT_STAT_RX_128_255,
+	OCELOT_STAT_RX_256_511,
+	OCELOT_STAT_RX_512_1023,
+	OCELOT_STAT_RX_1024_1526,
+	OCELOT_STAT_RX_1527_MAX,
+	OCELOT_STAT_RX_PAUSE,
+	OCELOT_STAT_RX_CONTROL,
+	OCELOT_STAT_RX_LONGS,
+	OCELOT_STAT_RX_CLASSIFIED_DROPS,
+	OCELOT_STAT_RX_RED_PRIO_0,
+	OCELOT_STAT_RX_RED_PRIO_1,
+	OCELOT_STAT_RX_RED_PRIO_2,
+	OCELOT_STAT_RX_RED_PRIO_3,
+	OCELOT_STAT_RX_RED_PRIO_4,
+	OCELOT_STAT_RX_RED_PRIO_5,
+	OCELOT_STAT_RX_RED_PRIO_6,
+	OCELOT_STAT_RX_RED_PRIO_7,
+	OCELOT_STAT_RX_YELLOW_PRIO_0,
+	OCELOT_STAT_RX_YELLOW_PRIO_1,
+	OCELOT_STAT_RX_YELLOW_PRIO_2,
+	OCELOT_STAT_RX_YELLOW_PRIO_3,
+	OCELOT_STAT_RX_YELLOW_PRIO_4,
+	OCELOT_STAT_RX_YELLOW_PRIO_5,
+	OCELOT_STAT_RX_YELLOW_PRIO_6,
+	OCELOT_STAT_RX_YELLOW_PRIO_7,
+	OCELOT_STAT_RX_GREEN_PRIO_0,
+	OCELOT_STAT_RX_GREEN_PRIO_1,
+	OCELOT_STAT_RX_GREEN_PRIO_2,
+	OCELOT_STAT_RX_GREEN_PRIO_3,
+	OCELOT_STAT_RX_GREEN_PRIO_4,
+	OCELOT_STAT_RX_GREEN_PRIO_5,
+	OCELOT_STAT_RX_GREEN_PRIO_6,
+	OCELOT_STAT_RX_GREEN_PRIO_7,
+	OCELOT_STAT_TX_OCTETS,
+	OCELOT_STAT_TX_UNICAST,
+	OCELOT_STAT_TX_MULTICAST,
+	OCELOT_STAT_TX_BROADCAST,
+	OCELOT_STAT_TX_COLLISION,
+	OCELOT_STAT_TX_DROPS,
+	OCELOT_STAT_TX_PAUSE,
+	OCELOT_STAT_TX_64,
+	OCELOT_STAT_TX_65_127,
+	OCELOT_STAT_TX_128_255,
+	OCELOT_STAT_TX_256_511,
+	OCELOT_STAT_TX_512_1023,
+	OCELOT_STAT_TX_1024_1526,
+	OCELOT_STAT_TX_1527_MAX,
+	OCELOT_STAT_TX_YELLOW_PRIO_0,
+	OCELOT_STAT_TX_YELLOW_PRIO_1,
+	OCELOT_STAT_TX_YELLOW_PRIO_2,
+	OCELOT_STAT_TX_YELLOW_PRIO_3,
+	OCELOT_STAT_TX_YELLOW_PRIO_4,
+	OCELOT_STAT_TX_YELLOW_PRIO_5,
+	OCELOT_STAT_TX_YELLOW_PRIO_6,
+	OCELOT_STAT_TX_YELLOW_PRIO_7,
+	OCELOT_STAT_TX_GREEN_PRIO_0,
+	OCELOT_STAT_TX_GREEN_PRIO_1,
+	OCELOT_STAT_TX_GREEN_PRIO_2,
+	OCELOT_STAT_TX_GREEN_PRIO_3,
+	OCELOT_STAT_TX_GREEN_PRIO_4,
+	OCELOT_STAT_TX_GREEN_PRIO_5,
+	OCELOT_STAT_TX_GREEN_PRIO_6,
+	OCELOT_STAT_TX_GREEN_PRIO_7,
+	OCELOT_STAT_TX_AGED,
+	OCELOT_STAT_DROP_LOCAL,
+	OCELOT_STAT_DROP_TAIL,
+	OCELOT_STAT_DROP_YELLOW_PRIO_0,
+	OCELOT_STAT_DROP_YELLOW_PRIO_1,
+	OCELOT_STAT_DROP_YELLOW_PRIO_2,
+	OCELOT_STAT_DROP_YELLOW_PRIO_3,
+	OCELOT_STAT_DROP_YELLOW_PRIO_4,
+	OCELOT_STAT_DROP_YELLOW_PRIO_5,
+	OCELOT_STAT_DROP_YELLOW_PRIO_6,
+	OCELOT_STAT_DROP_YELLOW_PRIO_7,
+	OCELOT_STAT_DROP_GREEN_PRIO_0,
+	OCELOT_STAT_DROP_GREEN_PRIO_1,
+	OCELOT_STAT_DROP_GREEN_PRIO_2,
+	OCELOT_STAT_DROP_GREEN_PRIO_3,
+	OCELOT_STAT_DROP_GREEN_PRIO_4,
+	OCELOT_STAT_DROP_GREEN_PRIO_5,
+	OCELOT_STAT_DROP_GREEN_PRIO_6,
+	OCELOT_STAT_DROP_GREEN_PRIO_7,
+	OCELOT_NUM_STATS,
+};
+
 struct ocelot_stat_layout {
 	u32 offset;
 	char name[ETH_GSTRING_LEN];
 };
 
-#define OCELOT_STAT_END { .name = "" }
-
 struct ocelot_stats_region {
 	struct list_head node;
 	u32 offset;
@@ -709,7 +799,6 @@ struct ocelot {
 	const u32 *const		*map;
 	const struct ocelot_stat_layout	*stats_layout;
 	struct list_head		stats_regions;
-	unsigned int			num_stats;
 
 	u32				pool_size[OCELOT_SB_NUM][OCELOT_SB_POOL_NUM];
 	int				packet_buffer_size;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 7/8] net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
                   ` (5 preceding siblings ...)
  2022-08-16 13:53 ` [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-16 13:53 ` [PATCH net 8/8] net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats Vladimir Oltean
  2022-08-18  5:20 ` [PATCH net 0/8] Fixes for Ocelot driver statistics patchwork-bot+netdevbpf
  8 siblings, 0 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

With so many counter addresses recently discovered as being wrong, it is
desirable to at least have a central database of information, rather
than two: one through the SYS_COUNT_* registers (used for
ndo_get_stats64), and the other through the offset field of struct
ocelot_stat_layout elements (used for ethtool -S).

The strategy will be to keep the SYS_COUNT_* definitions as the single
source of truth, but for that we need to expand our current definitions
to cover all registers. Then we need to convert the ocelot region
creation logic, and stats worker, to the read semantics imposed by going
through SYS_COUNT_* absolute register addresses, rather than offsets
of 32-bit words relative to SYS_COUNT_RX_OCTETS (which should have been
SYS_CNT, by the way).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c     | 253 ++++++++++++--------
 drivers/net/dsa/ocelot/seville_vsc9953.c   | 255 +++++++++++++--------
 drivers/net/ethernet/mscc/ocelot.c         |  11 +-
 drivers/net/ethernet/mscc/ocelot_vsc7514.c | 186 +++++++--------
 drivers/net/ethernet/mscc/vsc7514_regs.c   |  58 +++++
 include/soc/mscc/ocelot.h                  |  66 +++++-
 6 files changed, 540 insertions(+), 289 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index c9f270f24b1c..1cdce8a98d1d 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -274,10 +274,14 @@ static const u32 vsc9959_rew_regmap[] = {
 
 static const u32 vsc9959_sys_regmap[] = {
 	REG(SYS_COUNT_RX_OCTETS,		0x000000),
+	REG(SYS_COUNT_RX_UNICAST,		0x000004),
 	REG(SYS_COUNT_RX_MULTICAST,		0x000008),
+	REG(SYS_COUNT_RX_BROADCAST,		0x00000c),
 	REG(SYS_COUNT_RX_SHORTS,		0x000010),
 	REG(SYS_COUNT_RX_FRAGMENTS,		0x000014),
 	REG(SYS_COUNT_RX_JABBERS,		0x000018),
+	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,	0x00001c),
+	REG(SYS_COUNT_RX_SYM_ERRS,		0x000020),
 	REG(SYS_COUNT_RX_64,			0x000024),
 	REG(SYS_COUNT_RX_65_127,		0x000028),
 	REG(SYS_COUNT_RX_128_255,		0x00002c),
@@ -288,9 +292,38 @@ static const u32 vsc9959_sys_regmap[] = {
 	REG(SYS_COUNT_RX_PAUSE,			0x000040),
 	REG(SYS_COUNT_RX_CONTROL,		0x000044),
 	REG(SYS_COUNT_RX_LONGS,			0x000048),
+	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,	0x00004c),
+	REG(SYS_COUNT_RX_RED_PRIO_0,		0x000050),
+	REG(SYS_COUNT_RX_RED_PRIO_1,		0x000054),
+	REG(SYS_COUNT_RX_RED_PRIO_2,		0x000058),
+	REG(SYS_COUNT_RX_RED_PRIO_3,		0x00005c),
+	REG(SYS_COUNT_RX_RED_PRIO_4,		0x000060),
+	REG(SYS_COUNT_RX_RED_PRIO_5,		0x000064),
+	REG(SYS_COUNT_RX_RED_PRIO_6,		0x000068),
+	REG(SYS_COUNT_RX_RED_PRIO_7,		0x00006c),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_0,		0x000070),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_1,		0x000074),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_2,		0x000078),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_3,		0x00007c),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_4,		0x000080),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_5,		0x000084),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_6,		0x000088),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_7,		0x00008c),
+	REG(SYS_COUNT_RX_GREEN_PRIO_0,		0x000090),
+	REG(SYS_COUNT_RX_GREEN_PRIO_1,		0x000094),
+	REG(SYS_COUNT_RX_GREEN_PRIO_2,		0x000098),
+	REG(SYS_COUNT_RX_GREEN_PRIO_3,		0x00009c),
+	REG(SYS_COUNT_RX_GREEN_PRIO_4,		0x0000a0),
+	REG(SYS_COUNT_RX_GREEN_PRIO_5,		0x0000a4),
+	REG(SYS_COUNT_RX_GREEN_PRIO_6,		0x0000a8),
+	REG(SYS_COUNT_RX_GREEN_PRIO_7,		0x0000ac),
 	REG(SYS_COUNT_TX_OCTETS,		0x000200),
+	REG(SYS_COUNT_TX_UNICAST,		0x000204),
+	REG(SYS_COUNT_TX_MULTICAST,		0x000208),
+	REG(SYS_COUNT_TX_BROADCAST,		0x00020c),
 	REG(SYS_COUNT_TX_COLLISION,		0x000210),
 	REG(SYS_COUNT_TX_DROPS,			0x000214),
+	REG(SYS_COUNT_TX_PAUSE,			0x000218),
 	REG(SYS_COUNT_TX_64,			0x00021c),
 	REG(SYS_COUNT_TX_65_127,		0x000220),
 	REG(SYS_COUNT_TX_128_255,		0x000224),
@@ -298,7 +331,41 @@ static const u32 vsc9959_sys_regmap[] = {
 	REG(SYS_COUNT_TX_512_1023,		0x00022c),
 	REG(SYS_COUNT_TX_1024_1526,		0x000230),
 	REG(SYS_COUNT_TX_1527_MAX,		0x000234),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_0,		0x000238),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_1,		0x00023c),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_2,		0x000240),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_3,		0x000244),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_4,		0x000248),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_5,		0x00024c),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_6,		0x000250),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_7,		0x000254),
+	REG(SYS_COUNT_TX_GREEN_PRIO_0,		0x000258),
+	REG(SYS_COUNT_TX_GREEN_PRIO_1,		0x00025c),
+	REG(SYS_COUNT_TX_GREEN_PRIO_2,		0x000260),
+	REG(SYS_COUNT_TX_GREEN_PRIO_3,		0x000264),
+	REG(SYS_COUNT_TX_GREEN_PRIO_4,		0x000268),
+	REG(SYS_COUNT_TX_GREEN_PRIO_5,		0x00026c),
+	REG(SYS_COUNT_TX_GREEN_PRIO_6,		0x000270),
+	REG(SYS_COUNT_TX_GREEN_PRIO_7,		0x000274),
 	REG(SYS_COUNT_TX_AGING,			0x000278),
+	REG(SYS_COUNT_DROP_LOCAL,		0x000400),
+	REG(SYS_COUNT_DROP_TAIL,		0x000404),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_0,	0x000408),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_1,	0x00040c),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_2,	0x000410),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_3,	0x000414),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_4,	0x000418),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_5,	0x00041c),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_6,	0x000420),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_7,	0x000424),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_0,	0x000428),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_1,	0x00042c),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_2,	0x000430),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_3,	0x000434),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_4,	0x000438),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_5,	0x00043c),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_6,	0x000440),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_7,	0x000444),
 	REG(SYS_RESET_CFG,			0x000e00),
 	REG(SYS_SR_ETYPE_CFG,			0x000e04),
 	REG(SYS_VLAN_ETYPE_CFG,			0x000e08),
@@ -554,375 +621,375 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = {
 static const struct ocelot_stat_layout vsc9959_stats_layout[OCELOT_NUM_STATS] = {
 	[OCELOT_STAT_RX_OCTETS] = {
 		.name = "rx_octets",
-		.offset = 0x00,
+		.reg = SYS_COUNT_RX_OCTETS,
 	},
 	[OCELOT_STAT_RX_UNICAST] = {
 		.name = "rx_unicast",
-		.offset = 0x01,
+		.reg = SYS_COUNT_RX_UNICAST,
 	},
 	[OCELOT_STAT_RX_MULTICAST] = {
 		.name = "rx_multicast",
-		.offset = 0x02,
+		.reg = SYS_COUNT_RX_MULTICAST,
 	},
 	[OCELOT_STAT_RX_BROADCAST] = {
 		.name = "rx_broadcast",
-		.offset = 0x03,
+		.reg = SYS_COUNT_RX_BROADCAST,
 	},
 	[OCELOT_STAT_RX_SHORTS] = {
 		.name = "rx_shorts",
-		.offset = 0x04,
+		.reg = SYS_COUNT_RX_SHORTS,
 	},
 	[OCELOT_STAT_RX_FRAGMENTS] = {
 		.name = "rx_fragments",
-		.offset = 0x05,
+		.reg = SYS_COUNT_RX_FRAGMENTS,
 	},
 	[OCELOT_STAT_RX_JABBERS] = {
 		.name = "rx_jabbers",
-		.offset = 0x06,
+		.reg = SYS_COUNT_RX_JABBERS,
 	},
 	[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
 		.name = "rx_crc_align_errs",
-		.offset = 0x07,
+		.reg = SYS_COUNT_RX_CRC_ALIGN_ERRS,
 	},
 	[OCELOT_STAT_RX_SYM_ERRS] = {
 		.name = "rx_sym_errs",
-		.offset = 0x08,
+		.reg = SYS_COUNT_RX_SYM_ERRS,
 	},
 	[OCELOT_STAT_RX_64] = {
 		.name = "rx_frames_below_65_octets",
-		.offset = 0x09,
+		.reg = SYS_COUNT_RX_64,
 	},
 	[OCELOT_STAT_RX_65_127] = {
 		.name = "rx_frames_65_to_127_octets",
-		.offset = 0x0A,
+		.reg = SYS_COUNT_RX_65_127,
 	},
 	[OCELOT_STAT_RX_128_255] = {
 		.name = "rx_frames_128_to_255_octets",
-		.offset = 0x0B,
+		.reg = SYS_COUNT_RX_128_255,
 	},
 	[OCELOT_STAT_RX_256_511] = {
 		.name = "rx_frames_256_to_511_octets",
-		.offset = 0x0C,
+		.reg = SYS_COUNT_RX_256_511,
 	},
 	[OCELOT_STAT_RX_512_1023] = {
 		.name = "rx_frames_512_to_1023_octets",
-		.offset = 0x0D,
+		.reg = SYS_COUNT_RX_512_1023,
 	},
 	[OCELOT_STAT_RX_1024_1526] = {
 		.name = "rx_frames_1024_to_1526_octets",
-		.offset = 0x0E,
+		.reg = SYS_COUNT_RX_1024_1526,
 	},
 	[OCELOT_STAT_RX_1527_MAX] = {
 		.name = "rx_frames_over_1526_octets",
-		.offset = 0x0F,
+		.reg = SYS_COUNT_RX_1527_MAX,
 	},
 	[OCELOT_STAT_RX_PAUSE] = {
 		.name = "rx_pause",
-		.offset = 0x10,
+		.reg = SYS_COUNT_RX_PAUSE,
 	},
 	[OCELOT_STAT_RX_CONTROL] = {
 		.name = "rx_control",
-		.offset = 0x11,
+		.reg = SYS_COUNT_RX_CONTROL,
 	},
 	[OCELOT_STAT_RX_LONGS] = {
 		.name = "rx_longs",
-		.offset = 0x12,
+		.reg = SYS_COUNT_RX_LONGS,
 	},
 	[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
 		.name = "rx_classified_drops",
-		.offset = 0x13,
+		.reg = SYS_COUNT_RX_CLASSIFIED_DROPS,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_0] = {
 		.name = "rx_red_prio_0",
-		.offset = 0x14,
+		.reg = SYS_COUNT_RX_RED_PRIO_0,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_1] = {
 		.name = "rx_red_prio_1",
-		.offset = 0x15,
+		.reg = SYS_COUNT_RX_RED_PRIO_1,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_2] = {
 		.name = "rx_red_prio_2",
-		.offset = 0x16,
+		.reg = SYS_COUNT_RX_RED_PRIO_2,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_3] = {
 		.name = "rx_red_prio_3",
-		.offset = 0x17,
+		.reg = SYS_COUNT_RX_RED_PRIO_3,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_4] = {
 		.name = "rx_red_prio_4",
-		.offset = 0x18,
+		.reg = SYS_COUNT_RX_RED_PRIO_4,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_5] = {
 		.name = "rx_red_prio_5",
-		.offset = 0x19,
+		.reg = SYS_COUNT_RX_RED_PRIO_5,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_6] = {
 		.name = "rx_red_prio_6",
-		.offset = 0x1A,
+		.reg = SYS_COUNT_RX_RED_PRIO_6,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_7] = {
 		.name = "rx_red_prio_7",
-		.offset = 0x1B,
+		.reg = SYS_COUNT_RX_RED_PRIO_7,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
 		.name = "rx_yellow_prio_0",
-		.offset = 0x1C,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
 		.name = "rx_yellow_prio_1",
-		.offset = 0x1D,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
 		.name = "rx_yellow_prio_2",
-		.offset = 0x1E,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
 		.name = "rx_yellow_prio_3",
-		.offset = 0x1F,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
 		.name = "rx_yellow_prio_4",
-		.offset = 0x20,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
 		.name = "rx_yellow_prio_5",
-		.offset = 0x21,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
 		.name = "rx_yellow_prio_6",
-		.offset = 0x22,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
 		.name = "rx_yellow_prio_7",
-		.offset = 0x23,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_0] = {
 		.name = "rx_green_prio_0",
-		.offset = 0x24,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_1] = {
 		.name = "rx_green_prio_1",
-		.offset = 0x25,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_2] = {
 		.name = "rx_green_prio_2",
-		.offset = 0x26,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_3] = {
 		.name = "rx_green_prio_3",
-		.offset = 0x27,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_4] = {
 		.name = "rx_green_prio_4",
-		.offset = 0x28,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_5] = {
 		.name = "rx_green_prio_5",
-		.offset = 0x29,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_6] = {
 		.name = "rx_green_prio_6",
-		.offset = 0x2A,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_7] = {
 		.name = "rx_green_prio_7",
-		.offset = 0x2B,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_7,
 	},
 	[OCELOT_STAT_TX_OCTETS] = {
 		.name = "tx_octets",
-		.offset = 0x80,
+		.reg = SYS_COUNT_TX_OCTETS,
 	},
 	[OCELOT_STAT_TX_UNICAST] = {
 		.name = "tx_unicast",
-		.offset = 0x81,
+		.reg = SYS_COUNT_TX_UNICAST,
 	},
 	[OCELOT_STAT_TX_MULTICAST] = {
 		.name = "tx_multicast",
-		.offset = 0x82,
+		.reg = SYS_COUNT_TX_MULTICAST,
 	},
 	[OCELOT_STAT_TX_BROADCAST] = {
 		.name = "tx_broadcast",
-		.offset = 0x83,
+		.reg = SYS_COUNT_TX_BROADCAST,
 	},
 	[OCELOT_STAT_TX_COLLISION] = {
 		.name = "tx_collision",
-		.offset = 0x84,
+		.reg = SYS_COUNT_TX_COLLISION,
 	},
 	[OCELOT_STAT_TX_DROPS] = {
 		.name = "tx_drops",
-		.offset = 0x85,
+		.reg = SYS_COUNT_TX_DROPS,
 	},
 	[OCELOT_STAT_TX_PAUSE] = {
 		.name = "tx_pause",
-		.offset = 0x86,
+		.reg = SYS_COUNT_TX_PAUSE,
 	},
 	[OCELOT_STAT_TX_64] = {
 		.name = "tx_frames_below_65_octets",
-		.offset = 0x87,
+		.reg = SYS_COUNT_TX_64,
 	},
 	[OCELOT_STAT_TX_65_127] = {
 		.name = "tx_frames_65_to_127_octets",
-		.offset = 0x88,
+		.reg = SYS_COUNT_TX_65_127,
 	},
 	[OCELOT_STAT_TX_128_255] = {
 		.name = "tx_frames_128_255_octets",
-		.offset = 0x89,
+		.reg = SYS_COUNT_TX_128_255,
 	},
 	[OCELOT_STAT_TX_256_511] = {
 		.name = "tx_frames_256_511_octets",
-		.offset = 0x8A,
+		.reg = SYS_COUNT_TX_256_511,
 	},
 	[OCELOT_STAT_TX_512_1023] = {
 		.name = "tx_frames_512_1023_octets",
-		.offset = 0x8B,
+		.reg = SYS_COUNT_TX_512_1023,
 	},
 	[OCELOT_STAT_TX_1024_1526] = {
 		.name = "tx_frames_1024_1526_octets",
-		.offset = 0x8C,
+		.reg = SYS_COUNT_TX_1024_1526,
 	},
 	[OCELOT_STAT_TX_1527_MAX] = {
 		.name = "tx_frames_over_1526_octets",
-		.offset = 0x8D,
+		.reg = SYS_COUNT_TX_1527_MAX,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
 		.name = "tx_yellow_prio_0",
-		.offset = 0x8E,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
 		.name = "tx_yellow_prio_1",
-		.offset = 0x8F,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
 		.name = "tx_yellow_prio_2",
-		.offset = 0x90,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
 		.name = "tx_yellow_prio_3",
-		.offset = 0x91,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
 		.name = "tx_yellow_prio_4",
-		.offset = 0x92,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
 		.name = "tx_yellow_prio_5",
-		.offset = 0x93,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
 		.name = "tx_yellow_prio_6",
-		.offset = 0x94,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
 		.name = "tx_yellow_prio_7",
-		.offset = 0x95,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_0] = {
 		.name = "tx_green_prio_0",
-		.offset = 0x96,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_1] = {
 		.name = "tx_green_prio_1",
-		.offset = 0x97,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_2] = {
 		.name = "tx_green_prio_2",
-		.offset = 0x98,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_3] = {
 		.name = "tx_green_prio_3",
-		.offset = 0x99,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_4] = {
 		.name = "tx_green_prio_4",
-		.offset = 0x9A,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_5] = {
 		.name = "tx_green_prio_5",
-		.offset = 0x9B,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_6] = {
 		.name = "tx_green_prio_6",
-		.offset = 0x9C,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_7] = {
 		.name = "tx_green_prio_7",
-		.offset = 0x9D,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_7,
 	},
 	[OCELOT_STAT_TX_AGED] = {
 		.name = "tx_aged",
-		.offset = 0x9E,
+		.reg = SYS_COUNT_TX_AGING,
 	},
 	[OCELOT_STAT_DROP_LOCAL] = {
 		.name = "drop_local",
-		.offset = 0x100,
+		.reg = SYS_COUNT_DROP_LOCAL,
 	},
 	[OCELOT_STAT_DROP_TAIL] = {
 		.name = "drop_tail",
-		.offset = 0x101,
+		.reg = SYS_COUNT_DROP_TAIL,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
 		.name = "drop_yellow_prio_0",
-		.offset = 0x102,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
 		.name = "drop_yellow_prio_1",
-		.offset = 0x103,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
 		.name = "drop_yellow_prio_2",
-		.offset = 0x104,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
 		.name = "drop_yellow_prio_3",
-		.offset = 0x105,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
 		.name = "drop_yellow_prio_4",
-		.offset = 0x106,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
 		.name = "drop_yellow_prio_5",
-		.offset = 0x107,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
 		.name = "drop_yellow_prio_6",
-		.offset = 0x108,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
 		.name = "drop_yellow_prio_7",
-		.offset = 0x109,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
 		.name = "drop_green_prio_0",
-		.offset = 0x10A,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
 		.name = "drop_green_prio_1",
-		.offset = 0x10B,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
 		.name = "drop_green_prio_2",
-		.offset = 0x10C,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
 		.name = "drop_green_prio_3",
-		.offset = 0x10D,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
 		.name = "drop_green_prio_4",
-		.offset = 0x10E,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
 		.name = "drop_green_prio_5",
-		.offset = 0x10F,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
 		.name = "drop_green_prio_6",
-		.offset = 0x110,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
 		.name = "drop_green_prio_7",
-		.offset = 0x111,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_7,
 	},
 };
 
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index fe5d4642d0bc..b34f4cdfe814 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -270,10 +270,14 @@ static const u32 vsc9953_rew_regmap[] = {
 
 static const u32 vsc9953_sys_regmap[] = {
 	REG(SYS_COUNT_RX_OCTETS,		0x000000),
+	REG(SYS_COUNT_RX_UNICAST,		0x000004),
 	REG(SYS_COUNT_RX_MULTICAST,		0x000008),
+	REG(SYS_COUNT_RX_BROADCAST,		0x00000c),
 	REG(SYS_COUNT_RX_SHORTS,		0x000010),
 	REG(SYS_COUNT_RX_FRAGMENTS,		0x000014),
 	REG(SYS_COUNT_RX_JABBERS,		0x000018),
+	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,	0x00001c),
+	REG(SYS_COUNT_RX_SYM_ERRS,		0x000020),
 	REG(SYS_COUNT_RX_64,			0x000024),
 	REG(SYS_COUNT_RX_65_127,		0x000028),
 	REG(SYS_COUNT_RX_128_255,		0x00002c),
@@ -281,10 +285,41 @@ static const u32 vsc9953_sys_regmap[] = {
 	REG(SYS_COUNT_RX_512_1023,		0x000034),
 	REG(SYS_COUNT_RX_1024_1526,		0x000038),
 	REG(SYS_COUNT_RX_1527_MAX,		0x00003c),
+	REG(SYS_COUNT_RX_PAUSE,			0x000040),
+	REG(SYS_COUNT_RX_CONTROL,		0x000044),
 	REG(SYS_COUNT_RX_LONGS,			0x000048),
+	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,	0x00004c),
+	REG(SYS_COUNT_RX_RED_PRIO_0,		0x000050),
+	REG(SYS_COUNT_RX_RED_PRIO_1,		0x000054),
+	REG(SYS_COUNT_RX_RED_PRIO_2,		0x000058),
+	REG(SYS_COUNT_RX_RED_PRIO_3,		0x00005c),
+	REG(SYS_COUNT_RX_RED_PRIO_4,		0x000060),
+	REG(SYS_COUNT_RX_RED_PRIO_5,		0x000064),
+	REG(SYS_COUNT_RX_RED_PRIO_6,		0x000068),
+	REG(SYS_COUNT_RX_RED_PRIO_7,		0x00006c),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_0,		0x000070),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_1,		0x000074),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_2,		0x000078),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_3,		0x00007c),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_4,		0x000080),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_5,		0x000084),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_6,		0x000088),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_7,		0x00008c),
+	REG(SYS_COUNT_RX_GREEN_PRIO_0,		0x000090),
+	REG(SYS_COUNT_RX_GREEN_PRIO_1,		0x000094),
+	REG(SYS_COUNT_RX_GREEN_PRIO_2,		0x000098),
+	REG(SYS_COUNT_RX_GREEN_PRIO_3,		0x00009c),
+	REG(SYS_COUNT_RX_GREEN_PRIO_4,		0x0000a0),
+	REG(SYS_COUNT_RX_GREEN_PRIO_5,		0x0000a4),
+	REG(SYS_COUNT_RX_GREEN_PRIO_6,		0x0000a8),
+	REG(SYS_COUNT_RX_GREEN_PRIO_7,		0x0000ac),
 	REG(SYS_COUNT_TX_OCTETS,		0x000100),
+	REG(SYS_COUNT_TX_UNICAST,		0x000104),
+	REG(SYS_COUNT_TX_MULTICAST,		0x000108),
+	REG(SYS_COUNT_TX_BROADCAST,		0x00010c),
 	REG(SYS_COUNT_TX_COLLISION,		0x000110),
 	REG(SYS_COUNT_TX_DROPS,			0x000114),
+	REG(SYS_COUNT_TX_PAUSE,			0x000118),
 	REG(SYS_COUNT_TX_64,			0x00011c),
 	REG(SYS_COUNT_TX_65_127,		0x000120),
 	REG(SYS_COUNT_TX_128_255,		0x000124),
@@ -292,7 +327,41 @@ static const u32 vsc9953_sys_regmap[] = {
 	REG(SYS_COUNT_TX_512_1023,		0x00012c),
 	REG(SYS_COUNT_TX_1024_1526,		0x000130),
 	REG(SYS_COUNT_TX_1527_MAX,		0x000134),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_0,		0x000138),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_1,		0x00013c),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_2,		0x000140),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_3,		0x000144),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_4,		0x000148),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_5,		0x00014c),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_6,		0x000150),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_7,		0x000154),
+	REG(SYS_COUNT_TX_GREEN_PRIO_0,		0x000158),
+	REG(SYS_COUNT_TX_GREEN_PRIO_1,		0x00015c),
+	REG(SYS_COUNT_TX_GREEN_PRIO_2,		0x000160),
+	REG(SYS_COUNT_TX_GREEN_PRIO_3,		0x000164),
+	REG(SYS_COUNT_TX_GREEN_PRIO_4,		0x000168),
+	REG(SYS_COUNT_TX_GREEN_PRIO_5,		0x00016c),
+	REG(SYS_COUNT_TX_GREEN_PRIO_6,		0x000170),
+	REG(SYS_COUNT_TX_GREEN_PRIO_7,		0x000174),
 	REG(SYS_COUNT_TX_AGING,			0x000178),
+	REG(SYS_COUNT_DROP_LOCAL,		0x000200),
+	REG(SYS_COUNT_DROP_TAIL,		0x000204),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_0,	0x000208),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_1,	0x00020c),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_2,	0x000210),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_3,	0x000214),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_4,	0x000218),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_5,	0x00021c),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_6,	0x000220),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_7,	0x000224),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_0,	0x000228),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_1,	0x00022c),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_2,	0x000230),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_3,	0x000234),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_4,	0x000238),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_5,	0x00023c),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_6,	0x000240),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_7,	0x000244),
 	REG(SYS_RESET_CFG,			0x000318),
 	REG_RESERVED(SYS_SR_ETYPE_CFG),
 	REG(SYS_VLAN_ETYPE_CFG,			0x000320),
@@ -548,375 +617,375 @@ static const struct reg_field vsc9953_regfields[REGFIELD_MAX] = {
 static const struct ocelot_stat_layout vsc9953_stats_layout[OCELOT_NUM_STATS] = {
 	[OCELOT_STAT_RX_OCTETS] = {
 		.name = "rx_octets",
-		.offset = 0x00,
+		.reg = SYS_COUNT_RX_OCTETS,
 	},
 	[OCELOT_STAT_RX_UNICAST] = {
 		.name = "rx_unicast",
-		.offset = 0x01,
+		.reg = SYS_COUNT_RX_UNICAST,
 	},
 	[OCELOT_STAT_RX_MULTICAST] = {
 		.name = "rx_multicast",
-		.offset = 0x02,
+		.reg = SYS_COUNT_RX_MULTICAST,
 	},
 	[OCELOT_STAT_RX_BROADCAST] = {
 		.name = "rx_broadcast",
-		.offset = 0x03,
+		.reg = SYS_COUNT_RX_BROADCAST,
 	},
 	[OCELOT_STAT_RX_SHORTS] = {
 		.name = "rx_shorts",
-		.offset = 0x04,
+		.reg = SYS_COUNT_RX_SHORTS,
 	},
 	[OCELOT_STAT_RX_FRAGMENTS] = {
 		.name = "rx_fragments",
-		.offset = 0x05,
+		.reg = SYS_COUNT_RX_FRAGMENTS,
 	},
 	[OCELOT_STAT_RX_JABBERS] = {
 		.name = "rx_jabbers",
-		.offset = 0x06,
+		.reg = SYS_COUNT_RX_JABBERS,
 	},
 	[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
 		.name = "rx_crc_align_errs",
-		.offset = 0x07,
+		.reg = SYS_COUNT_RX_CRC_ALIGN_ERRS,
 	},
 	[OCELOT_STAT_RX_SYM_ERRS] = {
 		.name = "rx_sym_errs",
-		.offset = 0x08,
+		.reg = SYS_COUNT_RX_SYM_ERRS,
 	},
 	[OCELOT_STAT_RX_64] = {
 		.name = "rx_frames_below_65_octets",
-		.offset = 0x09,
+		.reg = SYS_COUNT_RX_64,
 	},
 	[OCELOT_STAT_RX_65_127] = {
 		.name = "rx_frames_65_to_127_octets",
-		.offset = 0x0A,
+		.reg = SYS_COUNT_RX_65_127,
 	},
 	[OCELOT_STAT_RX_128_255] = {
 		.name = "rx_frames_128_to_255_octets",
-		.offset = 0x0B,
+		.reg = SYS_COUNT_RX_128_255,
 	},
 	[OCELOT_STAT_RX_256_511] = {
 		.name = "rx_frames_256_to_511_octets",
-		.offset = 0x0C,
+		.reg = SYS_COUNT_RX_256_511,
 	},
 	[OCELOT_STAT_RX_512_1023] = {
 		.name = "rx_frames_512_to_1023_octets",
-		.offset = 0x0D,
+		.reg = SYS_COUNT_RX_512_1023,
 	},
 	[OCELOT_STAT_RX_1024_1526] = {
 		.name = "rx_frames_1024_to_1526_octets",
-		.offset = 0x0E,
+		.reg = SYS_COUNT_RX_1024_1526,
 	},
 	[OCELOT_STAT_RX_1527_MAX] = {
 		.name = "rx_frames_over_1526_octets",
-		.offset = 0x0F,
+		.reg = SYS_COUNT_RX_1527_MAX,
 	},
 	[OCELOT_STAT_RX_PAUSE] = {
 		.name = "rx_pause",
-		.offset = 0x10,
+		.reg = SYS_COUNT_RX_PAUSE,
 	},
 	[OCELOT_STAT_RX_CONTROL] = {
 		.name = "rx_control",
-		.offset = 0x11,
+		.reg = SYS_COUNT_RX_CONTROL,
 	},
 	[OCELOT_STAT_RX_LONGS] = {
 		.name = "rx_longs",
-		.offset = 0x12,
+		.reg = SYS_COUNT_RX_LONGS,
 	},
 	[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
 		.name = "rx_classified_drops",
-		.offset = 0x13,
+		.reg = SYS_COUNT_RX_CLASSIFIED_DROPS,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_0] = {
 		.name = "rx_red_prio_0",
-		.offset = 0x14,
+		.reg = SYS_COUNT_RX_RED_PRIO_0,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_1] = {
 		.name = "rx_red_prio_1",
-		.offset = 0x15,
+		.reg = SYS_COUNT_RX_RED_PRIO_1,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_2] = {
 		.name = "rx_red_prio_2",
-		.offset = 0x16,
+		.reg = SYS_COUNT_RX_RED_PRIO_2,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_3] = {
 		.name = "rx_red_prio_3",
-		.offset = 0x17,
+		.reg = SYS_COUNT_RX_RED_PRIO_3,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_4] = {
 		.name = "rx_red_prio_4",
-		.offset = 0x18,
+		.reg = SYS_COUNT_RX_RED_PRIO_4,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_5] = {
 		.name = "rx_red_prio_5",
-		.offset = 0x19,
+		.reg = SYS_COUNT_RX_RED_PRIO_5,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_6] = {
 		.name = "rx_red_prio_6",
-		.offset = 0x1A,
+		.reg = SYS_COUNT_RX_RED_PRIO_6,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_7] = {
 		.name = "rx_red_prio_7",
-		.offset = 0x1B,
+		.reg = SYS_COUNT_RX_RED_PRIO_7,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
 		.name = "rx_yellow_prio_0",
-		.offset = 0x1C,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
 		.name = "rx_yellow_prio_1",
-		.offset = 0x1D,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
 		.name = "rx_yellow_prio_2",
-		.offset = 0x1E,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
 		.name = "rx_yellow_prio_3",
-		.offset = 0x1F,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
 		.name = "rx_yellow_prio_4",
-		.offset = 0x20,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
 		.name = "rx_yellow_prio_5",
-		.offset = 0x21,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
 		.name = "rx_yellow_prio_6",
-		.offset = 0x22,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
 		.name = "rx_yellow_prio_7",
-		.offset = 0x23,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_0] = {
 		.name = "rx_green_prio_0",
-		.offset = 0x24,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_1] = {
 		.name = "rx_green_prio_1",
-		.offset = 0x25,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_2] = {
 		.name = "rx_green_prio_2",
-		.offset = 0x26,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_3] = {
 		.name = "rx_green_prio_3",
-		.offset = 0x27,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_4] = {
 		.name = "rx_green_prio_4",
-		.offset = 0x28,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_5] = {
 		.name = "rx_green_prio_5",
-		.offset = 0x29,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_6] = {
 		.name = "rx_green_prio_6",
-		.offset = 0x2A,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_7] = {
 		.name = "rx_green_prio_7",
-		.offset = 0x2B,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_7,
 	},
 	[OCELOT_STAT_TX_OCTETS] = {
 		.name = "tx_octets",
-		.offset = 0x40,
+		.reg = SYS_COUNT_TX_OCTETS,
 	},
 	[OCELOT_STAT_TX_UNICAST] = {
 		.name = "tx_unicast",
-		.offset = 0x41,
+		.reg = SYS_COUNT_TX_UNICAST,
 	},
 	[OCELOT_STAT_TX_MULTICAST] = {
 		.name = "tx_multicast",
-		.offset = 0x42,
+		.reg = SYS_COUNT_TX_MULTICAST,
 	},
 	[OCELOT_STAT_TX_BROADCAST] = {
 		.name = "tx_broadcast",
-		.offset = 0x43,
+		.reg = SYS_COUNT_TX_BROADCAST,
 	},
 	[OCELOT_STAT_TX_COLLISION] = {
 		.name = "tx_collision",
-		.offset = 0x44,
+		.reg = SYS_COUNT_TX_COLLISION,
 	},
 	[OCELOT_STAT_TX_DROPS] = {
 		.name = "tx_drops",
-		.offset = 0x45,
+		.reg = SYS_COUNT_TX_DROPS,
 	},
 	[OCELOT_STAT_TX_PAUSE] = {
 		.name = "tx_pause",
-		.offset = 0x46,
+		.reg = SYS_COUNT_TX_PAUSE,
 	},
 	[OCELOT_STAT_TX_64] = {
 		.name = "tx_frames_below_65_octets",
-		.offset = 0x47,
+		.reg = SYS_COUNT_TX_64,
 	},
 	[OCELOT_STAT_TX_65_127] = {
 		.name = "tx_frames_65_to_127_octets",
-		.offset = 0x48,
+		.reg = SYS_COUNT_TX_65_127,
 	},
 	[OCELOT_STAT_TX_128_255] = {
 		.name = "tx_frames_128_255_octets",
-		.offset = 0x49,
+		.reg = SYS_COUNT_TX_128_255,
 	},
 	[OCELOT_STAT_TX_256_511] = {
 		.name = "tx_frames_256_511_octets",
-		.offset = 0x4A,
+		.reg = SYS_COUNT_TX_256_511,
 	},
 	[OCELOT_STAT_TX_512_1023] = {
 		.name = "tx_frames_512_1023_octets",
-		.offset = 0x4B,
+		.reg = SYS_COUNT_TX_512_1023,
 	},
 	[OCELOT_STAT_TX_1024_1526] = {
 		.name = "tx_frames_1024_1526_octets",
-		.offset = 0x4C,
+		.reg = SYS_COUNT_TX_1024_1526,
 	},
 	[OCELOT_STAT_TX_1527_MAX] = {
 		.name = "tx_frames_over_1526_octets",
-		.offset = 0x4D,
+		.reg = SYS_COUNT_TX_1527_MAX,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
 		.name = "tx_yellow_prio_0",
-		.offset = 0x4E,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
 		.name = "tx_yellow_prio_1",
-		.offset = 0x4F,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
 		.name = "tx_yellow_prio_2",
-		.offset = 0x50,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
 		.name = "tx_yellow_prio_3",
-		.offset = 0x51,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
 		.name = "tx_yellow_prio_4",
-		.offset = 0x52,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
 		.name = "tx_yellow_prio_5",
-		.offset = 0x53,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
 		.name = "tx_yellow_prio_6",
-		.offset = 0x54,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
 		.name = "tx_yellow_prio_7",
-		.offset = 0x55,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_0] = {
 		.name = "tx_green_prio_0",
-		.offset = 0x56,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_1] = {
 		.name = "tx_green_prio_1",
-		.offset = 0x57,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_2] = {
 		.name = "tx_green_prio_2",
-		.offset = 0x58,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_3] = {
 		.name = "tx_green_prio_3",
-		.offset = 0x59,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_4] = {
 		.name = "tx_green_prio_4",
-		.offset = 0x5A,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_5] = {
 		.name = "tx_green_prio_5",
-		.offset = 0x5B,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_6] = {
 		.name = "tx_green_prio_6",
-		.offset = 0x5C,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_7] = {
 		.name = "tx_green_prio_7",
-		.offset = 0x5D,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_7,
 	},
 	[OCELOT_STAT_TX_AGED] = {
 		.name = "tx_aged",
-		.offset = 0x5E,
+		.reg = SYS_COUNT_TX_AGING,
 	},
 	[OCELOT_STAT_DROP_LOCAL] = {
 		.name = "drop_local",
-		.offset = 0x80,
+		.reg = SYS_COUNT_DROP_LOCAL,
 	},
 	[OCELOT_STAT_DROP_TAIL] = {
 		.name = "drop_tail",
-		.offset = 0x81,
+		.reg = SYS_COUNT_DROP_TAIL,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
 		.name = "drop_yellow_prio_0",
-		.offset = 0x82,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
 		.name = "drop_yellow_prio_1",
-		.offset = 0x83,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
 		.name = "drop_yellow_prio_2",
-		.offset = 0x84,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
 		.name = "drop_yellow_prio_3",
-		.offset = 0x85,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
 		.name = "drop_yellow_prio_4",
-		.offset = 0x86,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
 		.name = "drop_yellow_prio_5",
-		.offset = 0x87,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
 		.name = "drop_yellow_prio_6",
-		.offset = 0x88,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
 		.name = "drop_yellow_prio_7",
-		.offset = 0x89,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
 		.name = "drop_green_prio_0",
-		.offset = 0x8A,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
 		.name = "drop_green_prio_1",
-		.offset = 0x8B,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
 		.name = "drop_green_prio_2",
-		.offset = 0x8C,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
 		.name = "drop_green_prio_3",
-		.offset = 0x8D,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
 		.name = "drop_green_prio_4",
-		.offset = 0x8E,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
 		.name = "drop_green_prio_5",
-		.offset = 0x8F,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
 		.name = "drop_green_prio_6",
-		.offset = 0x90,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
 		.name = "drop_green_prio_7",
-		.offset = 0x91,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_7,
 	},
 };
 
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 68991b021c56..306026e6aa11 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1881,9 +1881,8 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
 	ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG);
 
 	list_for_each_entry(region, &ocelot->stats_regions, node) {
-		err = ocelot_bulk_read_rix(ocelot, SYS_COUNT_RX_OCTETS,
-					   region->offset, region->buf,
-					   region->count);
+		err = ocelot_bulk_read(ocelot, region->base, region->buf,
+				       region->count);
 		if (err)
 			return err;
 
@@ -1978,7 +1977,7 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
 		if (ocelot->stats_layout[i].name[0] == '\0')
 			continue;
 
-		if (region && ocelot->stats_layout[i].offset == last + 1) {
+		if (region && ocelot->stats_layout[i].reg == last + 4) {
 			region->count++;
 		} else {
 			region = devm_kzalloc(ocelot->dev, sizeof(*region),
@@ -1986,12 +1985,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
 			if (!region)
 				return -ENOMEM;
 
-			region->offset = ocelot->stats_layout[i].offset;
+			region->base = ocelot->stats_layout[i].reg;
 			region->count = 1;
 			list_add_tail(&region->node, &ocelot->stats_regions);
 		}
 
-		last = ocelot->stats_layout[i].offset;
+		last = ocelot->stats_layout[i].reg;
 	}
 
 	list_for_each_entry(region, &ocelot->stats_regions, node) {
diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
index 9ff910560043..9c488953f541 100644
--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
@@ -99,375 +99,375 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = {
 static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
 	[OCELOT_STAT_RX_OCTETS] = {
 		.name = "rx_octets",
-		.offset = 0x00,
+		.reg = SYS_COUNT_RX_OCTETS,
 	},
 	[OCELOT_STAT_RX_UNICAST] = {
 		.name = "rx_unicast",
-		.offset = 0x01,
+		.reg = SYS_COUNT_RX_UNICAST,
 	},
 	[OCELOT_STAT_RX_MULTICAST] = {
 		.name = "rx_multicast",
-		.offset = 0x02,
+		.reg = SYS_COUNT_RX_MULTICAST,
 	},
 	[OCELOT_STAT_RX_BROADCAST] = {
 		.name = "rx_broadcast",
-		.offset = 0x03,
+		.reg = SYS_COUNT_RX_BROADCAST,
 	},
 	[OCELOT_STAT_RX_SHORTS] = {
 		.name = "rx_shorts",
-		.offset = 0x04,
+		.reg = SYS_COUNT_RX_SHORTS,
 	},
 	[OCELOT_STAT_RX_FRAGMENTS] = {
 		.name = "rx_fragments",
-		.offset = 0x05,
+		.reg = SYS_COUNT_RX_FRAGMENTS,
 	},
 	[OCELOT_STAT_RX_JABBERS] = {
 		.name = "rx_jabbers",
-		.offset = 0x06,
+		.reg = SYS_COUNT_RX_JABBERS,
 	},
 	[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
 		.name = "rx_crc_align_errs",
-		.offset = 0x07,
+		.reg = SYS_COUNT_RX_CRC_ALIGN_ERRS,
 	},
 	[OCELOT_STAT_RX_SYM_ERRS] = {
 		.name = "rx_sym_errs",
-		.offset = 0x08,
+		.reg = SYS_COUNT_RX_SYM_ERRS,
 	},
 	[OCELOT_STAT_RX_64] = {
 		.name = "rx_frames_below_65_octets",
-		.offset = 0x09,
+		.reg = SYS_COUNT_RX_64,
 	},
 	[OCELOT_STAT_RX_65_127] = {
 		.name = "rx_frames_65_to_127_octets",
-		.offset = 0x0A,
+		.reg = SYS_COUNT_RX_65_127,
 	},
 	[OCELOT_STAT_RX_128_255] = {
 		.name = "rx_frames_128_to_255_octets",
-		.offset = 0x0B,
+		.reg = SYS_COUNT_RX_128_255,
 	},
 	[OCELOT_STAT_RX_256_511] = {
 		.name = "rx_frames_256_to_511_octets",
-		.offset = 0x0C,
+		.reg = SYS_COUNT_RX_256_511,
 	},
 	[OCELOT_STAT_RX_512_1023] = {
 		.name = "rx_frames_512_to_1023_octets",
-		.offset = 0x0D,
+		.reg = SYS_COUNT_RX_512_1023,
 	},
 	[OCELOT_STAT_RX_1024_1526] = {
 		.name = "rx_frames_1024_to_1526_octets",
-		.offset = 0x0E,
+		.reg = SYS_COUNT_RX_1024_1526,
 	},
 	[OCELOT_STAT_RX_1527_MAX] = {
 		.name = "rx_frames_over_1526_octets",
-		.offset = 0x0F,
+		.reg = SYS_COUNT_RX_1527_MAX,
 	},
 	[OCELOT_STAT_RX_PAUSE] = {
 		.name = "rx_pause",
-		.offset = 0x10,
+		.reg = SYS_COUNT_RX_PAUSE,
 	},
 	[OCELOT_STAT_RX_CONTROL] = {
 		.name = "rx_control",
-		.offset = 0x11,
+		.reg = SYS_COUNT_RX_CONTROL,
 	},
 	[OCELOT_STAT_RX_LONGS] = {
 		.name = "rx_longs",
-		.offset = 0x12,
+		.reg = SYS_COUNT_RX_LONGS,
 	},
 	[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
 		.name = "rx_classified_drops",
-		.offset = 0x13,
+		.reg = SYS_COUNT_RX_CLASSIFIED_DROPS,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_0] = {
 		.name = "rx_red_prio_0",
-		.offset = 0x14,
+		.reg = SYS_COUNT_RX_RED_PRIO_0,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_1] = {
 		.name = "rx_red_prio_1",
-		.offset = 0x15,
+		.reg = SYS_COUNT_RX_RED_PRIO_1,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_2] = {
 		.name = "rx_red_prio_2",
-		.offset = 0x16,
+		.reg = SYS_COUNT_RX_RED_PRIO_2,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_3] = {
 		.name = "rx_red_prio_3",
-		.offset = 0x17,
+		.reg = SYS_COUNT_RX_RED_PRIO_3,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_4] = {
 		.name = "rx_red_prio_4",
-		.offset = 0x18,
+		.reg = SYS_COUNT_RX_RED_PRIO_4,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_5] = {
 		.name = "rx_red_prio_5",
-		.offset = 0x19,
+		.reg = SYS_COUNT_RX_RED_PRIO_5,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_6] = {
 		.name = "rx_red_prio_6",
-		.offset = 0x1A,
+		.reg = SYS_COUNT_RX_RED_PRIO_6,
 	},
 	[OCELOT_STAT_RX_RED_PRIO_7] = {
 		.name = "rx_red_prio_7",
-		.offset = 0x1B,
+		.reg = SYS_COUNT_RX_RED_PRIO_7,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
 		.name = "rx_yellow_prio_0",
-		.offset = 0x1C,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
 		.name = "rx_yellow_prio_1",
-		.offset = 0x1D,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
 		.name = "rx_yellow_prio_2",
-		.offset = 0x1E,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
 		.name = "rx_yellow_prio_3",
-		.offset = 0x1F,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
 		.name = "rx_yellow_prio_4",
-		.offset = 0x20,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
 		.name = "rx_yellow_prio_5",
-		.offset = 0x21,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
 		.name = "rx_yellow_prio_6",
-		.offset = 0x22,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
 		.name = "rx_yellow_prio_7",
-		.offset = 0x23,
+		.reg = SYS_COUNT_RX_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_0] = {
 		.name = "rx_green_prio_0",
-		.offset = 0x24,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_1] = {
 		.name = "rx_green_prio_1",
-		.offset = 0x25,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_2] = {
 		.name = "rx_green_prio_2",
-		.offset = 0x26,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_3] = {
 		.name = "rx_green_prio_3",
-		.offset = 0x27,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_4] = {
 		.name = "rx_green_prio_4",
-		.offset = 0x28,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_5] = {
 		.name = "rx_green_prio_5",
-		.offset = 0x29,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_6] = {
 		.name = "rx_green_prio_6",
-		.offset = 0x2A,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_RX_GREEN_PRIO_7] = {
 		.name = "rx_green_prio_7",
-		.offset = 0x2B,
+		.reg = SYS_COUNT_RX_GREEN_PRIO_7,
 	},
 	[OCELOT_STAT_TX_OCTETS] = {
 		.name = "tx_octets",
-		.offset = 0x40,
+		.reg = SYS_COUNT_TX_OCTETS,
 	},
 	[OCELOT_STAT_TX_UNICAST] = {
 		.name = "tx_unicast",
-		.offset = 0x41,
+		.reg = SYS_COUNT_TX_UNICAST,
 	},
 	[OCELOT_STAT_TX_MULTICAST] = {
 		.name = "tx_multicast",
-		.offset = 0x42,
+		.reg = SYS_COUNT_TX_MULTICAST,
 	},
 	[OCELOT_STAT_TX_BROADCAST] = {
 		.name = "tx_broadcast",
-		.offset = 0x43,
+		.reg = SYS_COUNT_TX_BROADCAST,
 	},
 	[OCELOT_STAT_TX_COLLISION] = {
 		.name = "tx_collision",
-		.offset = 0x44,
+		.reg = SYS_COUNT_TX_COLLISION,
 	},
 	[OCELOT_STAT_TX_DROPS] = {
 		.name = "tx_drops",
-		.offset = 0x45,
+		.reg = SYS_COUNT_TX_DROPS,
 	},
 	[OCELOT_STAT_TX_PAUSE] = {
 		.name = "tx_pause",
-		.offset = 0x46,
+		.reg = SYS_COUNT_TX_PAUSE,
 	},
 	[OCELOT_STAT_TX_64] = {
 		.name = "tx_frames_below_65_octets",
-		.offset = 0x47,
+		.reg = SYS_COUNT_TX_64,
 	},
 	[OCELOT_STAT_TX_65_127] = {
 		.name = "tx_frames_65_to_127_octets",
-		.offset = 0x48,
+		.reg = SYS_COUNT_TX_65_127,
 	},
 	[OCELOT_STAT_TX_128_255] = {
 		.name = "tx_frames_128_255_octets",
-		.offset = 0x49,
+		.reg = SYS_COUNT_TX_128_255,
 	},
 	[OCELOT_STAT_TX_256_511] = {
 		.name = "tx_frames_256_511_octets",
-		.offset = 0x4A,
+		.reg = SYS_COUNT_TX_256_511,
 	},
 	[OCELOT_STAT_TX_512_1023] = {
 		.name = "tx_frames_512_1023_octets",
-		.offset = 0x4B,
+		.reg = SYS_COUNT_TX_512_1023,
 	},
 	[OCELOT_STAT_TX_1024_1526] = {
 		.name = "tx_frames_1024_1526_octets",
-		.offset = 0x4C,
+		.reg = SYS_COUNT_TX_1024_1526,
 	},
 	[OCELOT_STAT_TX_1527_MAX] = {
 		.name = "tx_frames_over_1526_octets",
-		.offset = 0x4D,
+		.reg = SYS_COUNT_TX_1527_MAX,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
 		.name = "tx_yellow_prio_0",
-		.offset = 0x4E,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
 		.name = "tx_yellow_prio_1",
-		.offset = 0x4F,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
 		.name = "tx_yellow_prio_2",
-		.offset = 0x50,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
 		.name = "tx_yellow_prio_3",
-		.offset = 0x51,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
 		.name = "tx_yellow_prio_4",
-		.offset = 0x52,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
 		.name = "tx_yellow_prio_5",
-		.offset = 0x53,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
 		.name = "tx_yellow_prio_6",
-		.offset = 0x54,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
 		.name = "tx_yellow_prio_7",
-		.offset = 0x55,
+		.reg = SYS_COUNT_TX_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_0] = {
 		.name = "tx_green_prio_0",
-		.offset = 0x56,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_1] = {
 		.name = "tx_green_prio_1",
-		.offset = 0x57,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_2] = {
 		.name = "tx_green_prio_2",
-		.offset = 0x58,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_3] = {
 		.name = "tx_green_prio_3",
-		.offset = 0x59,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_4] = {
 		.name = "tx_green_prio_4",
-		.offset = 0x5A,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_5] = {
 		.name = "tx_green_prio_5",
-		.offset = 0x5B,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_6] = {
 		.name = "tx_green_prio_6",
-		.offset = 0x5C,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_TX_GREEN_PRIO_7] = {
 		.name = "tx_green_prio_7",
-		.offset = 0x5D,
+		.reg = SYS_COUNT_TX_GREEN_PRIO_7,
 	},
 	[OCELOT_STAT_TX_AGED] = {
 		.name = "tx_aged",
-		.offset = 0x5E,
+		.reg = SYS_COUNT_TX_AGING,
 	},
 	[OCELOT_STAT_DROP_LOCAL] = {
 		.name = "drop_local",
-		.offset = 0x80,
+		.reg = SYS_COUNT_DROP_LOCAL,
 	},
 	[OCELOT_STAT_DROP_TAIL] = {
 		.name = "drop_tail",
-		.offset = 0x81,
+		.reg = SYS_COUNT_DROP_TAIL,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
 		.name = "drop_yellow_prio_0",
-		.offset = 0x82,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_0,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
 		.name = "drop_yellow_prio_1",
-		.offset = 0x83,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_1,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
 		.name = "drop_yellow_prio_2",
-		.offset = 0x84,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_2,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
 		.name = "drop_yellow_prio_3",
-		.offset = 0x85,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_3,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
 		.name = "drop_yellow_prio_4",
-		.offset = 0x86,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_4,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
 		.name = "drop_yellow_prio_5",
-		.offset = 0x87,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_5,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
 		.name = "drop_yellow_prio_6",
-		.offset = 0x88,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_6,
 	},
 	[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
 		.name = "drop_yellow_prio_7",
-		.offset = 0x89,
+		.reg = SYS_COUNT_DROP_YELLOW_PRIO_7,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
 		.name = "drop_green_prio_0",
-		.offset = 0x8A,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_0,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
 		.name = "drop_green_prio_1",
-		.offset = 0x8B,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_1,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
 		.name = "drop_green_prio_2",
-		.offset = 0x8C,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_2,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
 		.name = "drop_green_prio_3",
-		.offset = 0x8D,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_3,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
 		.name = "drop_green_prio_4",
-		.offset = 0x8E,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_4,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
 		.name = "drop_green_prio_5",
-		.offset = 0x8F,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_5,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
 		.name = "drop_green_prio_6",
-		.offset = 0x90,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_6,
 	},
 	[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
 		.name = "drop_green_prio_7",
-		.offset = 0x91,
+		.reg = SYS_COUNT_DROP_GREEN_PRIO_7,
 	},
 };
 
diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c
index 8ff935f7f150..9cf82ecf191c 100644
--- a/drivers/net/ethernet/mscc/vsc7514_regs.c
+++ b/drivers/net/ethernet/mscc/vsc7514_regs.c
@@ -188,6 +188,30 @@ const u32 vsc7514_sys_regmap[] = {
 	REG(SYS_COUNT_RX_CONTROL,			0x000044),
 	REG(SYS_COUNT_RX_LONGS,				0x000048),
 	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x00004c),
+	REG(SYS_COUNT_RX_RED_PRIO_0,			0x000050),
+	REG(SYS_COUNT_RX_RED_PRIO_1,			0x000054),
+	REG(SYS_COUNT_RX_RED_PRIO_2,			0x000058),
+	REG(SYS_COUNT_RX_RED_PRIO_3,			0x00005c),
+	REG(SYS_COUNT_RX_RED_PRIO_4,			0x000060),
+	REG(SYS_COUNT_RX_RED_PRIO_5,			0x000064),
+	REG(SYS_COUNT_RX_RED_PRIO_6,			0x000068),
+	REG(SYS_COUNT_RX_RED_PRIO_7,			0x00006c),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_0,			0x000070),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_1,			0x000074),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_2,			0x000078),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_3,			0x00007c),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_4,			0x000080),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_5,			0x000084),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_6,			0x000088),
+	REG(SYS_COUNT_RX_YELLOW_PRIO_7,			0x00008c),
+	REG(SYS_COUNT_RX_GREEN_PRIO_0,			0x000090),
+	REG(SYS_COUNT_RX_GREEN_PRIO_1,			0x000094),
+	REG(SYS_COUNT_RX_GREEN_PRIO_2,			0x000098),
+	REG(SYS_COUNT_RX_GREEN_PRIO_3,			0x00009c),
+	REG(SYS_COUNT_RX_GREEN_PRIO_4,			0x0000a0),
+	REG(SYS_COUNT_RX_GREEN_PRIO_5,			0x0000a4),
+	REG(SYS_COUNT_RX_GREEN_PRIO_6,			0x0000a8),
+	REG(SYS_COUNT_RX_GREEN_PRIO_7,			0x0000ac),
 	REG(SYS_COUNT_TX_OCTETS,			0x000100),
 	REG(SYS_COUNT_TX_UNICAST,			0x000104),
 	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
@@ -202,7 +226,41 @@ const u32 vsc7514_sys_regmap[] = {
 	REG(SYS_COUNT_TX_512_1023,			0x00012c),
 	REG(SYS_COUNT_TX_1024_1526,			0x000130),
 	REG(SYS_COUNT_TX_1527_MAX,			0x000134),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_0,			0x000138),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_1,			0x00013c),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_2,			0x000140),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_3,			0x000144),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_4,			0x000148),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_5,			0x00014c),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_6,			0x000150),
+	REG(SYS_COUNT_TX_YELLOW_PRIO_7,			0x000154),
+	REG(SYS_COUNT_TX_GREEN_PRIO_0,			0x000158),
+	REG(SYS_COUNT_TX_GREEN_PRIO_1,			0x00015c),
+	REG(SYS_COUNT_TX_GREEN_PRIO_2,			0x000160),
+	REG(SYS_COUNT_TX_GREEN_PRIO_3,			0x000164),
+	REG(SYS_COUNT_TX_GREEN_PRIO_4,			0x000168),
+	REG(SYS_COUNT_TX_GREEN_PRIO_5,			0x00016c),
+	REG(SYS_COUNT_TX_GREEN_PRIO_6,			0x000170),
+	REG(SYS_COUNT_TX_GREEN_PRIO_7,			0x000174),
 	REG(SYS_COUNT_TX_AGING,				0x000178),
+	REG(SYS_COUNT_DROP_LOCAL,			0x000200),
+	REG(SYS_COUNT_DROP_TAIL,			0x000204),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_0,		0x000208),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_1,		0x00020c),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_2,		0x000210),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_3,		0x000214),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_4,		0x000218),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_5,		0x00021c),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_6,		0x000220),
+	REG(SYS_COUNT_DROP_YELLOW_PRIO_7,		0x000214),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_0,		0x000218),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_1,		0x00021c),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_2,		0x000220),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_3,		0x000224),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_4,		0x000228),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_5,		0x00022c),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_6,		0x000230),
+	REG(SYS_COUNT_DROP_GREEN_PRIO_7,		0x000234),
 	REG(SYS_RESET_CFG,				0x000508),
 	REG(SYS_CMID,					0x00050c),
 	REG(SYS_VLAN_ETYPE_CFG,				0x000510),
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 2428bc64cb1d..2edea901bbd5 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -338,6 +338,30 @@ enum ocelot_reg {
 	SYS_COUNT_RX_CONTROL,
 	SYS_COUNT_RX_LONGS,
 	SYS_COUNT_RX_CLASSIFIED_DROPS,
+	SYS_COUNT_RX_RED_PRIO_0,
+	SYS_COUNT_RX_RED_PRIO_1,
+	SYS_COUNT_RX_RED_PRIO_2,
+	SYS_COUNT_RX_RED_PRIO_3,
+	SYS_COUNT_RX_RED_PRIO_4,
+	SYS_COUNT_RX_RED_PRIO_5,
+	SYS_COUNT_RX_RED_PRIO_6,
+	SYS_COUNT_RX_RED_PRIO_7,
+	SYS_COUNT_RX_YELLOW_PRIO_0,
+	SYS_COUNT_RX_YELLOW_PRIO_1,
+	SYS_COUNT_RX_YELLOW_PRIO_2,
+	SYS_COUNT_RX_YELLOW_PRIO_3,
+	SYS_COUNT_RX_YELLOW_PRIO_4,
+	SYS_COUNT_RX_YELLOW_PRIO_5,
+	SYS_COUNT_RX_YELLOW_PRIO_6,
+	SYS_COUNT_RX_YELLOW_PRIO_7,
+	SYS_COUNT_RX_GREEN_PRIO_0,
+	SYS_COUNT_RX_GREEN_PRIO_1,
+	SYS_COUNT_RX_GREEN_PRIO_2,
+	SYS_COUNT_RX_GREEN_PRIO_3,
+	SYS_COUNT_RX_GREEN_PRIO_4,
+	SYS_COUNT_RX_GREEN_PRIO_5,
+	SYS_COUNT_RX_GREEN_PRIO_6,
+	SYS_COUNT_RX_GREEN_PRIO_7,
 	SYS_COUNT_TX_OCTETS,
 	SYS_COUNT_TX_UNICAST,
 	SYS_COUNT_TX_MULTICAST,
@@ -352,7 +376,41 @@ enum ocelot_reg {
 	SYS_COUNT_TX_512_1023,
 	SYS_COUNT_TX_1024_1526,
 	SYS_COUNT_TX_1527_MAX,
+	SYS_COUNT_TX_YELLOW_PRIO_0,
+	SYS_COUNT_TX_YELLOW_PRIO_1,
+	SYS_COUNT_TX_YELLOW_PRIO_2,
+	SYS_COUNT_TX_YELLOW_PRIO_3,
+	SYS_COUNT_TX_YELLOW_PRIO_4,
+	SYS_COUNT_TX_YELLOW_PRIO_5,
+	SYS_COUNT_TX_YELLOW_PRIO_6,
+	SYS_COUNT_TX_YELLOW_PRIO_7,
+	SYS_COUNT_TX_GREEN_PRIO_0,
+	SYS_COUNT_TX_GREEN_PRIO_1,
+	SYS_COUNT_TX_GREEN_PRIO_2,
+	SYS_COUNT_TX_GREEN_PRIO_3,
+	SYS_COUNT_TX_GREEN_PRIO_4,
+	SYS_COUNT_TX_GREEN_PRIO_5,
+	SYS_COUNT_TX_GREEN_PRIO_6,
+	SYS_COUNT_TX_GREEN_PRIO_7,
 	SYS_COUNT_TX_AGING,
+	SYS_COUNT_DROP_LOCAL,
+	SYS_COUNT_DROP_TAIL,
+	SYS_COUNT_DROP_YELLOW_PRIO_0,
+	SYS_COUNT_DROP_YELLOW_PRIO_1,
+	SYS_COUNT_DROP_YELLOW_PRIO_2,
+	SYS_COUNT_DROP_YELLOW_PRIO_3,
+	SYS_COUNT_DROP_YELLOW_PRIO_4,
+	SYS_COUNT_DROP_YELLOW_PRIO_5,
+	SYS_COUNT_DROP_YELLOW_PRIO_6,
+	SYS_COUNT_DROP_YELLOW_PRIO_7,
+	SYS_COUNT_DROP_GREEN_PRIO_0,
+	SYS_COUNT_DROP_GREEN_PRIO_1,
+	SYS_COUNT_DROP_GREEN_PRIO_2,
+	SYS_COUNT_DROP_GREEN_PRIO_3,
+	SYS_COUNT_DROP_GREEN_PRIO_4,
+	SYS_COUNT_DROP_GREEN_PRIO_5,
+	SYS_COUNT_DROP_GREEN_PRIO_6,
+	SYS_COUNT_DROP_GREEN_PRIO_7,
 	SYS_RESET_CFG,
 	SYS_SR_ETYPE_CFG,
 	SYS_VLAN_ETYPE_CFG,
@@ -633,13 +691,13 @@ enum ocelot_stat {
 };
 
 struct ocelot_stat_layout {
-	u32 offset;
+	u32 reg;
 	char name[ETH_GSTRING_LEN];
 };
 
 struct ocelot_stats_region {
 	struct list_head node;
-	u32 offset;
+	u32 base;
 	int count;
 	u32 *buf;
 };
@@ -877,8 +935,8 @@ struct ocelot_policer {
 	u32 burst; /* bytes */
 };
 
-#define ocelot_bulk_read_rix(ocelot, reg, ri, buf, count) \
-	__ocelot_bulk_read_ix(ocelot, reg, reg##_RSZ * (ri), buf, count)
+#define ocelot_bulk_read(ocelot, reg, buf, count) \
+	__ocelot_bulk_read_ix(ocelot, reg, 0, buf, count)
 
 #define ocelot_read_ix(ocelot, reg, gi, ri) \
 	__ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH net 8/8] net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
                   ` (6 preceding siblings ...)
  2022-08-16 13:53 ` [PATCH net 7/8] net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset Vladimir Oltean
@ 2022-08-16 13:53 ` Vladimir Oltean
  2022-08-18  5:20 ` [PATCH net 0/8] Fixes for Ocelot driver statistics patchwork-bot+netdevbpf
  8 siblings, 0 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-16 13:53 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Claudiu Manoil,
	Alexandre Belloni, UNGLinuxDriver, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Colin Foster, Maxim Kochetkov

Rather than reading the stats64 counters directly from the 32-bit
hardware, it's better to rely on the output produced by the periodic
ocelot_port_update_stats().

It would be even better to call ocelot_port_update_stats() right from
ocelot_get_stats64() to make sure we report the current values rather
than the ones from 2 seconds ago. But we need to export
ocelot_port_update_stats() from the switch lib towards the switchdev
driver for that, and future work will largely undo that.

There are more ocelot-based drivers waiting to be introduced, an example
of which is the SPI-controlled VSC7512. In that driver's case, it will
be impossible to call ocelot_port_update_stats() from ndo_get_stats64
context, since the latter is atomic, and reading the stats over SPI is
sleepable. So the compromise taken here, which will also hold going
forward, is to report 64-bit counters to stats64, which are not 100% up
to date.

Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_net.c | 53 +++++++++++++-------------
 1 file changed, 26 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 6b9d37138844..330d30841cdc 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -725,41 +725,40 @@ static void ocelot_get_stats64(struct net_device *dev,
 	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
+	u64 *s;
 
 	spin_lock(&ocelot->stats_lock);
 
-	/* Configure the port to read the stats from */
-	ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port),
-		     SYS_STAT_CFG);
+	s = &ocelot->stats[port * OCELOT_NUM_STATS];
 
 	/* Get Rx stats */
-	stats->rx_bytes = ocelot_read(ocelot, SYS_COUNT_RX_OCTETS);
-	stats->rx_packets = ocelot_read(ocelot, SYS_COUNT_RX_SHORTS) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_FRAGMENTS) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_JABBERS) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_LONGS) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_64) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_65_127) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_128_255) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_256_511) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_512_1023) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_1024_1526) +
-			    ocelot_read(ocelot, SYS_COUNT_RX_1527_MAX);
-	stats->multicast = ocelot_read(ocelot, SYS_COUNT_RX_MULTICAST);
+	stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS];
+	stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] +
+			    s[OCELOT_STAT_RX_FRAGMENTS] +
+			    s[OCELOT_STAT_RX_JABBERS] +
+			    s[OCELOT_STAT_RX_LONGS] +
+			    s[OCELOT_STAT_RX_64] +
+			    s[OCELOT_STAT_RX_65_127] +
+			    s[OCELOT_STAT_RX_128_255] +
+			    s[OCELOT_STAT_RX_256_511] +
+			    s[OCELOT_STAT_RX_512_1023] +
+			    s[OCELOT_STAT_RX_1024_1526] +
+			    s[OCELOT_STAT_RX_1527_MAX];
+	stats->multicast = s[OCELOT_STAT_RX_MULTICAST];
 	stats->rx_dropped = dev->stats.rx_dropped;
 
 	/* Get Tx stats */
-	stats->tx_bytes = ocelot_read(ocelot, SYS_COUNT_TX_OCTETS);
-	stats->tx_packets = ocelot_read(ocelot, SYS_COUNT_TX_64) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_65_127) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_128_255) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_256_511) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_512_1023) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX);
-	stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) +
-			    ocelot_read(ocelot, SYS_COUNT_TX_AGING);
-	stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION);
+	stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS];
+	stats->tx_packets = s[OCELOT_STAT_TX_64] +
+			    s[OCELOT_STAT_TX_65_127] +
+			    s[OCELOT_STAT_TX_128_255] +
+			    s[OCELOT_STAT_TX_256_511] +
+			    s[OCELOT_STAT_TX_512_1023] +
+			    s[OCELOT_STAT_TX_1024_1526] +
+			    s[OCELOT_STAT_TX_1527_MAX];
+	stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] +
+			    s[OCELOT_STAT_TX_AGED];
+	stats->collisions = s[OCELOT_STAT_TX_COLLISION];
 
 	spin_unlock(&ocelot->stats_lock);
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH net 2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 packet counters
  2022-08-16 13:53 ` [PATCH net 2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 " Vladimir Oltean
@ 2022-08-17  6:26   ` Colin Foster
  0 siblings, 0 replies; 20+ messages in thread
From: Colin Foster @ 2022-08-17  6:26 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

> --- a/drivers/net/ethernet/mscc/vsc7514_regs.c
> +++ b/drivers/net/ethernet/mscc/vsc7514_regs.c
> @@ -180,13 +180,14 @@ const u32 vsc7514_sys_regmap[] = {
>  	REG(SYS_COUNT_RX_64,				0x000024),
>  	REG(SYS_COUNT_RX_65_127,			0x000028),
>  	REG(SYS_COUNT_RX_128_255,			0x00002c),
> -	REG(SYS_COUNT_RX_256_1023,			0x000030),
> -	REG(SYS_COUNT_RX_1024_1526,			0x000034),
> -	REG(SYS_COUNT_RX_1527_MAX,			0x000038),
> -	REG(SYS_COUNT_RX_PAUSE,				0x00003c),
> -	REG(SYS_COUNT_RX_CONTROL,			0x000040),
> -	REG(SYS_COUNT_RX_LONGS,				0x000044),
> -	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x000048),
> +	REG(SYS_COUNT_RX_256_511,			0x000030),
> +	REG(SYS_COUNT_RX_512_1023,			0x000034),
> +	REG(SYS_COUNT_RX_1024_1526,			0x000038),
> +	REG(SYS_COUNT_RX_1527_MAX,			0x00003c),
> +	REG(SYS_COUNT_RX_PAUSE,				0x000040),
> +	REG(SYS_COUNT_RX_CONTROL,			0x000044),
> +	REG(SYS_COUNT_RX_LONGS,				0x000048),
> +	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x00004c),

Hi Vladimir,

Good catch! From a 7512/7514 point, these all look good. There's a
couple conflicts I'll have to deal with to test the whole series.

>  	REG(SYS_COUNT_TX_OCTETS,			0x000100),
>  	REG(SYS_COUNT_TX_UNICAST,			0x000104),
>  	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
> @@ -196,10 +197,11 @@ const u32 vsc7514_sys_regmap[] = {
>  	REG(SYS_COUNT_TX_PAUSE,				0x000118),
>  	REG(SYS_COUNT_TX_64,				0x00011c),
>  	REG(SYS_COUNT_TX_65_127,			0x000120),
> -	REG(SYS_COUNT_TX_128_511,			0x000124),
> -	REG(SYS_COUNT_TX_512_1023,			0x000128),
> -	REG(SYS_COUNT_TX_1024_1526,			0x00012c),
> -	REG(SYS_COUNT_TX_1527_MAX,			0x000130),
> +	REG(SYS_COUNT_TX_128_255,			0x000124),
> +	REG(SYS_COUNT_TX_256_511,			0x000128),
> +	REG(SYS_COUNT_TX_512_1023,			0x00012c),
> +	REG(SYS_COUNT_TX_1024_1526,			0x000130),
> +	REG(SYS_COUNT_TX_1527_MAX,			0x000134),
>  	REG(SYS_COUNT_TX_AGING,				0x000170),
>  	REG(SYS_RESET_CFG,				0x000508),
>  	REG(SYS_CMID,					0x00050c),
> diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
> index ac151ecc7f19..e7e5b06deb2d 100644
> --- a/include/soc/mscc/ocelot.h
> +++ b/include/soc/mscc/ocelot.h
> @@ -335,7 +335,8 @@ enum ocelot_reg {
>  	SYS_COUNT_RX_64,
>  	SYS_COUNT_RX_65_127,
>  	SYS_COUNT_RX_128_255,
> -	SYS_COUNT_RX_256_1023,
> +	SYS_COUNT_RX_256_511,
> +	SYS_COUNT_RX_512_1023,
>  	SYS_COUNT_RX_1024_1526,
>  	SYS_COUNT_RX_1527_MAX,
>  	SYS_COUNT_RX_PAUSE,
> @@ -351,7 +352,8 @@ enum ocelot_reg {
>  	SYS_COUNT_TX_PAUSE,
>  	SYS_COUNT_TX_64,
>  	SYS_COUNT_TX_65_127,
> -	SYS_COUNT_TX_128_511,
> +	SYS_COUNT_TX_128_255,
> +	SYS_COUNT_TX_256_511,
>  	SYS_COUNT_TX_512_1023,
>  	SYS_COUNT_TX_1024_1526,
>  	SYS_COUNT_TX_1527_MAX,
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-16 13:53 ` [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable Vladimir Oltean
@ 2022-08-17  6:46   ` Colin Foster
  2022-08-17 11:06     ` Vladimir Oltean
  0 siblings, 1 reply; 20+ messages in thread
From: Colin Foster @ 2022-08-17  6:46 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Tue, Aug 16, 2022 at 04:53:50PM +0300, Vladimir Oltean wrote:
> The ocelot counters are 32-bit and require periodic reading, every 2
> seconds, by ocelot_port_update_stats(), so that wraparounds are
> detected.
> 
> Currently, the counters reported by ocelot_get_stats64() come from the
> 32-bit hardware counters directly, rather than from the 64-bit
> accumulated ocelot->stats, and this is a problem for their integrity.
> 
> The strategy is to make ocelot_get_stats64() able to cherry-pick
> individual stats from ocelot->stats the way in which it currently reads
> them out from SYS_COUNT_* registers. But currently it can't, because
> ocelot->stats is an opaque u64 array that's used only to feed data into
> ethtool -S.
> 
> To solve that problem, we need to make ocelot->stats indexable, and
> associate each element with an element of struct ocelot_stat_layout used
> by ethtool -S.
> 
> This makes ocelot_stat_layout a fat (and possibly sparse) array, so we
> need to change the way in which we access it. We no longer need
> OCELOT_STAT_END as a sentinel, because we know the array's size
> (OCELOT_NUM_STATS). We just need to skip the array elements that were
> left unpopulated for the switch revision (ocelot, felix, seville).

Hi Vladimir,

I'm not sure if this is an issue here, and I'm not sure it will ever
be... ocelot_stat_layout as you know relies on consecutive register
addresses to be most efficient. This was indirectly enforced by
*_stats_layout[] always being laid out in ascending order.

If the order of ocelot_stat doesn't match each device's register
offset order, there'll be unnecessary overhead. I tried to test
this just now, but I'll have to deal with a few conflicts that I won't
be able to get to immediately.

Do you see this as a potential issue in the future? Or do you expect all
hardware is simliar enough that they'll all be ordered the same?

Or, because I'm the lucky one running on a slow SPI bus, this will be my
problem to monitor and fix if need be :)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17  6:46   ` Colin Foster
@ 2022-08-17 11:06     ` Vladimir Oltean
  2022-08-17 13:05       ` Vladimir Oltean
  0 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-17 11:06 UTC (permalink / raw)
  To: Colin Foster
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Tue, Aug 16, 2022 at 11:46:46PM -0700, Colin Foster wrote:
> Hi Vladimir,
> 
> I'm not sure if this is an issue here, and I'm not sure it will ever
> be... ocelot_stat_layout as you know relies on consecutive register
> addresses to be most efficient. This was indirectly enforced by
> *_stats_layout[] always being laid out in ascending order.
> 
> If the order of ocelot_stat doesn't match each device's register
> offset order, there'll be unnecessary overhead. I tried to test
> this just now, but I'll have to deal with a few conflicts that I won't
> be able to get to immediately.
> 
> Do you see this as a potential issue in the future? Or do you expect all
> hardware is simliar enough that they'll all be ordered the same?
> 
> Or, because I'm the lucky one running on a slow SPI bus, this will be my
> problem to monitor and fix if need be :)

No, you're right and the bulk reads complicate things; in fact I'm not
sure that this patch even works by anything other than pure chance.

In some future changes I'm making the first N elements of the
struct ocelot_stat_layout array be common across all drivers. Only Felix
VSC9959 has some extra TSN-related counters which the others don't have.
It would look like this:

/* 32-bit counter checked for wraparound by ocelot_port_update_stats()
 * and copied to ocelot->stats.
 */
#define OCELOT_STAT(kind) \
	[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind }
/* Same as above, except also exported to ethtool -S. Standard counters should
 * only be exposed to more specific interfaces rather than by their string name.
 */
#define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \
	[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name }

#define OCELOT_COMMON_STATS \
	OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \
	OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \
	OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \
	OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \
	OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \
	OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \
	OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \
	OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \
	OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \
	OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \
	OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \
	OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \
	OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \
	OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \
	OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \
	OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \
	OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \
	OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \
	OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \
	OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \
	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \
	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \
	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \
	OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \
	OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \
	OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \
	OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \
	OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \
	OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \
	OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \
	OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \
	OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \
	OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \
	OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \
	OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \
	OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \
	OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \
	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \
	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \
	OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \
	OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \
	OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \
	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \
	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7")

static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
	OCELOT_COMMON_STATS,
};

static const struct ocelot_stat_layout vsc9953_stats_layout[OCELOT_NUM_STATS] = {
	OCELOT_COMMON_STATS,
};

static const struct ocelot_stat_layout vsc9959_stats_layout[OCELOT_NUM_STATS] = {
	OCELOT_COMMON_STATS,
	OCELOT_STAT(RX_ASSEMBLY_ERRS),
	OCELOT_STAT(RX_SMD_ERRS),
	OCELOT_STAT(RX_ASSEMBLY_OK),
	OCELOT_STAT(RX_MERGE_FRAGMENTS),
	OCELOT_STAT(TX_MERGE_FRAGMENTS),
	OCELOT_STAT(RX_PMAC_OCTETS),
	OCELOT_STAT(RX_PMAC_UNICAST),
	OCELOT_STAT(RX_PMAC_MULTICAST),
	OCELOT_STAT(RX_PMAC_BROADCAST),
	OCELOT_STAT(RX_PMAC_SHORTS),
	OCELOT_STAT(RX_PMAC_FRAGMENTS),
	OCELOT_STAT(RX_PMAC_JABBERS),
	OCELOT_STAT(RX_PMAC_CRC_ALIGN_ERRS),
	OCELOT_STAT(RX_PMAC_SYM_ERRS),
	OCELOT_STAT(RX_PMAC_64),
	OCELOT_STAT(RX_PMAC_65_127),
	OCELOT_STAT(RX_PMAC_128_255),
	OCELOT_STAT(RX_PMAC_256_511),
	OCELOT_STAT(RX_PMAC_512_1023),
	OCELOT_STAT(RX_PMAC_1024_1526),
	OCELOT_STAT(RX_PMAC_1527_MAX),
	OCELOT_STAT(RX_PMAC_PAUSE),
	OCELOT_STAT(RX_PMAC_CONTROL),
	OCELOT_STAT(RX_PMAC_LONGS),
	OCELOT_STAT(TX_PMAC_OCTETS),
	OCELOT_STAT(TX_PMAC_UNICAST),
	OCELOT_STAT(TX_PMAC_MULTICAST),
	OCELOT_STAT(TX_PMAC_BROADCAST),
	OCELOT_STAT(TX_PMAC_PAUSE),
	OCELOT_STAT(TX_PMAC_64),
	OCELOT_STAT(TX_PMAC_65_127),
	OCELOT_STAT(TX_PMAC_128_255),
	OCELOT_STAT(TX_PMAC_256_511),
	OCELOT_STAT(TX_PMAC_512_1023),
	OCELOT_STAT(TX_PMAC_1024_1526),
	OCELOT_STAT(TX_PMAC_1527_MAX),
};

I would like to keep the flexibility of defining the counters in this
way without too much regard for:
- the order in which they are listed in enum ocelot_stat
- the order in which they are listed in the struct ocelot_stat_layout array
- the value of the SYS_COUNT_* of their underlying register address

However I'd still like to have a way in which I can index ocelot->stats
when I know specifically what I am looking for.

I think in practice this means that ocelot_prepare_stats_regions() would
need to be modified to first sort the ocelot_stat_layout array by "reg"
value (to keep bulking efficient), and then, I think I'd have to keep to
introduce another array of u32 *ocelot->stat_indices (to keep specific
indexing possible). Then I'd have to go through one extra layer of
indirection; RX_OCTETS would be available at

ocelot->stats[port * OCELOT_NUM_STATS + ocelot->stat_indices[OCELOT_STAT_RX_OCTETS]].

(I can wrap this behind a helper, of course)

This is a bit complicated, but I'm not aware of something simpler that
would do what you want and what I want. What are your thoughts?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 11:06     ` Vladimir Oltean
@ 2022-08-17 13:05       ` Vladimir Oltean
  2022-08-17 15:14         ` Colin Foster
  0 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-17 13:05 UTC (permalink / raw)
  To: Colin Foster
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 02:06:44PM +0300, Vladimir Oltean wrote:
> I think in practice this means that ocelot_prepare_stats_regions() would
> need to be modified to first sort the ocelot_stat_layout array by "reg"
> value (to keep bulking efficient), and then, I think I'd have to keep to
> introduce another array of u32 *ocelot->stat_indices (to keep specific
> indexing possible). Then I'd have to go through one extra layer of
> indirection; RX_OCTETS would be available at
> 
> ocelot->stats[port * OCELOT_NUM_STATS + ocelot->stat_indices[OCELOT_STAT_RX_OCTETS]].
> 
> (I can wrap this behind a helper, of course)
> 
> This is a bit complicated, but I'm not aware of something simpler that
> would do what you want and what I want. What are your thoughts?

Or simpler, we can keep enum ocelot_stat sorted in ascending order of
the associated SYS_COUNT_* register addresses. That should be very much
possible, we just need to add a comment to watch out for that. Between
switch revisions, the counter relative ordering won't differ. It's just
that RX and TX counters have a larger space between each other.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 13:05       ` Vladimir Oltean
@ 2022-08-17 15:14         ` Colin Foster
  2022-08-17 17:42           ` Vladimir Oltean
  0 siblings, 1 reply; 20+ messages in thread
From: Colin Foster @ 2022-08-17 15:14 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 01:05:32PM +0000, Vladimir Oltean wrote:
> On Wed, Aug 17, 2022 at 02:06:44PM +0300, Vladimir Oltean wrote:
> > I think in practice this means that ocelot_prepare_stats_regions() would
> > need to be modified to first sort the ocelot_stat_layout array by "reg"
> > value (to keep bulking efficient), and then, I think I'd have to keep to
> > introduce another array of u32 *ocelot->stat_indices (to keep specific
> > indexing possible). Then I'd have to go through one extra layer of
> > indirection; RX_OCTETS would be available at
> > 
> > ocelot->stats[port * OCELOT_NUM_STATS + ocelot->stat_indices[OCELOT_STAT_RX_OCTETS]].
> > 
> > (I can wrap this behind a helper, of course)
> > 
> > This is a bit complicated, but I'm not aware of something simpler that
> > would do what you want and what I want. What are your thoughts?
> 
> Or simpler, we can keep enum ocelot_stat sorted in ascending order of
> the associated SYS_COUNT_* register addresses. That should be very much
> possible, we just need to add a comment to watch out for that. Between
> switch revisions, the counter relative ordering won't differ. It's just
> that RX and TX counters have a larger space between each other.

That's what I thought was done... enum order == register order. But
that's a subtle, currently undocumented "feature" of my implementation
of the bulk reads. Also, it now relies on the fact that register order
is the same between hardware products - that's the new requirement that
I'm addressing.

I agree it would be nice to not require specific ordering, either in the
display order of `ethtool -S` or the definition order of enum
ocelot_stat. That's telling me that at some point someone (likely me?)
should probably write a sorting routine to guarantee optimized reads,
regardless of how they're defined or if there are common / unique
register sets.

The good thing about the current implementation is that the worst case
scenario is it will just fall back to the original behavior. That was
intentional.



Tangentially related: I'm having a heck of a time getting the QSGMII
connection to the VSC8514 working correctly. I plan to write a tool to
print out human-readable register names. Am I right to assume this is
the job of a userspace application, translating the output of
/sys/kernel/debug/regmap/ reads to their datasheet-friendly names, and
not something that belongs in some sort of sysfs interface? I took a
peek at mv88e6xxx_dump but it didn't seem to be what I was looking for.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 15:14         ` Colin Foster
@ 2022-08-17 17:42           ` Vladimir Oltean
  2022-08-17 20:47             ` Colin Foster
  0 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-17 17:42 UTC (permalink / raw)
  To: Colin Foster
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 08:14:09AM -0700, Colin Foster wrote:
> On Wed, Aug 17, 2022 at 01:05:32PM +0000, Vladimir Oltean wrote:
> > On Wed, Aug 17, 2022 at 02:06:44PM +0300, Vladimir Oltean wrote:
> > > I think in practice this means that ocelot_prepare_stats_regions() would
> > > need to be modified to first sort the ocelot_stat_layout array by "reg"
> > > value (to keep bulking efficient), and then, I think I'd have to keep to
> > > introduce another array of u32 *ocelot->stat_indices (to keep specific
> > > indexing possible). Then I'd have to go through one extra layer of
> > > indirection; RX_OCTETS would be available at
> > > 
> > > ocelot->stats[port * OCELOT_NUM_STATS + ocelot->stat_indices[OCELOT_STAT_RX_OCTETS]].
> > > 
> > > (I can wrap this behind a helper, of course)
> > > 
> > > This is a bit complicated, but I'm not aware of something simpler that
> > > would do what you want and what I want. What are your thoughts?
> > 
> > Or simpler, we can keep enum ocelot_stat sorted in ascending order of
> > the associated SYS_COUNT_* register addresses. That should be very much
> > possible, we just need to add a comment to watch out for that. Between
> > switch revisions, the counter relative ordering won't differ. It's just
> > that RX and TX counters have a larger space between each other.
> 
> That's what I thought was done... enum order == register order. But
> that's a subtle, currently undocumented "feature" of my implementation
> of the bulk reads. Also, it now relies on the fact that register order
> is the same between hardware products - that's the new requirement that
> I'm addressing.
> 
> I agree it would be nice to not require specific ordering, either in the
> display order of `ethtool -S` or the definition order of enum
> ocelot_stat. That's telling me that at some point someone (likely me?)
> should probably write a sorting routine to guarantee optimized reads,
> regardless of how they're defined or if there are common / unique
> register sets.
> 
> The good thing about the current implementation is that the worst case
> scenario is it will just fall back to the original behavior. That was
> intentional.

How about we add this extra check?

diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c
index d39908c1c6c9..85259de86ec2 100644
--- a/drivers/net/ethernet/mscc/ocelot_stats.c
+++ b/drivers/net/ethernet/mscc/ocelot_stats.c
@@ -385,7 +385,7 @@ EXPORT_SYMBOL(ocelot_port_get_stats64);
 static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
 {
 	struct ocelot_stats_region *region = NULL;
-	unsigned int last;
+	unsigned int last = 0;
 	int i;
 
 	INIT_LIST_HEAD(&ocelot->stats_regions);
@@ -402,6 +402,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
 			if (!region)
 				return -ENOMEM;
 
+			/* enum ocelot_stat must be kept sorted in the same
+			 * order as ocelot->stats_layout[i].reg in order to
+			 * have efficient bulking.
+			 */
+			WARN_ON(last >= ocelot->stats_layout[i].reg);
+
 			region->base = ocelot->stats_layout[i].reg;
 			region->count = 1;
 			list_add_tail(&region->node, &ocelot->stats_regions);

If not, help me understand the concern better.

> Tangentially related: I'm having a heck of a time getting the QSGMII
> connection to the VSC8514 working correctly. I plan to write a tool to
> print out human-readable register names. Am I right to assume this is
> the job of a userspace application, translating the output of
> /sys/kernel/debug/regmap/ reads to their datasheet-friendly names, and
> not something that belongs in some sort of sysfs interface? I took a
> peek at mv88e6xxx_dump but it didn't seem to be what I was looking for.

Why is the mv88e6xxx_dump kind of program (using devlink regions) not
what you're looking for?

There's also ethtool --register-dump which some DSA drivers have support
for (again, mv88e6xxx), but I think that's mainly per port.

I tried to add support for devlink regions to dump the PGIDs, but doing
this from the common ocelot switch lib is a PITA, because in the devlink
callbacks, we need to access the struct ocelot *ocelot from the
struct devlink *devlink. But DSA keeps the devlink pointer one way, and
the ocelot switchdev driver another. To know how to retrieve the ocelot
pointer from the devlink pointer, you'd need to know where to search for it.

So I'm thinking, if we add devlink regions to ocelot, it would be just
for DSA for now.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 17:42           ` Vladimir Oltean
@ 2022-08-17 20:47             ` Colin Foster
  2022-08-17 22:03               ` Vladimir Oltean
  0 siblings, 1 reply; 20+ messages in thread
From: Colin Foster @ 2022-08-17 20:47 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 05:42:27PM +0000, Vladimir Oltean wrote:
> On Wed, Aug 17, 2022 at 08:14:09AM -0700, Colin Foster wrote:
> > On Wed, Aug 17, 2022 at 01:05:32PM +0000, Vladimir Oltean wrote:
> > > On Wed, Aug 17, 2022 at 02:06:44PM +0300, Vladimir Oltean wrote:
> > > > I think in practice this means that ocelot_prepare_stats_regions() would
> > > > need to be modified to first sort the ocelot_stat_layout array by "reg"
> > > > value (to keep bulking efficient), and then, I think I'd have to keep to
> > > > introduce another array of u32 *ocelot->stat_indices (to keep specific
> > > > indexing possible). Then I'd have to go through one extra layer of
> > > > indirection; RX_OCTETS would be available at
> > > > 
> > > > ocelot->stats[port * OCELOT_NUM_STATS + ocelot->stat_indices[OCELOT_STAT_RX_OCTETS]].
> > > > 
> > > > (I can wrap this behind a helper, of course)
> > > > 
> > > > This is a bit complicated, but I'm not aware of something simpler that
> > > > would do what you want and what I want. What are your thoughts?
> > > 
> > > Or simpler, we can keep enum ocelot_stat sorted in ascending order of
> > > the associated SYS_COUNT_* register addresses. That should be very much
> > > possible, we just need to add a comment to watch out for that. Between
> > > switch revisions, the counter relative ordering won't differ. It's just
> > > that RX and TX counters have a larger space between each other.
> > 
> > That's what I thought was done... enum order == register order. But
> > that's a subtle, currently undocumented "feature" of my implementation
> > of the bulk reads. Also, it now relies on the fact that register order
> > is the same between hardware products - that's the new requirement that
> > I'm addressing.
> > 
> > I agree it would be nice to not require specific ordering, either in the
> > display order of `ethtool -S` or the definition order of enum
> > ocelot_stat. That's telling me that at some point someone (likely me?)
> > should probably write a sorting routine to guarantee optimized reads,
> > regardless of how they're defined or if there are common / unique
> > register sets.
> > 
> > The good thing about the current implementation is that the worst case
> > scenario is it will just fall back to the original behavior. That was
> > intentional.
> 
> How about we add this extra check?
> 
> diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c
> index d39908c1c6c9..85259de86ec2 100644
> --- a/drivers/net/ethernet/mscc/ocelot_stats.c
> +++ b/drivers/net/ethernet/mscc/ocelot_stats.c
> @@ -385,7 +385,7 @@ EXPORT_SYMBOL(ocelot_port_get_stats64);
>  static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
>  {
>  	struct ocelot_stats_region *region = NULL;
> -	unsigned int last;
> +	unsigned int last = 0;
>  	int i;
>  
>  	INIT_LIST_HEAD(&ocelot->stats_regions);
> @@ -402,6 +402,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
>  			if (!region)
>  				return -ENOMEM;
>  
> +			/* enum ocelot_stat must be kept sorted in the same
> +			 * order as ocelot->stats_layout[i].reg in order to
> +			 * have efficient bulking.
> +			 */
> +			WARN_ON(last >= ocelot->stats_layout[i].reg);
> +
>  			region->base = ocelot->stats_layout[i].reg;
>  			region->count = 1;
>  			list_add_tail(&region->node, &ocelot->stats_regions);
> 
> If not, help me understand the concern better.

You get my concern. That's a good comment / addition. Gaps are welcome
in the register layout, but moving backwards will ensure (in the current
implementation) inefficiencies.

> 
> > Tangentially related: I'm having a heck of a time getting the QSGMII
> > connection to the VSC8514 working correctly. I plan to write a tool to
> > print out human-readable register names. Am I right to assume this is
> > the job of a userspace application, translating the output of
> > /sys/kernel/debug/regmap/ reads to their datasheet-friendly names, and
> > not something that belongs in some sort of sysfs interface? I took a
> > peek at mv88e6xxx_dump but it didn't seem to be what I was looking for.
> 
> Why is the mv88e6xxx_dump kind of program (using devlink regions) not
> what you're looking for?

I suspect the issue I'm seeing is that there's something wrong with the
HSIO registers that control the QSGMII interface between the 7512 and
the 8514. Possibly something with PLL configuration / calibration? I
don't really know yet, and bouncing between the source
(ocelot_vsc7514.c, {felix,ocelot-ext}.c, phy-ocelot-serdes.c), the
reference design software, and the datasheet is slowing me down quite a
bit. Unless I am mistaken, it feels like the problems I'm chasing down
are at the register <> datasheet interface and not something exposed
through any existing interfaces.

I plan to get some internal support on that front that can hopefully
point me in the right direction, or find what I have set up incorrectly.
Otherwise it probably doesn't even make sense to send out anything for
review until the MFD set gets accepted. Though maybe I'm wrong there.

I'd also like to try to keep my patch version count down to one nibble
next time, so I'm planning on keeping ports 0-3 and ports 4-7+ in
separate patch sets :D

> 
> There's also ethtool --register-dump which some DSA drivers have support
> for (again, mv88e6xxx), but I think that's mainly per port.
> 
> I tried to add support for devlink regions to dump the PGIDs, but doing
> this from the common ocelot switch lib is a PITA, because in the devlink
> callbacks, we need to access the struct ocelot *ocelot from the
> struct devlink *devlink. But DSA keeps the devlink pointer one way, and
> the ocelot switchdev driver another. To know how to retrieve the ocelot
> pointer from the devlink pointer, you'd need to know where to search for it.
> 
> So I'm thinking, if we add devlink regions to ocelot, it would be just
> for DSA for now.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 20:47             ` Colin Foster
@ 2022-08-17 22:03               ` Vladimir Oltean
  2022-08-17 22:07                 ` Colin Foster
  2022-08-18  6:01                 ` Colin Foster
  0 siblings, 2 replies; 20+ messages in thread
From: Vladimir Oltean @ 2022-08-17 22:03 UTC (permalink / raw)
  To: Colin Foster
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 01:47:07PM -0700, Colin Foster wrote:
> > How about we add this extra check?
> > 
> > diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c
> > index d39908c1c6c9..85259de86ec2 100644
> > --- a/drivers/net/ethernet/mscc/ocelot_stats.c
> > +++ b/drivers/net/ethernet/mscc/ocelot_stats.c
> > @@ -385,7 +385,7 @@ EXPORT_SYMBOL(ocelot_port_get_stats64);
> >  static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
> >  {
> >  	struct ocelot_stats_region *region = NULL;
> > -	unsigned int last;
> > +	unsigned int last = 0;
> >  	int i;
> >  
> >  	INIT_LIST_HEAD(&ocelot->stats_regions);
> > @@ -402,6 +402,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
> >  			if (!region)
> >  				return -ENOMEM;
> >  
> > +			/* enum ocelot_stat must be kept sorted in the same
> > +			 * order as ocelot->stats_layout[i].reg in order to
> > +			 * have efficient bulking.
> > +			 */
> > +			WARN_ON(last >= ocelot->stats_layout[i].reg);
> > +
> >  			region->base = ocelot->stats_layout[i].reg;
> >  			region->count = 1;
> >  			list_add_tail(&region->node, &ocelot->stats_regions);
> > 
> > If not, help me understand the concern better.
> 
> You get my concern. That's a good comment / addition. Gaps are welcome
> in the register layout, but moving backwards will ensure (in the current
> implementation) inefficiencies.

Ok. The WARN_ON() won't trigger with current code. Do you mind if I add
it as a net-next change, and don't resend this series for net? I'm
worried I'll miss this week's "net" pull request which means I'll have
to wait some more for the other rework surrounding stats handling in the
ocelot driver (which in turn is a dependency for frame preemption).

> > 
> > > Tangentially related: I'm having a heck of a time getting the QSGMII
> > > connection to the VSC8514 working correctly. I plan to write a tool to
> > > print out human-readable register names. Am I right to assume this is
> > > the job of a userspace application, translating the output of
> > > /sys/kernel/debug/regmap/ reads to their datasheet-friendly names, and
> > > not something that belongs in some sort of sysfs interface? I took a
> > > peek at mv88e6xxx_dump but it didn't seem to be what I was looking for.
> > 
> > Why is the mv88e6xxx_dump kind of program (using devlink regions) not
> > what you're looking for?
> 
> I suspect the issue I'm seeing is that there's something wrong with the
> HSIO registers that control the QSGMII interface between the 7512 and
> the 8514. Possibly something with PLL configuration / calibration? I
> don't really know yet, and bouncing between the source
> (ocelot_vsc7514.c, {felix,ocelot-ext}.c, phy-ocelot-serdes.c), the
> reference design software, and the datasheet is slowing me down quite a
> bit. Unless I am mistaken, it feels like the problems I'm chasing down
> are at the register <> datasheet interface and not something exposed
> through any existing interfaces.

So you mean you suspect that the HSIO register definitions are somehow
wrong? You mean the phy-ocelot-serdes.c driver seems to behave strangely
in a way that could possibly indicate it's accessing the wrong stuff?
Do you have any indication that this is the case? I'm not familiar at
all with blocks that weren't instantiated on NXP hardware (we have our
own SERDES), and I see you're already monitoring the right source files,
so I'm afraid there isn't much that I can help you with.

> I plan to get some internal support on that front that can hopefully
> point me in the right direction, or find what I have set up incorrectly.
> Otherwise it probably doesn't even make sense to send out anything for
> review until the MFD set gets accepted. Though maybe I'm wrong there.

IDK, if you have a concrete description of the problem, I suppose the
contributors to the SERDES driver may be able to come up with a
suggestion or two?

I suggest you try to cover all bases; is the HSIO PLL locked and at the
right frequency for QSGMII? Does the lane acquire CDR lock? Are in-band
autoneg settings in sync between the PCS and the PHY? Does the PCS
report link up?

> I'd also like to try to keep my patch version count down to one nibble
> next time, so I'm planning on keeping ports 0-3 and ports 4-7+ in
> separate patch sets :D

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 22:03               ` Vladimir Oltean
@ 2022-08-17 22:07                 ` Colin Foster
  2022-08-18  6:01                 ` Colin Foster
  1 sibling, 0 replies; 20+ messages in thread
From: Colin Foster @ 2022-08-17 22:07 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 10:03:51PM +0000, Vladimir Oltean wrote:
> On Wed, Aug 17, 2022 at 01:47:07PM -0700, Colin Foster wrote:
> > > How about we add this extra check?
> > > 
> > > diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c
> > > index d39908c1c6c9..85259de86ec2 100644
> > > --- a/drivers/net/ethernet/mscc/ocelot_stats.c
> > > +++ b/drivers/net/ethernet/mscc/ocelot_stats.c
> > > @@ -385,7 +385,7 @@ EXPORT_SYMBOL(ocelot_port_get_stats64);
> > >  static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
> > >  {
> > >  	struct ocelot_stats_region *region = NULL;
> > > -	unsigned int last;
> > > +	unsigned int last = 0;
> > >  	int i;
> > >  
> > >  	INIT_LIST_HEAD(&ocelot->stats_regions);
> > > @@ -402,6 +402,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
> > >  			if (!region)
> > >  				return -ENOMEM;
> > >  
> > > +			/* enum ocelot_stat must be kept sorted in the same
> > > +			 * order as ocelot->stats_layout[i].reg in order to
> > > +			 * have efficient bulking.
> > > +			 */
> > > +			WARN_ON(last >= ocelot->stats_layout[i].reg);
> > > +
> > >  			region->base = ocelot->stats_layout[i].reg;
> > >  			region->count = 1;
> > >  			list_add_tail(&region->node, &ocelot->stats_regions);
> > > 
> > > If not, help me understand the concern better.
> > 
> > You get my concern. That's a good comment / addition. Gaps are welcome
> > in the register layout, but moving backwards will ensure (in the current
> > implementation) inefficiencies.
> 
> Ok. The WARN_ON() won't trigger with current code. Do you mind if I add
> it as a net-next change, and don't resend this series for net? I'm
> worried I'll miss this week's "net" pull request which means I'll have
> to wait some more for the other rework surrounding stats handling in the
> ocelot driver (which in turn is a dependency for frame preemption).

No objections here.

I'll respond in more detail to your other points in a separate email.
Might not be able to craft a response today.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 0/8] Fixes for Ocelot driver statistics
  2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
                   ` (7 preceding siblings ...)
  2022-08-16 13:53 ` [PATCH net 8/8] net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats Vladimir Oltean
@ 2022-08-18  5:20 ` patchwork-bot+netdevbpf
  8 siblings, 0 replies; 20+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-08-18  5:20 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, andrew, vivien.didelot, f.fainelli, claudiu.manoil,
	alexandre.belloni, UNGLinuxDriver, davem, edumazet, kuba, pabeni,
	colin.foster, fido_max

Hello:

This series was applied to netdev/net.git (master)
by Jakub Kicinski <kuba@kernel.org>:

On Tue, 16 Aug 2022 16:53:44 +0300 you wrote:
> This series contains bug fixes for the ocelot drivers (both switchdev
> and DSA). Some concern the counters exposed to ethtool -S, and others to
> the counters exposed to ifconfig. I'm aware that the changes are fairly
> large, but I wanted to prioritize on a proper approach to addressing the
> issues rather than a quick hack.
> 
> Some of the noticed problems:
> - bad register offsets for some counters
> - unhandled concurrency leading to corrupted counters
> - unhandled 32-bit wraparound of ifconfig counters
> 
> [...]

Here is the summary with links:
  - [net,1/8] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters
    https://git.kernel.org/netdev/net/c/40d21c4565bc
  - [net,2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 packet counters
    https://git.kernel.org/netdev/net/c/5152de7b79ab
  - [net,3/8] net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter
    https://git.kernel.org/netdev/net/c/173ca86618d7
  - [net,4/8] net: mscc: ocelot: turn stats_lock into a spinlock
    https://git.kernel.org/netdev/net/c/22d842e3efe5
  - [net,5/8] net: mscc: ocelot: fix race between ndo_get_stats64 and ocelot_check_stats_work
    https://git.kernel.org/netdev/net/c/18d8e67df184
  - [net,6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
    https://git.kernel.org/netdev/net/c/9190460084dd
  - [net,7/8] net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset
    https://git.kernel.org/netdev/net/c/d4c367650704
  - [net,8/8] net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats
    https://git.kernel.org/netdev/net/c/e780e3193e88

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable
  2022-08-17 22:03               ` Vladimir Oltean
  2022-08-17 22:07                 ` Colin Foster
@ 2022-08-18  6:01                 ` Colin Foster
  1 sibling, 0 replies; 20+ messages in thread
From: Colin Foster @ 2022-08-18  6:01 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxim Kochetkov

On Wed, Aug 17, 2022 at 10:03:51PM +0000, Vladimir Oltean wrote:
> On Wed, Aug 17, 2022 at 01:47:07PM -0700, Colin Foster wrote:
> > > > Tangentially related: I'm having a heck of a time getting the QSGMII
> > > > connection to the VSC8514 working correctly. I plan to write a tool to
> > > > print out human-readable register names. Am I right to assume this is
> > > > the job of a userspace application, translating the output of
> > > > /sys/kernel/debug/regmap/ reads to their datasheet-friendly names, and
> > > > not something that belongs in some sort of sysfs interface? I took a
> > > > peek at mv88e6xxx_dump but it didn't seem to be what I was looking for.
> > > 
> > > Why is the mv88e6xxx_dump kind of program (using devlink regions) not
> > > what you're looking for?
> > 
> > I suspect the issue I'm seeing is that there's something wrong with the
> > HSIO registers that control the QSGMII interface between the 7512 and
> > the 8514. Possibly something with PLL configuration / calibration? I
> > don't really know yet, and bouncing between the source
> > (ocelot_vsc7514.c, {felix,ocelot-ext}.c, phy-ocelot-serdes.c), the
> > reference design software, and the datasheet is slowing me down quite a
> > bit. Unless I am mistaken, it feels like the problems I'm chasing down
> > are at the register <> datasheet interface and not something exposed
> > through any existing interfaces.
> 
> So you mean you suspect that the HSIO register definitions are somehow
> wrong? You mean the phy-ocelot-serdes.c driver seems to behave strangely
> in a way that could possibly indicate it's accessing the wrong stuff?
> Do you have any indication that this is the case? I'm not familiar at
> all with blocks that weren't instantiated on NXP hardware (we have our
> own SERDES), and I see you're already monitoring the right source files,
> so I'm afraid there isn't much that I can help you with.

So I was crafting my response with an explanation of how I'd gotten to
where I was (starting in the footsteps of ocelot_vsc7512.c). Of course,
while trying to explain that, a couple things jumped out at me to try.

Long story short, phylink_ops wasn't getting invoked by anything. In
ocelot_vsc7512.c they get invoked by the net_device (I think) but in
ocelot-ext, while they were registered to the phylink, only the
felix pcs_config (and other phylink_pcs_ops). I had all the pieces,
but just didn't tie them all together.

So my current status is there's at least some full communication between
the 7512 and the 8514 to the external ports. I'll do some more thorough
testing as well. Now that I have more than 3 ports, I should be able to
run more of the elaborate kernel test scenarios. But also I'll have to
do a lot more validation and testing.


Thanks for the hints Vladimir! And for being helpful in this rubber-duck
debugging session :-)

> 
> > I plan to get some internal support on that front that can hopefully
> > point me in the right direction, or find what I have set up incorrectly.
> > Otherwise it probably doesn't even make sense to send out anything for
> > review until the MFD set gets accepted. Though maybe I'm wrong there.
> 
> IDK, if you have a concrete description of the problem, I suppose the
> contributors to the SERDES driver may be able to come up with a
> suggestion or two?
> 
> I suggest you try to cover all bases; is the HSIO PLL locked and at the
> right frequency for QSGMII? Does the lane acquire CDR lock? Are in-band
> autoneg settings in sync between the PCS and the PHY? Does the PCS
> report link up?
> 
> > I'd also like to try to keep my patch version count down to one nibble
> > next time, so I'm planning on keeping ports 0-3 and ports 4-7+ in
> > separate patch sets :D

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2022-08-18  6:02 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-16 13:53 [PATCH net 0/8] Fixes for Ocelot driver statistics Vladimir Oltean
2022-08-16 13:53 ` [PATCH net 1/8] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters Vladimir Oltean
2022-08-16 13:53 ` [PATCH net 2/8] net: mscc: ocelot: fix incorrect ndo_get_stats64 " Vladimir Oltean
2022-08-17  6:26   ` Colin Foster
2022-08-16 13:53 ` [PATCH net 3/8] net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter Vladimir Oltean
2022-08-16 13:53 ` [PATCH net 4/8] net: mscc: ocelot: turn stats_lock into a spinlock Vladimir Oltean
2022-08-16 13:53 ` [PATCH net 5/8] net: mscc: ocelot: fix race between ndo_get_stats64 and ocelot_check_stats_work Vladimir Oltean
2022-08-16 13:53 ` [PATCH net 6/8] net: mscc: ocelot: make struct ocelot_stat_layout array indexable Vladimir Oltean
2022-08-17  6:46   ` Colin Foster
2022-08-17 11:06     ` Vladimir Oltean
2022-08-17 13:05       ` Vladimir Oltean
2022-08-17 15:14         ` Colin Foster
2022-08-17 17:42           ` Vladimir Oltean
2022-08-17 20:47             ` Colin Foster
2022-08-17 22:03               ` Vladimir Oltean
2022-08-17 22:07                 ` Colin Foster
2022-08-18  6:01                 ` Colin Foster
2022-08-16 13:53 ` [PATCH net 7/8] net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset Vladimir Oltean
2022-08-16 13:53 ` [PATCH net 8/8] net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats Vladimir Oltean
2022-08-18  5:20 ` [PATCH net 0/8] Fixes for Ocelot driver statistics patchwork-bot+netdevbpf

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.