Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bnxt_en: Fix XDP_TX path

For XDP_TX action in bnxt_rx_xdp(), clearing of the event flags is not
correct. __bnxt_poll_work() -> bnxt_rx_pkt() -> bnxt_rx_xdp() may be
looping within NAPI and some event flags may be set in earlier
iterations. In particular, if BNXT_TX_EVENT is set earlier indicating
some XDP_TX packets are ready and pending, it will be cleared if it is
XDP_TX action again. Normally, we will set BNXT_TX_EVENT again when we
successfully call __bnxt_xmit_xdp(). But if the TX ring has no more
room, the flag will not be set. This will cause the TX producer to be
ahead but the driver will not hit the TX doorbell.

For multi-buf XDP_TX, there is no need to clear the event flags and set
BNXT_AGG_EVENT. The BNXT_AGG_EVENT flag should have been set earlier in
bnxt_rx_pkt().

The visible symptom of this is that the RX ring associated with the
TX XDP ring will eventually become empty and all packets will be dropped.
Because this condition will cause the driver to not refill the RX ring
seeing that the TX ring has forever pending XDP_TX packets.

The fix is to only clear BNXT_RX_EVENT when we have successfully
called __bnxt_xmit_xdp().

Fixes: 7f0a168b0441 ("bnxt_en: Add completion ring pointer in TX and RX ring structures")
Reported-by: Pavel Dubovitsky <pdubovitsky@meta.com>
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20251203003024.2246699-1-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Michael Chan and committed by
Jakub Kicinski
0373d5c3 a479a27f

+1 -2
+1 -2
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
··· 268 268 case XDP_TX: 269 269 rx_buf = &rxr->rx_buf_ring[cons]; 270 270 mapping = rx_buf->mapping - bp->rx_dma_offset; 271 - *event &= BNXT_TX_CMP_EVENT; 272 271 273 272 if (unlikely(xdp_buff_has_frags(xdp))) { 274 273 struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); 275 274 276 275 tx_needed += sinfo->nr_frags; 277 - *event = BNXT_AGG_EVENT; 278 276 } 279 277 280 278 if (tx_avail < tx_needed) { ··· 285 287 dma_sync_single_for_device(&pdev->dev, mapping + offset, *len, 286 288 bp->rx_dir); 287 289 290 + *event &= ~BNXT_RX_EVENT; 288 291 *event |= BNXT_TX_EVENT; 289 292 __bnxt_xmit_xdp(bp, txr, mapping + offset, *len, 290 293 NEXT_RX(rxr->rx_prod), xdp);