enetc_xdp_xmit() keeps track of 3 numbers: - num_frames: total length of passed struct xdp_frame **frames array - xdp_tx_frm_cnt: number of frames successfully sent - k: index of currently sent frame from array With "k != xdp_tx_frm_cnt", the intention was to detect an early break due to an inability to send a frame, and to trigger a TX doorbell anyway. However, that doesn't work because every time when the loop breaks, k and xdp_tx_frm_cnt are mathematically equal. The correct condition on which we should ring the doorbell is when at least one frame was sent, and either the caller required us to flush, or we couldn't enqueue the entire passed array. After updating the enetc_update_tx_ring_tail() calling condition, we can delete the 'xdp_tx_frm_cnt' variable, since it is equal to 'k' after the loop exits. Fixes: 9d2b68cc108d ("net: enetc: add support for XDP_REDIRECT") Signed-off-by: Vladimir Oltean Reviewed-by: Wei Fang --- v3->v4: - context change after introduction of &bdr->xdp_lock - make sure k is initialized with 0 for the ENETC_TX_DOWN || !netif_carrier_ok() early exit, like xdp_tx_frm_cnt was v2->v3: delete redundant xdp_tx_frm_cnt variable v1->v2: patch is new --- drivers/net/ethernet/freescale/enetc/enetc.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index fe5db840d2cc..9ae7fef377d1 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -1888,8 +1888,8 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames, struct enetc_ndev_priv *priv = netdev_priv(ndev); struct skb_shared_info *shinfo; struct enetc_bdr *tx_ring; - int xdp_tx_bd_cnt, i, k; - int xdp_tx_frm_cnt = 0; + int xdp_tx_bd_cnt; + int i, k = 0; int err = 0; tx_ring = priv->xdp_tx_ring[smp_processor_id()]; @@ -1925,22 +1925,20 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames, &xdp_redirect_arr[i]); break; } - - xdp_tx_frm_cnt++; } - if (unlikely((flags & XDP_XMIT_FLUSH) || k != xdp_tx_frm_cnt)) + if (unlikely(k && ((flags & XDP_XMIT_FLUSH) || k < num_frames))) enetc_update_tx_ring_tail(tx_ring); enetc_unlock_mdio(); out: - tx_ring->stats.xdp_tx += xdp_tx_frm_cnt; - tx_ring->stats.xdp_tx_drops += num_frames - xdp_tx_frm_cnt; + tx_ring->stats.xdp_tx += k; + tx_ring->stats.xdp_tx_drops += num_frames - k; spin_unlock(&tx_ring->xdp_lock); - return err ?: xdp_tx_frm_cnt; + return err ?: k; } EXPORT_SYMBOL_GPL(enetc_xdp_xmit); -- 2.43.0