From: Lorenzo Bianconi <lorenzo@kernel.org>
To: David Yang <mmyangfl@gmail.com>
Cc: netdev@vger.kernel.org, Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next] net: airoha: Use u64_stats_t with u64_stats_sync properly
Date: Thu, 22 Jan 2026 22:58:47 +0100 [thread overview]
Message-ID: <aXKdl8N7YPTbEtFZ@lore-desk> (raw)
In-Reply-To: <20260122185255.2761568-1-mmyangfl@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 13610 bytes --]
> On 64bit arches, struct u64_stats_sync is empty and provides no help
> against load/store tearing. Convert to u64_stats_t to ensure atomic
> operations.
I guess we need a Fixes tag here.
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
>
> Signed-off-by: David Yang <mmyangfl@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 136 +++++++++++------------
> drivers/net/ethernet/airoha/airoha_eth.h | 34 +++---
> 2 files changed, 85 insertions(+), 85 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 62bcbbbe2a95..6ed220e5a094 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1472,131 +1472,131 @@ static void airoha_update_hw_stats(struct airoha_gdm_port *port)
>
> /* TX */
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id));
> - port->stats.tx_ok_pkts += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_ok_pkts, (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id));
> - port->stats.tx_ok_pkts += val;
> + u64_stats_add(&port->stats.tx_ok_pkts, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id));
> - port->stats.tx_ok_bytes += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_ok_bytes, (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id));
> - port->stats.tx_ok_bytes += val;
> + u64_stats_add(&port->stats.tx_ok_bytes, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id));
> - port->stats.tx_drops += val;
> + u64_stats_add(&port->stats.tx_drops, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id));
> - port->stats.tx_broadcast += val;
> + u64_stats_add(&port->stats.tx_broadcast, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id));
> - port->stats.tx_multicast += val;
> + u64_stats_add(&port->stats.tx_multicast, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id));
> - port->stats.tx_len[i] += val;
> + u64_stats_add(&port->stats.tx_len[i], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id));
> - port->stats.tx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id));
> - port->stats.tx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id));
> - port->stats.tx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id));
> - port->stats.tx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id));
> - port->stats.tx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id));
> - port->stats.tx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.tx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id));
> - port->stats.tx_len[i++] += val;
> + u64_stats_add(&port->stats.tx_len[i++], val);
>
> /* RX */
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id));
> - port->stats.rx_ok_pkts += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_ok_pkts, (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id));
> - port->stats.rx_ok_pkts += val;
> + u64_stats_add(&port->stats.rx_ok_pkts, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id));
> - port->stats.rx_ok_bytes += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_ok_bytes, (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id));
> - port->stats.rx_ok_bytes += val;
> + u64_stats_add(&port->stats.rx_ok_bytes, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id));
> - port->stats.rx_drops += val;
> + u64_stats_add(&port->stats.rx_drops, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id));
> - port->stats.rx_broadcast += val;
> + u64_stats_add(&port->stats.rx_broadcast, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id));
> - port->stats.rx_multicast += val;
> + u64_stats_add(&port->stats.rx_multicast, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id));
> - port->stats.rx_errors += val;
> + u64_stats_add(&port->stats.rx_errors, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id));
> - port->stats.rx_crc_error += val;
> + u64_stats_add(&port->stats.rx_crc_error, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id));
> - port->stats.rx_over_errors += val;
> + u64_stats_add(&port->stats.rx_over_errors, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id));
> - port->stats.rx_fragment += val;
> + u64_stats_add(&port->stats.rx_fragment, val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id));
> - port->stats.rx_jabber += val;
> + u64_stats_add(&port->stats.rx_jabber, val);
>
> i = 0;
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id));
> - port->stats.rx_len[i] += val;
> + u64_stats_add(&port->stats.rx_len[i], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id));
> - port->stats.rx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id));
> - port->stats.rx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id));
> - port->stats.rx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id));
> - port->stats.rx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id));
> - port->stats.rx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id));
> - port->stats.rx_len[i] += ((u64)val << 32);
> + u64_stats_add(&port->stats.rx_len[i], (u64)val << 32);
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id));
> - port->stats.rx_len[i++] += val;
> + u64_stats_add(&port->stats.rx_len[i++], val);
>
> /* reset mib counters */
> airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id),
> @@ -1795,16 +1795,16 @@ static void airoha_dev_get_stats64(struct net_device *dev,
> airoha_update_hw_stats(port);
> do {
> start = u64_stats_fetch_begin(&port->stats.syncp);
> - storage->rx_packets = port->stats.rx_ok_pkts;
> - storage->tx_packets = port->stats.tx_ok_pkts;
> - storage->rx_bytes = port->stats.rx_ok_bytes;
> - storage->tx_bytes = port->stats.tx_ok_bytes;
> - storage->multicast = port->stats.rx_multicast;
> - storage->rx_errors = port->stats.rx_errors;
> - storage->rx_dropped = port->stats.rx_drops;
> - storage->tx_dropped = port->stats.tx_drops;
> - storage->rx_crc_errors = port->stats.rx_crc_error;
> - storage->rx_over_errors = port->stats.rx_over_errors;
> + storage->rx_packets = u64_stats_read(&port->stats.rx_ok_pkts);
> + storage->tx_packets = u64_stats_read(&port->stats.tx_ok_pkts);
> + storage->rx_bytes = u64_stats_read(&port->stats.rx_ok_bytes);
> + storage->tx_bytes = u64_stats_read(&port->stats.tx_ok_bytes);
> + storage->multicast = u64_stats_read(&port->stats.rx_multicast);
> + storage->rx_errors = u64_stats_read(&port->stats.rx_errors);
> + storage->rx_dropped = u64_stats_read(&port->stats.rx_drops);
> + storage->tx_dropped = u64_stats_read(&port->stats.tx_drops);
> + storage->rx_crc_errors = u64_stats_read(&port->stats.rx_crc_error);
> + storage->rx_over_errors = u64_stats_read(&port->stats.rx_over_errors);
> } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> }
>
> @@ -2057,13 +2057,13 @@ static void airoha_ethtool_get_mac_stats(struct net_device *dev,
> airoha_update_hw_stats(port);
> do {
> start = u64_stats_fetch_begin(&port->stats.syncp);
> - stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
> - stats->OctetsTransmittedOK = port->stats.tx_ok_bytes;
> - stats->MulticastFramesXmittedOK = port->stats.tx_multicast;
> - stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast;
> - stats->FramesReceivedOK = port->stats.rx_ok_pkts;
> - stats->OctetsReceivedOK = port->stats.rx_ok_bytes;
> - stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast;
> + stats->FramesTransmittedOK = u64_stats_read(&port->stats.tx_ok_pkts);
> + stats->OctetsTransmittedOK = u64_stats_read(&port->stats.tx_ok_bytes);
> + stats->MulticastFramesXmittedOK = u64_stats_read(&port->stats.tx_multicast);
> + stats->BroadcastFramesXmittedOK = u64_stats_read(&port->stats.tx_broadcast);
> + stats->FramesReceivedOK = u64_stats_read(&port->stats.rx_ok_pkts);
> + stats->OctetsReceivedOK = u64_stats_read(&port->stats.rx_ok_bytes);
> + stats->BroadcastFramesReceivedOK = u64_stats_read(&port->stats.rx_broadcast);
> } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> }
>
> @@ -2098,12 +2098,12 @@ airoha_ethtool_get_rmon_stats(struct net_device *dev,
> int i;
>
> start = u64_stats_fetch_begin(&port->stats.syncp);
> - stats->fragments = hw_stats->rx_fragment;
> - stats->jabbers = hw_stats->rx_jabber;
> + stats->fragments = u64_stats_read(&hw_stats->rx_fragment);
> + stats->jabbers = u64_stats_read(&hw_stats->rx_jabber);
> for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1;
> i++) {
> - stats->hist[i] = hw_stats->rx_len[i];
> - stats->hist_tx[i] = hw_stats->tx_len[i];
> + stats->hist[i] = u64_stats_read(&hw_stats->rx_len[i]);
> + stats->hist_tx[i] = u64_stats_read(&hw_stats->tx_len[i]);
> }
> } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> }
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 20e602d61e61..b2e9bd849f8b 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -215,24 +215,24 @@ struct airoha_hw_stats {
> struct u64_stats_sync syncp;
>
> /* get_stats64 */
> - u64 rx_ok_pkts;
> - u64 tx_ok_pkts;
> - u64 rx_ok_bytes;
> - u64 tx_ok_bytes;
> - u64 rx_multicast;
> - u64 rx_errors;
> - u64 rx_drops;
> - u64 tx_drops;
> - u64 rx_crc_error;
> - u64 rx_over_errors;
> + u64_stats_t rx_ok_pkts;
> + u64_stats_t tx_ok_pkts;
> + u64_stats_t rx_ok_bytes;
> + u64_stats_t tx_ok_bytes;
> + u64_stats_t rx_multicast;
> + u64_stats_t rx_errors;
> + u64_stats_t rx_drops;
> + u64_stats_t tx_drops;
> + u64_stats_t rx_crc_error;
> + u64_stats_t rx_over_errors;
> /* ethtool stats */
> - u64 tx_broadcast;
> - u64 tx_multicast;
> - u64 tx_len[7];
> - u64 rx_broadcast;
> - u64 rx_fragment;
> - u64 rx_jabber;
> - u64 rx_len[7];
> + u64_stats_t tx_broadcast;
> + u64_stats_t tx_multicast;
> + u64_stats_t tx_len[7];
> + u64_stats_t rx_broadcast;
> + u64_stats_t rx_fragment;
> + u64_stats_t rx_jabber;
> + u64_stats_t rx_len[7];
> };
>
> enum {
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
next prev parent reply other threads:[~2026-01-22 21:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-22 18:52 [PATCH net-next] net: airoha: Use u64_stats_t with u64_stats_sync properly David Yang
2026-01-22 21:58 ` Lorenzo Bianconi [this message]
2026-01-25 21:28 ` [net-next] " Jakub Kicinski
2026-01-25 22:34 ` [PATCH net-next] " David Laight
2026-01-25 22:56 ` Yangfl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aXKdl8N7YPTbEtFZ@lore-desk \
--to=lorenzo@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=mmyangfl@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.