public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v3 0/2] net: dsa: yt921x: Use u64_stats_t for MIB stats
@ 2026-02-27 13:50 David Yang
  2026-02-27 13:50 ` [PATCH net-next v3 1/2] net: dsa: yt921x: Return early for failed MIB read David Yang
  2026-02-27 13:50 ` [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
  0 siblings, 2 replies; 6+ messages in thread
From: David Yang @ 2026-02-27 13:50 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel

Avoid load/store tearing of 64-bit values on 32-bit architectures.

v2: https://lore.kernel.org/r/20260224112411.1561917-1-mmyangfl@gmail.com
  - git rid of print_port_err()
  - remove unused variable
v1: https://lore.kernel.org/r/20260203171305.95085-1-mmyangfl@gmail.com
  - use functions instead of macros
  - rework commit message
  - hold lock for stats when possible
v0:
  - Sending remaining part of
    https://lore.kernel.org/r/20260118013019.1078847-1-mmyangfl@gmail.com

David Yang (2):
  net: dsa: yt921x: Return early for failed MIB read
  net: dsa: yt921x: Use u64_stats_t for MIB stats

 drivers/net/dsa/yt921x.c | 206 +++++++++++++++++++++++----------------
 drivers/net/dsa/yt921x.h | 114 ++++++++++++----------
 2 files changed, 184 insertions(+), 136 deletions(-)

-- 
2.51.0


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

* [PATCH net-next v3 1/2] net: dsa: yt921x: Return early for failed MIB read
  2026-02-27 13:50 [PATCH net-next v3 0/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
@ 2026-02-27 13:50 ` David Yang
  2026-03-03 11:34   ` Simon Horman
  2026-02-27 13:50 ` [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
  1 sibling, 1 reply; 6+ messages in thread
From: David Yang @ 2026-02-27 13:50 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel

This is a prerequisite for another patch. It does not change the
behavior on the success path.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/yt921x.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index 98e8915dd6c2..a968a3fb56f8 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -711,6 +711,12 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
 		WRITE_ONCE(*valp, val);
 	}
 
+	if (res) {
+		dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
+			port, res);
+		return res;
+	}
+
 	pp->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
 			mib->rx_128_255byte + mib->rx_256_511byte +
 			mib->rx_512_1023byte + mib->rx_1024_1518byte +
@@ -720,10 +726,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
 			mib->tx_512_1023byte + mib->tx_1024_1518byte +
 			mib->tx_jumbo;
 
-	if (res)
-		dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
-			port, res);
-	return res;
+	return 0;
 }
 
 static void yt921x_poll_mib(struct work_struct *work)
-- 
2.51.0


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

* [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats
  2026-02-27 13:50 [PATCH net-next v3 0/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
  2026-02-27 13:50 ` [PATCH net-next v3 1/2] net: dsa: yt921x: Return early for failed MIB read David Yang
@ 2026-02-27 13:50 ` David Yang
  2026-03-03 11:31   ` Simon Horman
  2026-03-03 11:40   ` Paolo Abeni
  1 sibling, 2 replies; 6+ messages in thread
From: David Yang @ 2026-02-27 13:50 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel

64-bit variables might not be atomic on 32-bit architectures, and could
lead to load/store tearing. Use u64_stats_t to ensure consistency.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/yt921x.c | 197 +++++++++++++++++++++++----------------
 drivers/net/dsa/yt921x.h | 114 ++++++++++++----------
 2 files changed, 178 insertions(+), 133 deletions(-)

diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index a968a3fb56f8..8129c278e224 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -20,6 +20,7 @@
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/sort.h>
+#include <linux/u64_stats_sync.h>
 
 #include <net/dsa.h>
 #include <net/dscp.h>
@@ -670,22 +671,20 @@ yt921x_mbus_ext_init(struct yt921x_priv *priv, struct device_node *mnp)
 static int yt921x_read_mib(struct yt921x_priv *priv, int port)
 {
 	struct yt921x_port *pp = &priv->ports[port];
+	struct yt921x_mib *mib_new = &pp->mib_new;
 	struct device *dev = to_device(priv);
 	struct yt921x_mib *mib = &pp->mib;
+	u64 rx_frames;
+	u64 tx_frames;
 	int res = 0;
 
-	/* Reading of yt921x_port::mib is not protected by a lock and it's vain
-	 * to keep its consistency, since we have to read registers one by one
-	 * and there is no way to make a snapshot of MIB stats.
-	 *
-	 * Writing (by this function only) is and should be protected by
-	 * reg_lock.
+	/* u64_stats_read/set is redundant for mib_new, but I don't want to
+	 * declare a plain u64 yt921x_mib variant.
 	 */
 
 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
 		const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
 		u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
-		u64 *valp = &((u64 *)mib)[i];
 		u32 val0;
 		u64 val;
 
@@ -694,7 +693,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
 			break;
 
 		if (desc->size <= 1) {
-			u64 old_val = *valp;
+			u64 old_val = u64_stats_read(&mib->stats[i]);
 
 			val = (old_val & ~(u64)U32_MAX) | val0;
 			if (val < old_val)
@@ -708,7 +707,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
 			val = ((u64)val1 << 32) | val0;
 		}
 
-		WRITE_ONCE(*valp, val);
+		u64_stats_set(&mib_new->stats[i], val);
 	}
 
 	if (res) {
@@ -717,14 +716,29 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
 		return res;
 	}
 
-	pp->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
-			mib->rx_128_255byte + mib->rx_256_511byte +
-			mib->rx_512_1023byte + mib->rx_1024_1518byte +
-			mib->rx_jumbo;
-	pp->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
-			mib->tx_128_255byte + mib->tx_256_511byte +
-			mib->tx_512_1023byte + mib->tx_1024_1518byte +
-			mib->tx_jumbo;
+	rx_frames = u64_stats_read(&mib_new->rx_64byte) +
+		    u64_stats_read(&mib_new->rx_65_127byte) +
+		    u64_stats_read(&mib_new->rx_128_255byte) +
+		    u64_stats_read(&mib_new->rx_256_511byte) +
+		    u64_stats_read(&mib_new->rx_512_1023byte) +
+		    u64_stats_read(&mib_new->rx_1024_1518byte) +
+		    u64_stats_read(&mib_new->rx_jumbo);
+	tx_frames = u64_stats_read(&mib_new->tx_64byte) +
+		    u64_stats_read(&mib_new->tx_65_127byte) +
+		    u64_stats_read(&mib_new->tx_128_255byte) +
+		    u64_stats_read(&mib_new->tx_256_511byte) +
+		    u64_stats_read(&mib_new->tx_512_1023byte) +
+		    u64_stats_read(&mib_new->tx_1024_1518byte) +
+		    u64_stats_read(&mib_new->tx_jumbo);
+
+	u64_stats_update_begin(&pp->syncp);
+	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
+		u64_stats_set(&mib->stats[i],
+			      u64_stats_read(&mib_new->stats[i]));
+	}
+	u64_stats_set(&pp->rx_frames, rx_frames);
+	u64_stats_set(&pp->tx_frames, tx_frames);
+	u64_stats_update_end(&pp->syncp);
 
 	return 0;
 }
@@ -772,8 +786,8 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
 	size_t j;
 
 	mutex_lock(&priv->reg_lock);
+
 	yt921x_read_mib(priv, port);
-	mutex_unlock(&priv->reg_lock);
 
 	j = 0;
 	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
@@ -782,9 +796,11 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
 		if (!desc->name)
 			continue;
 
-		data[j] = ((u64 *)mib)[i];
+		data[j] = u64_stats_read(&((u64_stats_t *)mib)[i]);
 		j++;
 	}
+
+	mutex_unlock(&priv->reg_lock);
 }
 
 static int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset)
@@ -813,31 +829,33 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
 	struct yt921x_mib *mib = &pp->mib;
 
 	mutex_lock(&priv->reg_lock);
+
 	yt921x_read_mib(priv, port);
-	mutex_unlock(&priv->reg_lock);
 
-	mac_stats->FramesTransmittedOK = pp->tx_frames;
-	mac_stats->SingleCollisionFrames = mib->tx_single_collisions;
-	mac_stats->MultipleCollisionFrames = mib->tx_multiple_collisions;
-	mac_stats->FramesReceivedOK = pp->rx_frames;
-	mac_stats->FrameCheckSequenceErrors = mib->rx_crc_errors;
-	mac_stats->AlignmentErrors = mib->rx_alignment_errors;
-	mac_stats->OctetsTransmittedOK = mib->tx_good_bytes;
-	mac_stats->FramesWithDeferredXmissions = mib->tx_deferred;
-	mac_stats->LateCollisions = mib->tx_late_collisions;
-	mac_stats->FramesAbortedDueToXSColls = mib->tx_aborted_errors;
+	mac_stats->FramesTransmittedOK = u64_stats_read(&pp->tx_frames);
+	mac_stats->SingleCollisionFrames = u64_stats_read(&mib->tx_single_collisions);
+	mac_stats->MultipleCollisionFrames = u64_stats_read(&mib->tx_multiple_collisions);
+	mac_stats->FramesReceivedOK = u64_stats_read(&pp->rx_frames);
+	mac_stats->FrameCheckSequenceErrors = u64_stats_read(&mib->rx_crc_errors);
+	mac_stats->AlignmentErrors = u64_stats_read(&mib->rx_alignment_errors);
+	mac_stats->OctetsTransmittedOK = u64_stats_read(&mib->tx_good_bytes);
+	mac_stats->FramesWithDeferredXmissions = u64_stats_read(&mib->tx_deferred);
+	mac_stats->LateCollisions = u64_stats_read(&mib->tx_late_collisions);
+	mac_stats->FramesAbortedDueToXSColls = u64_stats_read(&mib->tx_aborted_errors);
 	/* mac_stats->FramesLostDueToIntMACXmitError */
 	/* mac_stats->CarrierSenseErrors */
-	mac_stats->OctetsReceivedOK = mib->rx_good_bytes;
+	mac_stats->OctetsReceivedOK = u64_stats_read(&mib->rx_good_bytes);
 	/* mac_stats->FramesLostDueToIntMACRcvError */
-	mac_stats->MulticastFramesXmittedOK = mib->tx_multicast;
-	mac_stats->BroadcastFramesXmittedOK = mib->tx_broadcast;
+	mac_stats->MulticastFramesXmittedOK = u64_stats_read(&mib->tx_multicast);
+	mac_stats->BroadcastFramesXmittedOK = u64_stats_read(&mib->tx_broadcast);
 	/* mac_stats->FramesWithExcessiveDeferral */
-	mac_stats->MulticastFramesReceivedOK = mib->rx_multicast;
-	mac_stats->BroadcastFramesReceivedOK = mib->rx_broadcast;
+	mac_stats->MulticastFramesReceivedOK = u64_stats_read(&mib->rx_multicast);
+	mac_stats->BroadcastFramesReceivedOK = u64_stats_read(&mib->rx_broadcast);
 	/* mac_stats->InRangeLengthErrors */
 	/* mac_stats->OutOfRangeLengthField */
-	mac_stats->FrameTooLongErrors = mib->rx_oversize_errors;
+	mac_stats->FrameTooLongErrors = u64_stats_read(&mib->rx_oversize_errors);
+
+	mutex_unlock(&priv->reg_lock);
 }
 
 static void
@@ -849,12 +867,14 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
 	struct yt921x_mib *mib = &pp->mib;
 
 	mutex_lock(&priv->reg_lock);
+
 	yt921x_read_mib(priv, port);
-	mutex_unlock(&priv->reg_lock);
 
-	ctrl_stats->MACControlFramesTransmitted = mib->tx_pause;
-	ctrl_stats->MACControlFramesReceived = mib->rx_pause;
+	ctrl_stats->MACControlFramesTransmitted = u64_stats_read(&mib->tx_pause);
+	ctrl_stats->MACControlFramesReceived = u64_stats_read(&mib->rx_pause);
 	/* ctrl_stats->UnsupportedOpcodesReceived */
+
+	mutex_unlock(&priv->reg_lock);
 }
 
 static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = {
@@ -878,31 +898,33 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
 	struct yt921x_mib *mib = &pp->mib;
 
 	mutex_lock(&priv->reg_lock);
+
 	yt921x_read_mib(priv, port);
-	mutex_unlock(&priv->reg_lock);
 
 	*ranges = yt921x_rmon_ranges;
 
-	rmon_stats->undersize_pkts = mib->rx_undersize_errors;
-	rmon_stats->oversize_pkts = mib->rx_oversize_errors;
-	rmon_stats->fragments = mib->rx_alignment_errors;
+	rmon_stats->undersize_pkts = u64_stats_read(&mib->rx_undersize_errors);
+	rmon_stats->oversize_pkts = u64_stats_read(&mib->rx_oversize_errors);
+	rmon_stats->fragments = u64_stats_read(&mib->rx_alignment_errors);
 	/* rmon_stats->jabbers */
 
-	rmon_stats->hist[0] = mib->rx_64byte;
-	rmon_stats->hist[1] = mib->rx_65_127byte;
-	rmon_stats->hist[2] = mib->rx_128_255byte;
-	rmon_stats->hist[3] = mib->rx_256_511byte;
-	rmon_stats->hist[4] = mib->rx_512_1023byte;
-	rmon_stats->hist[5] = mib->rx_1024_1518byte;
-	rmon_stats->hist[6] = mib->rx_jumbo;
+	rmon_stats->hist[0] = u64_stats_read(&mib->rx_64byte);
+	rmon_stats->hist[1] = u64_stats_read(&mib->rx_65_127byte);
+	rmon_stats->hist[2] = u64_stats_read(&mib->rx_128_255byte);
+	rmon_stats->hist[3] = u64_stats_read(&mib->rx_256_511byte);
+	rmon_stats->hist[4] = u64_stats_read(&mib->rx_512_1023byte);
+	rmon_stats->hist[5] = u64_stats_read(&mib->rx_1024_1518byte);
+	rmon_stats->hist[6] = u64_stats_read(&mib->rx_jumbo);
+
+	rmon_stats->hist_tx[0] = u64_stats_read(&mib->tx_64byte);
+	rmon_stats->hist_tx[1] = u64_stats_read(&mib->tx_65_127byte);
+	rmon_stats->hist_tx[2] = u64_stats_read(&mib->tx_128_255byte);
+	rmon_stats->hist_tx[3] = u64_stats_read(&mib->tx_256_511byte);
+	rmon_stats->hist_tx[4] = u64_stats_read(&mib->tx_512_1023byte);
+	rmon_stats->hist_tx[5] = u64_stats_read(&mib->tx_1024_1518byte);
+	rmon_stats->hist_tx[6] = u64_stats_read(&mib->tx_jumbo);
 
-	rmon_stats->hist_tx[0] = mib->tx_64byte;
-	rmon_stats->hist_tx[1] = mib->tx_65_127byte;
-	rmon_stats->hist_tx[2] = mib->tx_128_255byte;
-	rmon_stats->hist_tx[3] = mib->tx_256_511byte;
-	rmon_stats->hist_tx[4] = mib->tx_512_1023byte;
-	rmon_stats->hist_tx[5] = mib->tx_1024_1518byte;
-	rmon_stats->hist_tx[6] = mib->tx_jumbo;
+	mutex_unlock(&priv->reg_lock);
 }
 
 static void
@@ -912,33 +934,41 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
 	struct yt921x_priv *priv = to_yt921x_priv(ds);
 	struct yt921x_port *pp = &priv->ports[port];
 	struct yt921x_mib *mib = &pp->mib;
+	unsigned int start;
+
+	do {
+		start = u64_stats_fetch_begin(&pp->syncp);
+
+		stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) +
+					  u64_stats_read(&mib->rx_fragment_errors);
+		stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors);
+		stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors);
+		stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors);
+		/* stats->rx_fifo_errors */
+		/* stats->rx_missed_errors */
+
+		stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors);
+		/* stats->tx_carrier_errors */
+		stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors);
+		/* stats->tx_heartbeat_errors */
+		stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions);
+
+		stats->rx_packets = u64_stats_read(&pp->rx_frames);
+		stats->tx_packets = u64_stats_read(&pp->tx_frames);
+		stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) -
+				  ETH_FCS_LEN * stats->rx_packets;
+		stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) -
+				  ETH_FCS_LEN * stats->tx_packets;
+		stats->rx_dropped = u64_stats_read(&mib->rx_dropped);
+		/* stats->tx_dropped */
+		stats->multicast = u64_stats_read(&mib->rx_multicast);
+		stats->collisions = u64_stats_read(&mib->tx_collisions);
+	} while (u64_stats_fetch_retry(&pp->syncp, start));
 
-	stats->rx_length_errors = mib->rx_undersize_errors +
-				  mib->rx_fragment_errors;
-	stats->rx_over_errors = mib->rx_oversize_errors;
-	stats->rx_crc_errors = mib->rx_crc_errors;
-	stats->rx_frame_errors = mib->rx_alignment_errors;
-	/* stats->rx_fifo_errors */
-	/* stats->rx_missed_errors */
-
-	stats->tx_aborted_errors = mib->tx_aborted_errors;
-	/* stats->tx_carrier_errors */
-	stats->tx_fifo_errors = mib->tx_undersize_errors;
-	/* stats->tx_heartbeat_errors */
-	stats->tx_window_errors = mib->tx_late_collisions;
-
-	stats->rx_packets = pp->rx_frames;
-	stats->tx_packets = pp->tx_frames;
-	stats->rx_bytes = mib->rx_good_bytes - ETH_FCS_LEN * stats->rx_packets;
-	stats->tx_bytes = mib->tx_good_bytes - ETH_FCS_LEN * stats->tx_packets;
 	stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
 			   stats->rx_crc_errors + stats->rx_frame_errors;
 	stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
 			   stats->tx_window_errors;
-	stats->rx_dropped = mib->rx_dropped;
-	/* stats->tx_dropped */
-	stats->multicast = mib->rx_multicast;
-	stats->collisions = mib->tx_collisions;
 }
 
 static void
@@ -950,11 +980,13 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
 	struct yt921x_mib *mib = &pp->mib;
 
 	mutex_lock(&priv->reg_lock);
+
 	yt921x_read_mib(priv, port);
-	mutex_unlock(&priv->reg_lock);
 
-	pause_stats->tx_pause_frames = mib->tx_pause;
-	pause_stats->rx_pause_frames = mib->rx_pause;
+	pause_stats->tx_pause_frames = u64_stats_read(&mib->tx_pause);
+	pause_stats->rx_pause_frames = u64_stats_read(&mib->rx_pause);
+
+	mutex_unlock(&priv->reg_lock);
 }
 
 static int
@@ -3423,6 +3455,7 @@ static int yt921x_mdio_probe(struct mdio_device *mdiodev)
 
 		pp->index = i;
 		INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib);
+		u64_stats_init(&pp->syncp);
 	}
 
 	ds = &priv->ds;
diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 3f129b8d403f..0f4231accf3e 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h
@@ -6,6 +6,8 @@
 #ifndef __YT921X_H
 #define __YT921X_H
 
+#include <linux/u64_stats_sync.h>
+
 #include <net/dsa.h>
 
 #define YT921X_SMI_SWITCHID_M		GENMASK(3, 2)
@@ -530,55 +532,61 @@ enum yt921x_fdb_entry_status {
 #define yt921x_port_is_external(port) (8 <= (port) && (port) < 9)
 
 struct yt921x_mib {
-	u64 rx_broadcast;
-	u64 rx_pause;
-	u64 rx_multicast;
-	u64 rx_crc_errors;
-
-	u64 rx_alignment_errors;
-	u64 rx_undersize_errors;
-	u64 rx_fragment_errors;
-	u64 rx_64byte;
-
-	u64 rx_65_127byte;
-	u64 rx_128_255byte;
-	u64 rx_256_511byte;
-	u64 rx_512_1023byte;
-
-	u64 rx_1024_1518byte;
-	u64 rx_jumbo;
-	u64 rx_good_bytes;
-
-	u64 rx_bad_bytes;
-	u64 rx_oversize_errors;
-
-	u64 rx_dropped;
-	u64 tx_broadcast;
-	u64 tx_pause;
-	u64 tx_multicast;
-
-	u64 tx_undersize_errors;
-	u64 tx_64byte;
-	u64 tx_65_127byte;
-	u64 tx_128_255byte;
-
-	u64 tx_256_511byte;
-	u64 tx_512_1023byte;
-	u64 tx_1024_1518byte;
-	u64 tx_jumbo;
-
-	u64 tx_good_bytes;
-	u64 tx_collisions;
-
-	u64 tx_aborted_errors;
-	u64 tx_multiple_collisions;
-	u64 tx_single_collisions;
-	u64 tx_good;
-
-	u64 tx_deferred;
-	u64 tx_late_collisions;
-	u64 rx_oam;
-	u64 tx_oam;
+	union {
+		struct {
+			u64_stats_t rx_broadcast;
+			u64_stats_t rx_pause;
+			u64_stats_t rx_multicast;
+			u64_stats_t rx_crc_errors;
+
+			u64_stats_t rx_alignment_errors;
+			u64_stats_t rx_undersize_errors;
+			u64_stats_t rx_fragment_errors;
+			u64_stats_t rx_64byte;
+
+			u64_stats_t rx_65_127byte;
+			u64_stats_t rx_128_255byte;
+			u64_stats_t rx_256_511byte;
+			u64_stats_t rx_512_1023byte;
+
+			u64_stats_t rx_1024_1518byte;
+			u64_stats_t rx_jumbo;
+			u64_stats_t rx_good_bytes;
+
+			u64_stats_t rx_bad_bytes;
+			u64_stats_t rx_oversize_errors;
+
+			u64_stats_t rx_dropped;
+			u64_stats_t tx_broadcast;
+			u64_stats_t tx_pause;
+			u64_stats_t tx_multicast;
+
+			u64_stats_t tx_undersize_errors;
+			u64_stats_t tx_64byte;
+			u64_stats_t tx_65_127byte;
+			u64_stats_t tx_128_255byte;
+
+			u64_stats_t tx_256_511byte;
+			u64_stats_t tx_512_1023byte;
+			u64_stats_t tx_1024_1518byte;
+			u64_stats_t tx_jumbo;
+
+			u64_stats_t tx_good_bytes;
+			u64_stats_t tx_collisions;
+
+			u64_stats_t tx_aborted_errors;
+			u64_stats_t tx_multiple_collisions;
+			u64_stats_t tx_single_collisions;
+			u64_stats_t tx_good;
+
+			u64_stats_t tx_deferred;
+			u64_stats_t tx_late_collisions;
+			u64_stats_t rx_oam;
+			u64_stats_t tx_oam;
+		};
+
+		u64_stats_t stats[39];
+	};
 };
 
 struct yt921x_port {
@@ -588,9 +596,13 @@ struct yt921x_port {
 	bool isolated;
 
 	struct delayed_work mib_read;
+	struct u64_stats_sync syncp;
 	struct yt921x_mib mib;
-	u64 rx_frames;
-	u64 tx_frames;
+	u64_stats_t rx_frames;
+	u64_stats_t tx_frames;
+
+	/* only used by read routine to avoid huge allocations on the stack */
+	struct yt921x_mib mib_new;
 };
 
 struct yt921x_reg_ops {
-- 
2.51.0


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

* Re: [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats
  2026-02-27 13:50 ` [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
@ 2026-03-03 11:31   ` Simon Horman
  2026-03-03 11:40   ` Paolo Abeni
  1 sibling, 0 replies; 6+ messages in thread
From: Simon Horman @ 2026-03-03 11:31 UTC (permalink / raw)
  To: David Yang
  Cc: netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel

On Fri, Feb 27, 2026 at 09:50:54PM +0800, David Yang wrote:
> 64-bit variables might not be atomic on 32-bit architectures, and could
> lead to load/store tearing. Use u64_stats_t to ensure consistency.
> 
> Signed-off-by: David Yang <mmyangfl@gmail.com>

...

> @@ -717,14 +716,29 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)

...

> +	u64_stats_update_begin(&pp->syncp);
> +	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
> +		u64_stats_set(&mib->stats[i],
> +			      u64_stats_read(&mib_new->stats[i]));
> +	}
> +	u64_stats_set(&pp->rx_frames, rx_frames);
> +	u64_stats_set(&pp->tx_frames, tx_frames);
> +	u64_stats_update_end(&pp->syncp);
>  
>  	return 0;
>  }

