]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
be2net: fix data race in be_get_new_eqd
authorDavid Yang <mmyangfl@gmail.com>
Mon, 19 Jan 2026 15:34:36 +0000 (23:34 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 30 Jan 2026 09:27:36 +0000 (10:27 +0100)
[ Upstream commit 302e5b481caa7b3d11ec0e058434c1fc95195e50 ]

In be_get_new_eqd(), statistics of pkts, protected by u64_stats_sync, are
read and accumulated in ignorance of possible u64_stats_fetch_retry()
events. Before the commit in question, these statistics were retrieved
one by one directly from queues. Fix this by reading them into temporary
variables first.

Fixes: 209477704187 ("be2net: set interrupt moderation for Skyhawk-R using EQ-DB")
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20260119153440.1440578-1-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/emulex/benet/be_main.c

index 011c8cc8429e3a4f4fac7ab93e3006f384b175f1..2ed1e290f9d78ec1a2b7cf80cdafee949d914183 100644 (file)
@@ -2141,7 +2141,7 @@ static int be_get_new_eqd(struct be_eq_obj *eqo)
        struct be_aic_obj *aic;
        struct be_rx_obj *rxo;
        struct be_tx_obj *txo;
-       u64 rx_pkts = 0, tx_pkts = 0;
+       u64 rx_pkts = 0, tx_pkts = 0, pkts;
        ulong now;
        u32 pps, delta;
        int i;
@@ -2157,15 +2157,17 @@ static int be_get_new_eqd(struct be_eq_obj *eqo)
        for_all_rx_queues_on_eq(adapter, eqo, rxo, i) {
                do {
                        start = u64_stats_fetch_begin(&rxo->stats.sync);
-                       rx_pkts += rxo->stats.rx_pkts;
+                       pkts = rxo->stats.rx_pkts;
                } while (u64_stats_fetch_retry(&rxo->stats.sync, start));
+               rx_pkts += pkts;
        }
 
        for_all_tx_queues_on_eq(adapter, eqo, txo, i) {
                do {
                        start = u64_stats_fetch_begin(&txo->stats.sync);
-                       tx_pkts += txo->stats.tx_reqs;
+                       pkts = txo->stats.tx_reqs;
                } while (u64_stats_fetch_retry(&txo->stats.sync, start));
+               tx_pkts += pkts;
        }
 
        /* Skip, if wrapped around or first calculation */