diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-08-21 22:30:52 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:36:23 +0300 |
| commit | 83c9a3b84b8f576e5890029029c60b993c0c9305 (patch) | |
| tree | d777a1c3d8926455063b806bf3f7d29429e430d3 | |
| parent | a84655e43fb891b723ee9c8beacbc9af4dd3eed1 (diff) | |
| download | linux-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.c | 13 |
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; |