...

> @@ -782,9 +796,11 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
>  		if (!desc->name)
>  			continue;
>  
> -		data[j] = ((u64 *)mib)[i];
> +		data[j] = u64_stats_read(&((u64_stats_t *)mib)[i]);

Stats is available as a member of mib as an array of u64_stats_t.
So this code can avoid bypassing the type system with a cast.
And be consistent with an earlier change in this patch.

		data[j] = u64_stats_read(&mib->stats[i]);

>  		j++;
>  	}
> +
> +	mutex_unlock(&priv->reg_lock);
>  }

...

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

* Re: [PATCH net-next v3 1/2] net: dsa: yt921x: Return early for failed MIB read
  2026-02-27 13:50 ` [PATCH net-next v3 1/2] net: dsa: yt921x: Return early for failed MIB read David Yang
@ 2026-03-03 11:34   ` Simon Horman
  0 siblings, 0 replies; 6+ messages in thread
From: Simon Horman @ 2026-03-03 11:34 UTC (permalink / raw)
  To: David Yang
  Cc: netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel

On Fri, Feb 27, 2026 at 09:50:53PM +0800, David Yang wrote:
> This is a prerequisite for another patch. It does not change the
> behavior on the success path.

I think that you need to discuss what change this introduces
on the error path. And the AI generated review did too.

