]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: remove cpu stall in txq_trans_update()
authorEric Dumazet <edumazet@google.com>
Tue, 8 Apr 2025 20:27:42 +0000 (20:27 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 10 Apr 2025 01:03:31 +0000 (18:03 -0700)
txq_trans_update() currently uses txq->xmit_lock_owner
to conditionally update txq->trans_start.

For regular devices, txq->xmit_lock_owner is updated
from HARD_TX_LOCK() and HARD_TX_UNLOCK(), and this apparently
causes cpu stalls.

Using dev->lltx, which sits in a read-mostly cache-line,
and already used in HARD_TX_LOCK() and HARD_TX_UNLOCK()
helps cpu prediction.

On an AMD EPYC 7B12 dual socket server, tcp_rr with 128 threads
and 30,000 flows gets a 5 % increase in throughput.

As explained in commit 95ecba62e2fd ("net: fix races in
netdev_tx_sent_queue()/dev_watchdog()") I am planning
to no longer update txq->trans_start in the fast path
in a followup patch.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250408202742.2145516-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/ti/am65-cpsw-nuss.c
include/linux/netdevice.h

index c9fd34787c9986946c06e3d8d9de693c4438ab6a..e78de79a5d78c2e673809841e5c6d2dc35c754a1 100644 (file)
@@ -427,7 +427,7 @@ static void am65_cpsw_nuss_ndo_host_tx_timeout(struct net_device *ndev,
 
        if (netif_tx_queue_stopped(netif_txq)) {
                /* try recover if stopped by us */
-               txq_trans_update(netif_txq);
+               txq_trans_update(ndev, netif_txq);
                netif_tx_wake_queue(netif_txq);
        }
 }
index dece2ae396a1e2086840c0c4b7201f4b31e026f1..a28a08046615fa3643c19604ae50e7ef9a690f7d 100644 (file)
@@ -4693,9 +4693,10 @@ static inline void __netif_tx_unlock_bh(struct netdev_queue *txq)
 /*
  * txq->trans_start can be read locklessly from dev_watchdog()
  */
-static inline void txq_trans_update(struct netdev_queue *txq)
+static inline void txq_trans_update(const struct net_device *dev,
+                                   struct netdev_queue *txq)
 {
-       if (txq->xmit_lock_owner != -1)
+       if (!dev->lltx)
                WRITE_ONCE(txq->trans_start, jiffies);
 }
 
@@ -5214,7 +5215,7 @@ static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_devi
 
        rc = __netdev_start_xmit(ops, skb, dev, more);
        if (rc == NETDEV_TX_OK)
-               txq_trans_update(txq);
+               txq_trans_update(dev, txq);
 
        return rc;
 }