[PATCH net-next v03 2/4] hinic3: Avoid concurrent updates on 32-bit systems.

From: Fan Gong

Date: Thu Nov 12 2026 - 02:12:34 EST


Within the while loop of hinic3_get_stats64(), the counters between
u64_stats_fetch_retry and u64_stats_fetch_begin are incremented by +=.
This operation will cause repeated counting of the counters on a 32-bit
system. Therefore, change += to + and the counters are incremented
out side the wile loop.

csum_errors and other_errors are not the same things. csum_errors will
go to csum_bad in netdev netlink qstats.

Remove unnecessary checks for the nic_dev->txqs and nic_dev->rxqs.

Remove dead stores before the loop.

Fixes: f47872bed40f ("hinic3: Add .ndo_tx_timeout and .ndo_get_stats64")
Co-developed-by: Wu Di <wudi234@xxxxxxxxxx>
Signed-off-by: Wu Di <wudi234@xxxxxxxxxx>
Co-developed-by: Teng Peisen <tengpeisen@xxxxxxxxxx>
Signed-off-by: Teng Peisen <tengpeisen@xxxxxxxxxx>
Signed-off-by: Fan Gong <gongfan1@xxxxxxxxxx>
---
.../huawei/hinic3/hinic3_netdev_ops.c | 42 +++++++------------
1 file changed, 14 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
index da73811641a9..d1fd91d97ccf 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
@@ -791,49 +791,35 @@ static void hinic3_get_stats64(struct net_device *netdev,
unsigned int start;
int i;

- bytes = 0;
- packets = 0;
- dropped = 0;
for (i = 0; i < nic_dev->max_qps; i++) {
- if (!nic_dev->txqs)
- break;
-
txq = &nic_dev->txqs[i];
txq_stats = &txq->txq_stats;
do {
start = u64_stats_fetch_begin(&txq_stats->syncp);
- bytes += txq_stats->bytes;
- packets += txq_stats->packets;
- dropped += txq_stats->dropped;
+ bytes = txq_stats->bytes;
+ packets = txq_stats->packets;
+ dropped = txq_stats->dropped;
} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ stats->tx_dropped += dropped;
}
- stats->tx_packets = packets;
- stats->tx_bytes = bytes;
- stats->tx_dropped = dropped;

- bytes = 0;
- packets = 0;
- errors = 0;
- dropped = 0;
for (i = 0; i < nic_dev->max_qps; i++) {
- if (!nic_dev->rxqs)
- break;
-
rxq = &nic_dev->rxqs[i];
rxq_stats = &rxq->rxq_stats;
do {
start = u64_stats_fetch_begin(&rxq_stats->syncp);
- bytes += rxq_stats->bytes;
- packets += rxq_stats->packets;
- errors += rxq_stats->csum_errors +
- rxq_stats->other_errors;
- dropped += rxq_stats->dropped;
+ bytes = rxq_stats->bytes;
+ packets = rxq_stats->packets;
+ errors = rxq_stats->other_errors;
+ dropped = rxq_stats->dropped;
} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ stats->rx_errors += errors;
+ stats->rx_dropped += dropped;
}
- stats->rx_packets = packets;
- stats->rx_bytes = bytes;
- stats->rx_errors = errors;
- stats->rx_dropped = dropped;
}

static void hinic3_nic_set_rx_mode(struct net_device *netdev)
--
2.43.0