Looking a bit more, it seems that Jakub offered feedback on
this in his review of v1 [1]. I do see that the commit message
has been updated. And is strictly correct. But I think the intention
of Jakub's feedback was that the behaviour is changed should be described.

[1] https://lore.kernel.org/netdev/20260205050813.2421675-1-kuba@kernel.org/

> 
> Signed-off-by: David Yang <mmyangfl@gmail.com>

-- 
pw-bot: changes-requested.

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

* Re: [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats
  2026-02-27 13:50 ` [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
  2026-03-03 11:31   ` Simon Horman
@ 2026-03-03 11:40   ` Paolo Abeni
  1 sibling, 0 replies; 6+ messages in thread
From: Paolo Abeni @ 2026-03-03 11:40 UTC (permalink / raw)
  To: David Yang, netdev
  Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-kernel



On 2/27/26 2:50 PM, David Yang wrote:
> 64-bit variables might not be atomic on 32-bit architectures, and could
> lead to load/store tearing. Use u64_stats_t to ensure consistency.
> 
> Signed-off-by: David Yang <mmyangfl@gmail.com>
> ---
>  drivers/net/dsa/yt921x.c | 197 +++++++++++++++++++++++----------------
>  drivers/net/dsa/yt921x.h | 114 ++++++++++++----------
>  2 files changed, 178 insertions(+), 133 deletions(-)
> 
> diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
> index a968a3fb56f8..8129c278e224 100644
> --- a/drivers/net/dsa/yt921x.c
> +++ b/drivers/net/dsa/yt921x.c
> @@ -20,6 +20,7 @@
>  #include <linux/of_mdio.h>
>  #include <linux/of_net.h>
>  #include <linux/sort.h>
> +#include <linux/u64_stats_sync.h>
>  
>  #include <net/dsa.h>
>  #include <net/dscp.h>
> @@ -670,22 +671,20 @@ yt921x_mbus_ext_init(struct yt921x_priv *priv, struct device_node *mnp)
>  static int yt921x_read_mib(struct yt921x_priv *priv, int port)
>  {
>  	struct yt921x_port *pp = &priv->ports[port];
> +	struct yt921x_mib *mib_new = &pp->mib_new;
>  	struct device *dev = to_device(priv);
>  	struct yt921x_mib *mib = &pp->mib;
> +	u64 rx_frames;
> +	u64 tx_frames;
>  	int res = 0;
>  
> -	/* Reading of yt921x_port::mib is not protected by a lock and it's vain
> -	 * to keep its consistency, since we have to read registers one by one
> -	 * and there is no way to make a snapshot of MIB stats.
> -	 *
> -	 * Writing (by this function only) is and should be protected by
> -	 * reg_lock.
> +	/* u64_stats_read/set is redundant for mib_new, but I don't want to
> +	 * declare a plain u64 yt921x_mib variant.
>  	 */
>  
>  	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
>  		const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
>  		u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
> -		u64 *valp = &((u64 *)mib)[i];
>  		u32 val0;
>  		u64 val;
>  
> @@ -694,7 +693,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
>  			break;
>  
>  		if (desc->size <= 1) {
> -			u64 old_val = *valp;
> +			u64 old_val = u64_stats_read(&mib->stats[i]);
>  
>  			val = (old_val & ~(u64)U32_MAX) | val0;
>  			if (val < old_val)
> @@ -708,7 +707,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
>  			val = ((u64)val1 << 32) | val0;
>  		}
>  
> -		WRITE_ONCE(*valp, val);
> +		u64_stats_set(&mib_new->stats[i], val);
>  	}
>  
>  	if (res) {
> @@ -717,14 +716,29 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
>  		return res;
>  	}
>  
> -	pp->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
> -			mib->rx_128_255byte + mib->rx_256_511byte +
> -			mib->rx_512_1023byte + mib->rx_1024_1518byte +
> -			mib->rx_jumbo;
> -	pp->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
> -			mib->tx_128_255byte + mib->tx_256_511byte +
> -			mib->tx_512_1023byte + mib->tx_1024_1518byte +
> -			mib->tx_jumbo;
> +	rx_frames = u64_stats_read(&mib_new->rx_64byte) +
> +		    u64_stats_read(&mib_new->rx_65_127byte) +
> +		    u64_stats_read(&mib_new->rx_128_255byte) +
> +		    u64_stats_read(&mib_new->rx_256_511byte) +
> +		    u64_stats_read(&mib_new->rx_512_1023byte) +
> +		    u64_stats_read(&mib_new->rx_1024_1518byte) +
> +		    u64_stats_read(&mib_new->rx_jumbo);
> +	tx_frames = u64_stats_read(&mib_new->tx_64byte) +
> +		    u64_stats_read(&mib_new->tx_65_127byte) +
> +		    u64_stats_read(&mib_new->tx_128_255byte) +
> +		    u64_stats_read(&mib_new->tx_256_511byte) +
> +		    u64_stats_read(&mib_new->tx_512_1023byte) +
> +		    u64_stats_read(&mib_new->tx_1024_1518byte) +
> +		    u64_stats_read(&mib_new->tx_jumbo);
> +
> +	u64_stats_update_begin(&pp->syncp);
> +	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
> +		u64_stats_set(&mib->stats[i],
> +			      u64_stats_read(&mib_new->stats[i]));
> +	}
> +	u64_stats_set(&pp->rx_frames, rx_frames);
> +	u64_stats_set(&pp->tx_frames, tx_frames);
> +	u64_stats_update_end(&pp->syncp);
>  
>  	return 0;
>  }
> @@ -772,8 +786,8 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
>  	size_t j;
>  
>  	mutex_lock(&priv->reg_lock);
> +
>  	yt921x_read_mib(priv, port);
> -	mutex_unlock(&priv->reg_lock);
>  
>  	j = 0;
>  	for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
> @@ -782,9 +796,11 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
>  		if (!desc->name)
>  			continue;
>  
> -		data[j] = ((u64 *)mib)[i];
> +		data[j] = u64_stats_read(&((u64_stats_t *)mib)[i]);
>  		j++;
>  	}
> +
> +	mutex_unlock(&priv->reg_lock);
>  }
>  
>  static int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset)
> @@ -813,31 +829,33 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
>  	struct yt921x_mib *mib = &pp->mib;
>  
>  	mutex_lock(&priv->reg_lock);
> +
>  	yt921x_read_mib(priv, port);
> -	mutex_unlock(&priv->reg_lock);
>  
> -	mac_stats->FramesTransmittedOK = pp->tx_frames;
> -	mac_stats->SingleCollisionFrames = mib->tx_single_collisions;
> -	mac_stats->MultipleCollisionFrames = mib->tx_multiple_collisions;
> -	mac_stats->FramesReceivedOK = pp->rx_frames;
> -	mac_stats->FrameCheckSequenceErrors = mib->rx_crc_errors;
> -	mac_stats->AlignmentErrors = mib->rx_alignment_errors;
> -	mac_stats->OctetsTransmittedOK = mib->tx_good_bytes;
> -	mac_stats->FramesWithDeferredXmissions = mib->tx_deferred;
> -	mac_stats->LateCollisions = mib->tx_late_collisions;
> -	mac_stats->FramesAbortedDueToXSColls = mib->tx_aborted_errors;
> +	mac_stats->FramesTransmittedOK = u64_stats_read(&pp->tx_frames);
> +	mac_stats->SingleCollisionFrames = u64_stats_read(&mib->tx_single_collisions);
> +	mac_stats->MultipleCollisionFrames = u64_stats_read(&mib->tx_multiple_collisions);
> +	mac_stats->FramesReceivedOK = u64_stats_read(&pp->rx_frames);
> +	mac_stats->FrameCheckSequenceErrors = u64_stats_read(&mib->rx_crc_errors);
> +	mac_stats->AlignmentErrors = u64_stats_read(&mib->rx_alignment_errors);
> +	mac_stats->OctetsTransmittedOK = u64_stats_read(&mib->tx_good_bytes);
> +	mac_stats->FramesWithDeferredXmissions = u64_stats_read(&mib->tx_deferred);
> +	mac_stats->LateCollisions = u64_stats_read(&mib->tx_late_collisions);
> +	mac_stats->FramesAbortedDueToXSColls = u64_stats_read(&mib->tx_aborted_errors);
>  	/* mac_stats->FramesLostDueToIntMACXmitError */
>  	/* mac_stats->CarrierSenseErrors */
> -	mac_stats->OctetsReceivedOK = mib->rx_good_bytes;
> +	mac_stats->OctetsReceivedOK = u64_stats_read(&mib->rx_good_bytes);
>  	/* mac_stats->FramesLostDueToIntMACRcvError */
> -	mac_stats->MulticastFramesXmittedOK = mib->tx_multicast;
> -	mac_stats->BroadcastFramesXmittedOK = mib->tx_broadcast;
> +	mac_stats->MulticastFramesXmittedOK = u64_stats_read(&mib->tx_multicast);
> +	mac_stats->BroadcastFramesXmittedOK = u64_stats_read(&mib->tx_broadcast);
>  	/* mac_stats->FramesWithExcessiveDeferral */
> -	mac_stats->MulticastFramesReceivedOK = mib->rx_multicast;
> -	mac_stats->BroadcastFramesReceivedOK = mib->rx_broadcast;
> +	mac_stats->MulticastFramesReceivedOK = u64_stats_read(&mib->rx_multicast);
> +	mac_stats->BroadcastFramesReceivedOK = u64_stats_read(&mib->rx_broadcast);
>  	/* mac_stats->InRangeLengthErrors */
>  	/* mac_stats->OutOfRangeLengthField */
> -	mac_stats->FrameTooLongErrors = mib->rx_oversize_errors;
> +	mac_stats->FrameTooLongErrors = u64_stats_read(&mib->rx_oversize_errors);
> +
> +	mutex_unlock(&priv->reg_lock);
>  }
>  
>  static void
> @@ -849,12 +867,14 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
>  	struct yt921x_mib *mib = &pp->mib;
>  
>  	mutex_lock(&priv->reg_lock);
> +
>  	yt921x_read_mib(priv, port);
> -	mutex_unlock(&priv->reg_lock);
>  
> -	ctrl_stats->MACControlFramesTransmitted = mib->tx_pause;
> -	ctrl_stats->MACControlFramesReceived = mib->rx_pause;
> +	ctrl_stats->MACControlFramesTransmitted = u64_stats_read(&mib->tx_pause);
> +	ctrl_stats->MACControlFramesReceived = u64_stats_read(&mib->rx_pause);
>  	/* ctrl_stats->UnsupportedOpcodesReceived */
> +
> +	mutex_unlock(&priv->reg_lock);
>  }
>  
>  static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = {
> @@ -878,31 +898,33 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
>  	struct yt921x_mib *mib = &pp->mib;
>  
>  	mutex_lock(&priv->reg_lock);
> +
>  	yt921x_read_mib(priv, port);
> -	mutex_unlock(&priv->reg_lock);
>  
>  	*ranges = yt921x_rmon_ranges;
>  
> -	rmon_stats->undersize_pkts = mib->rx_undersize_errors;
> -	rmon_stats->oversize_pkts = mib->rx_oversize_errors;
> -	rmon_stats->fragments = mib->rx_alignment_errors;
> +	rmon_stats->undersize_pkts = u64_stats_read(&mib->rx_undersize_errors);
> +	rmon_stats->oversize_pkts = u64_stats_read(&mib->rx_oversize_errors);
> +	rmon_stats->fragments = u64_stats_read(&mib->rx_alignment_errors);
>  	/* rmon_stats->jabbers */
>  
> -	rmon_stats->hist[0] = mib->rx_64byte;
> -	rmon_stats->hist[1] = mib->rx_65_127byte;
> -	rmon_stats->hist[2] = mib->rx_128_255byte;
> -	rmon_stats->hist[3] = mib->rx_256_511byte;
> -	rmon_stats->hist[4] = mib->rx_512_1023byte;
> -	rmon_stats->hist[5] = mib->rx_1024_1518byte;
> -	rmon_stats->hist[6] = mib->rx_jumbo;
> +	rmon_stats->hist[0] = u64_stats_read(&mib->rx_64byte);
> +	rmon_stats->hist[1] = u64_stats_read(&mib->rx_65_127byte);
> +	rmon_stats->hist[2] = u64_stats_read(&mib->rx_128_255byte);
> +	rmon_stats->hist[3] = u64_stats_read(&mib->rx_256_511byte);
> +	rmon_stats->hist[4] = u64_stats_read(&mib->rx_512_1023byte);
> +	rmon_stats->hist[5] = u64_stats_read(&mib->rx_1024_1518byte);
> +	rmon_stats->hist[6] = u64_stats_read(&mib->rx_jumbo);
> +
> +	rmon_stats->hist_tx[0] = u64_stats_read(&mib->tx_64byte);
> +	rmon_stats->hist_tx[1] = u64_stats_read(&mib->tx_65_127byte);
> +	rmon_stats->hist_tx[2] = u64_stats_read(&mib->tx_128_255byte);
> +	rmon_stats->hist_tx[3] = u64_stats_read(&mib->tx_256_511byte);
> +	rmon_stats->hist_tx[4] = u64_stats_read(&mib->tx_512_1023byte);
> +	rmon_stats->hist_tx[5] = u64_stats_read(&mib->tx_1024_1518byte);
> +	rmon_stats->hist_tx[6] = u64_stats_read(&mib->tx_jumbo);
>  
> -	rmon_stats->hist_tx[0] = mib->tx_64byte;
> -	rmon_stats->hist_tx[1] = mib->tx_65_127byte;
> -	rmon_stats->hist_tx[2] = mib->tx_128_255byte;
> -	rmon_stats->hist_tx[3] = mib->tx_256_511byte;
> -	rmon_stats->hist_tx[4] = mib->tx_512_1023byte;
> -	rmon_stats->hist_tx[5] = mib->tx_1024_1518byte;
> -	rmon_stats->hist_tx[6] = mib->tx_jumbo;
> +	mutex_unlock(&priv->reg_lock);
>  }
>  
>  static void
> @@ -912,33 +934,41 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
>  	struct yt921x_priv *priv = to_yt921x_priv(ds);
>  	struct yt921x_port *pp = &priv->ports[port];
>  	struct yt921x_mib *mib = &pp->mib;
> +	unsigned int start;
> +
> +	do {
> +		start = u64_stats_fetch_begin(&pp->syncp);
> +
> +		stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) +
> +					  u64_stats_read(&mib->rx_fragment_errors);
> +		stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors);
> +		stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors);
> +		stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors);
> +		/* stats->rx_fifo_errors */
> +		/* stats->rx_missed_errors */
> +
> +		stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors);
> +		/* stats->tx_carrier_errors */
> +		stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors);
> +		/* stats->tx_heartbeat_errors */
> +		stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions);
> +
> +		stats->rx_packets = u64_stats_read(&pp->rx_frames);
> +		stats->tx_packets = u64_stats_read(&pp->tx_frames);
> +		stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) -
> +				  ETH_FCS_LEN * stats->rx_packets;
> +		stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) -
> +				  ETH_FCS_LEN * stats->tx_packets;
> +		stats->rx_dropped = u64_stats_read(&mib->rx_dropped);
> +		/* stats->tx_dropped */
> +		stats->multicast = u64_stats_read(&mib->rx_multicast);
> +		stats->collisions = u64_stats_read(&mib->tx_collisions);
> +	} while (u64_stats_fetch_retry(&pp->syncp, start));
>  
> -	stats->rx_length_errors = mib->rx_undersize_errors +
> -				  mib->rx_fragment_errors;
> -	stats->rx_over_errors = mib->rx_oversize_errors;
> -	stats->rx_crc_errors = mib->rx_crc_errors;
> -	stats->rx_frame_errors = mib->rx_alignment_errors;
> -	/* stats->rx_fifo_errors */
> -	/* stats->rx_missed_errors */
> -
> -	stats->tx_aborted_errors = mib->tx_aborted_errors;
> -	/* stats->tx_carrier_errors */
> -	stats->tx_fifo_errors = mib->tx_undersize_errors;
> -	/* stats->tx_heartbeat_errors */
> -	stats->tx_window_errors = mib->tx_late_collisions;
> -
> -	stats->rx_packets = pp->rx_frames;
> -	stats->tx_packets = pp->tx_frames;
> -	stats->rx_bytes = mib->rx_good_bytes - ETH_FCS_LEN * stats->rx_packets;
> -	stats->tx_bytes = mib->tx_good_bytes - ETH_FCS_LEN * stats->tx_packets;
>  	stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
>  			   stats->rx_crc_errors + stats->rx_frame_errors;
>  	stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
>  			   stats->tx_window_errors;
> -	stats->rx_dropped = mib->rx_dropped;
> -	/* stats->tx_dropped */
> -	stats->multicast = mib->rx_multicast;
> -	stats->collisions = mib->tx_collisions;
>  }
>  
>  static void
> @@ -950,11 +980,13 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
>  	struct yt921x_mib *mib = &pp->mib;
>  
>  	mutex_lock(&priv->reg_lock);
> +
>  	yt921x_read_mib(priv, port);
> -	mutex_unlock(&priv->reg_lock);
>  
> -	pause_stats->tx_pause_frames = mib->tx_pause;
> -	pause_stats->rx_pause_frames = mib->rx_pause;
> +	pause_stats->tx_pause_frames = u64_stats_read(&mib->tx_pause);
> +	pause_stats->rx_pause_frames = u64_stats_read(&mib->rx_pause);
> +
> +	mutex_unlock(&priv->reg_lock);
>  }
>  
>  static int
> @@ -3423,6 +3455,7 @@ static int yt921x_mdio_probe(struct mdio_device *mdiodev)
>  
>  		pp->index = i;
>  		INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib);
> +		u64_stats_init(&pp->syncp);
>  	}
>  
>  	ds = &priv->ds;
> diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
> index 3f129b8d403f..0f4231accf3e 100644
> --- a/drivers/net/dsa/yt921x.h
> +++ b/drivers/net/dsa/yt921x.h
> @@ -6,6 +6,8 @@
>  #ifndef __YT921X_H
>  #define __YT921X_H
>  
> +#include <linux/u64_stats_sync.h>
> +
>  #include <net/dsa.h>
>  
>  #define YT921X_SMI_SWITCHID_M		GENMASK(3, 2)
> @@ -530,55 +532,61 @@ enum yt921x_fdb_entry_status {
>  #define yt921x_port_is_external(port) (8 <= (port) && (port) < 9)
>  
>  struct yt921x_mib {
> -	u64 rx_broadcast;
> -	u64 rx_pause;
> -	u64 rx_multicast;
> -	u64 rx_crc_errors;
> -
> -	u64 rx_alignment_errors;
> -	u64 rx_undersize_errors;
> -	u64 rx_fragment_errors;
> -	u64 rx_64byte;
> -
> -	u64 rx_65_127byte;
> -	u64 rx_128_255byte;
> -	u64 rx_256_511byte;
> -	u64 rx_512_1023byte;
> -
> -	u64 rx_1024_1518byte;
> -	u64 rx_jumbo;
> -	u64 rx_good_bytes;
> -
> -	u64 rx_bad_bytes;
> -	u64 rx_oversize_errors;
> -
> -	u64 rx_dropped;
> -	u64 tx_broadcast;
> -	u64 tx_pause;
> -	u64 tx_multicast;
> -
> -	u64 tx_undersize_errors;
> -	u64 tx_64byte;
> -	u64 tx_65_127byte;
> -	u64 tx_128_255byte;
> -
> -	u64 tx_256_511byte;
> -	u64 tx_512_1023byte;
> -	u64 tx_1024_1518byte;
> -	u64 tx_jumbo;
> -
> -	u64 tx_good_bytes;
> -	u64 tx_collisions;
> -
> -	u64 tx_aborted_errors;
> -	u64 tx_multiple_collisions;
> -	u64 tx_single_collisions;
> -	u64 tx_good;
> -
> -	u64 tx_deferred;
> -	u64 tx_late_collisions;
> -	u64 rx_oam;
> -	u64 tx_oam;
> +	union {
> +		struct {
> +			u64_stats_t rx_broadcast;
> +			u64_stats_t rx_pause;
> +			u64_stats_t rx_multicast;
> +			u64_stats_t rx_crc_errors;
> +
> +			u64_stats_t rx_alignment_errors;
> +			u64_stats_t rx_undersize_errors;
> +			u64_stats_t rx_fragment_errors;
> +			u64_stats_t rx_64byte;
> +
> +			u64_stats_t rx_65_127byte;
> +			u64_stats_t rx_128_255byte;
> +			u64_stats_t rx_256_511byte;
> +			u64_stats_t rx_512_1023byte;
> +
> +			u64_stats_t rx_1024_1518byte;
> +			u64_stats_t rx_jumbo;
> +			u64_stats_t rx_good_bytes;
> +
> +			u64_stats_t rx_bad_bytes;
> +			u64_stats_t rx_oversize_errors;
> +
> +			u64_stats_t rx_dropped;
> +			u64_stats_t tx_broadcast;
> +			u64_stats_t tx_pause;
> +			u64_stats_t tx_multicast;
> +
> +			u64_stats_t tx_undersize_errors;
> +			u64_stats_t tx_64byte;
> +			u64_stats_t tx_65_127byte;
> +			u64_stats_t tx_128_255byte;
> +
> +			u64_stats_t tx_256_511byte;
> +			u64_stats_t tx_512_1023byte;
> +			u64_stats_t tx_1024_1518byte;
> +			u64_stats_t tx_jumbo;
> +
> +			u64_stats_t tx_good_bytes;
> +			u64_stats_t tx_collisions;
> +
> +			u64_stats_t tx_aborted_errors;
> +			u64_stats_t tx_multiple_collisions;
> +			u64_stats_t tx_single_collisions;
> +			u64_stats_t tx_good;
> +
> +			u64_stats_t tx_deferred;
> +			u64_stats_t tx_late_collisions;
> +			u64_stats_t rx_oam;
> +			u64_stats_t tx_oam;
> +		};
> +
> +		u64_stats_t stats[39];

The above looks bug prone if the future chip revisions will support more
stats.

/P


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

end of thread, other threads:[~2026-03-03 11:40 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-27 13:50 [PATCH net-next v3 0/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
2026-02-27 13:50 ` [PATCH net-next v3 1/2] net: dsa: yt921x: Return early for failed MIB read David Yang
2026-03-03 11:34   ` Simon Horman
2026-02-27 13:50 ` [PATCH net-next v3 2/2] net: dsa: yt921x: Use u64_stats_t for MIB stats David Yang
2026-03-03 11:31   ` Simon Horman
2026-03-03 11:40   ` Paolo Abeni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox