[PATCH net v3 2/2] net: stmmac: Stop Tx queue when (en|dis)abling XSK pools
Kurt Kanzenbach
kurt at linutronix.de
Tue Oct 13 01:57:22 PDT 2026
When enabling or disabling XSK pools in parallel to Tx traffic, kernel
crashes occur. For VLAN tagged frames that happens in stmmac_xmit() ->
dwmac4_set_vlan_tag() and for normal frames in stmmac_xmit() ->
dwmac4_set_addr(). Both of these functions access the Tx DMA descriptors.
The XDP pool (en|dis)ablement frees and reallocates the Tx DMA resources:
stmmac_disable_tx_queue:
__free_dma_tx_desc_resources
stmmac_enable_tx_queue:
__alloc_dma_tx_desc_resources
__init_dma_tx_desc_rings
NAPI is disabled during that allocation window, but the Tx queue is not
stopped. Therefore, add the stopping of the Tx queue during the enabling
and disabling of XSK pools.
The issue can be easily reproduced by:
1. Run iperf
2. Run application which opens an AF_XDP/ZC socket
Also add a dedicated queue check for the XDP Tx paths.
Fixes: 132c32ee5bc0 ("net: stmmac: Add TX via XDP zero-copy socket")
Suggested-by: Nicolai Buchwitz <nb at tipi-net.de> # XDP Tx checks
Signed-off-by: Kurt Kanzenbach <kurt at linutronix.de>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++
drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 2aa5a2695473..0e8ab2bd8f3e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5216,6 +5216,10 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
dma_addr_t dma_addr;
bool set_ic;
+ /* Ring may be torn down for an XSK pool switch */
+ if (netif_tx_queue_stopped(netdev_get_tx_queue(priv->dev, queue)))
+ return STMMAC_XDP_CONSUMED;
+
if (stmmac_tx_avail(priv, queue) < STMMAC_TX_THRESH(priv))
return STMMAC_XDP_CONSUMED;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
index d7e4db7224b0..a75ab93aef53 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
@@ -6,6 +6,15 @@
#include "stmmac.h"
#include "stmmac_xdp.h"
+static void stmmac_xdp_stop_tx_queue(struct stmmac_priv *priv, u16 queue)
+{
+ struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue);
+
+ __netif_tx_lock_bh(nq);
+ netif_tx_stop_queue(nq);
+ __netif_tx_unlock_bh(nq);
+}
+
static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
struct xsk_buff_pool *pool, u16 queue)
{
@@ -36,6 +45,7 @@ static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
if (need_update) {
napi_disable(&ch->rx_napi);
napi_disable(&ch->tx_napi);
+ stmmac_xdp_stop_tx_queue(priv, queue);
stmmac_disable_rx_queue(priv, queue);
stmmac_disable_tx_queue(priv, queue);
}
@@ -46,6 +56,7 @@ static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
stmmac_enable_rx_queue(priv, queue);
stmmac_enable_tx_queue(priv, queue);
napi_enable(&ch->rxtx_napi);
+ netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, queue));
err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
if (err)
@@ -73,6 +84,7 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
if (need_update) {
napi_disable(&ch->rxtx_napi);
+ stmmac_xdp_stop_tx_queue(priv, queue);
stmmac_disable_rx_queue(priv, queue);
stmmac_disable_tx_queue(priv, queue);
synchronize_rcu();
@@ -87,6 +99,7 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
stmmac_enable_tx_queue(priv, queue);
napi_enable(&ch->rx_napi);
napi_enable(&ch->tx_napi);
+ netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, queue));
}
return 0;
--
2.47.3
More information about the linux-arm-kernel
mailing list