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. Update trans_start when stopping the queue to avoid spurious watchdog timeouts. The issue can be easily reproduced by: 1. Run iperf 2. Run application which opens an AF_XDP/ZC socket Fixes: 132c32ee5bc0 ("net: stmmac: Add TX via XDP zero-copy socket") Signed-off-by: Kurt Kanzenbach --- drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c index d7e4db7224b0..883bd3fe8089 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c @@ -6,6 +6,16 @@ #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); + txq_trans_cond_update(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 +46,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 +57,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 +85,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 +100,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