summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-08-21 22:30:52 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:36:23 +0300
commit83c9a3b84b8f576e5890029029c60b993c0c9305 (patch)
treed777a1c3d8926455063b806bf3f7d29429e430d3
parenta84655e43fb891b723ee9c8beacbc9af4dd3eed1 (diff)
downloadlinux-gmac/ext3/xdp.tar.gz
linux-gmac/ext3/xdp.zip
net: stmmac: Fix XDP transmission paths inconsistencygmac/ext3/xdp
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 <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c13
1 files 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;