With header split, idpf_rx_update_bufq_desc() allocates the payload
buffer for a buffer ID first and its header buffer second. If the header
buffer allocation fails, it returns -ENOMEM and leaves the new payload
buffer in bufq->buf[buf_id]. idpf_rx_clean_refillq() then stops without
consuming the refill queue entry, and the next NAPI poll retries the
same buffer ID, again starting with the payload buffer.
libeth_rx_alloc() overwrites bufq->buf[buf_id], and the earlier payload
buffer is never returned to its page_pool.
Each such failure leaks one payload buffer. The pool's inflight count
never drops to zero, so when the queues are re-created or the device
goes away, the pool never finishes shutting down and
page_pool_release_retry() keeps warning about a stalled pool shutdown.
This happens when the header buffer pool runs dry while the payload pool
still has pages, for example under memory pressure: a header page holds
several header buffers and only goes back to its pool once the skbs
using all of them have been freed.
Release the payload buffer when the header buffer cannot be allocated,
as ice_alloc_rx_bufs() already does, so that the retry starts from an
empty slot. idpf_rx_page_rel() also clears the slot, so the buffer queue
teardown cannot release the buffer a second time.
Fixes: 90912f9f4f2d ("idpf: convert header split mode to libeth +
napi_build_skb()")
Signed-off-by: Naman Gulati <[email protected]>
---
drivers/net/ethernet/intel/idpf/idpf_txrx.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index 885df6294ad94..7383d8241ead5 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -3745,8 +3745,10 @@ static int idpf_rx_update_bufq_desc(struct
idpf_buf_queue *bufq, u32 buf_id,
fq.truesize = bufq->hdr_truesize;
addr = libeth_rx_alloc(&fq, buf_id);
- if (addr == DMA_MAPPING_ERROR)
+ if (addr == DMA_MAPPING_ERROR) {
+ idpf_rx_page_rel(&bufq->buf[buf_id]);
return -ENOMEM;
+ }
buf_desc->hdr_addr = cpu_to_le64(addr);
--
2.56.0.398.g882cbad275-goog