From 83c9a3b84b8f576e5890029029c60b993c0c9305 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Thu, 21 Aug 2025 22:30:52 +0300 Subject: net: stmmac: Fix XDP transmission paths inconsistency The stmmac_dma_ops::enable_dma_transmission() callback implements the Tx Poll Demand command implying to charge Tx DMA to be seeking for the next DMA-own descriptor and start transmitting the respective frames to the wire. The stmmac_dma_ops::set_tx_tail_ptr() implements the same logic except that it also updates the Tx tail pointer and if the former method is specific for the DW MAC100/GMAC IP-cores the later callback is available on the most modern IP-cores: DW QoS Ether, DW XGMAC, etc. Thus both callbacks must be called in sync otherwise the respective xmit procedures will work differently on different controllers. Currently it's correctly implemented for the simple net_device_ops::stmmac_xmit() method. But for some mysterious reason the XDP ZC (stmmac_xdp_xmit_zc()) and XDP Tx/Redirect (stmmac_xdp_xmit_xdpf()) features get to call the stmmac_enable_dma_transmission() method right after each Tx-frame submission to Tx DMA engine way before the stmmac_flush_tx_descriptors() invocation thus delivering poorer XDP-performance on DW MAC100/GMAC devices. Let's fix that by moving the stmmac_enable_dma_transmission() method call to stmmac_flush_tx_descriptors() where the stmmac_set_tx_tail_ptr() function invocation resides. Thus both Tx DMA charging methods will be called in sync delivering the same Tx procedure semantics on all the supported DW network controllers. Fixes: 132c32ee5bc0 ("net: stmmac: Add TX via XDP zero-copy socket") Fixes: be8b38a722e6 ("net: stmmac: Add support for XDP_TX action") Signed-off-by: Serge Semin --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4caa0b5210ce..b1c509035276 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3007,8 +3007,6 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) csum, priv->mode, true, true, xdp_desc.len); - stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); - xsk_tx_metadata_to_compl(meta, &tx_q->tx_skbuff_dma[entry].xsk_meta); @@ -4588,8 +4586,16 @@ static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue) */ wmb(); + /* Update Tx desc tail pointer and issue the Tx poll demand cmd + * (specific for the most modern IP-cores: DW QoS Ether, XGMAC, etc). + */ tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * desc_size); stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue); + + /* Just issue the Tx poll demand cmd (specific to the older DW + * MAC100/GMAC IP-cores). + */ + stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); } /** @@ -5150,7 +5156,6 @@ flush_ring: dev_kfree_skb(skb); priv->xstats.tx_dropped++; } - stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); stmmac_flush_tx_descriptors(priv, queue); stmmac_tx_timer_arm(priv, queue); } @@ -5517,8 +5522,6 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, u64_stats_update_end(&txq_stats->q_syncp); } - stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); - entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size); tx_q->cur_tx = entry; -- cgit v1.2.3