net/mana: fix RX mempool leak on port stop
PATCH 1/1 net/mana: fix RX mempool leak on port stop
The RX descriptor ring drain loop in mana_stop_rx_queues() uses 'while (tail != head)' to free posted mbufs. The RX ring is likely completely full because every consumed WQE is immediately replenished, so head == tail when the ring is full. The drain loop never executes, leaking all RX mbufs on every port stop.
Fix by adding a desc_ring_len counter to mana_rxq (matching mana_txq) and using 'while (desc_ring_len > 0)' as the drain condition. Apply the same change to the TX drain loop for consistency.
--- drivers/net/mana/mana.h | 2 +- drivers/net/mana/rx.c | 6 +++++- drivers/net/mana/tx.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-)
drivers/net/mana/mana.h +1 -1
@@ -443,7 +443,7 @@ struct mana_rxq {/* desc_ring_head is where we put pending requests to ring, * completion pull off desc_ring_tail */ -uint32_t desc_ring_head, desc_ring_tail; +uint32_t desc_ring_head, desc_ring_tail, desc_ring_len;#ifdef RTE_ARCH_32 /* For storing wqe increment count btw each short doorbell ring */
drivers/net/mana/rx.c +5 -1
@@ -102,6 +102,7 @@ mana_post_rx_wqe(struct mana_rxq *rxq, struct rte_mbuf *mbuf) rxq->wqe_cnt_to_short_db += wqe_size_in_bu;#endif rxq->desc_ring_head = (rxq->desc_ring_head +1 ) % rxq->num_desc; + rxq->desc_ring_len++; }else {DP_LOG (DEBUG ,"failed to post recv ret %d" , ret);return ret;
@@ -215,7 +216,7 @@ mana_stop_rx_queues(struct rte_eth_dev *dev) }/* Drain and free posted WQEs */ -while (rxq->desc_ring_tail != rxq->desc_ring_head) { +while (rxq->desc_ring_len >0 ) {struct mana_rxq_desc *desc = &rxq->desc_ring[rxq->desc_ring_tail];
@@ -223,9 +224,11 @@ mana_stop_rx_queues(struct rte_eth_dev *dev) rxq->desc_ring_tail = (rxq->desc_ring_tail +1 ) % rxq->num_desc; + rxq->desc_ring_len--; } rxq->desc_ring_head =0 ; rxq->desc_ring_tail =0 ; + rxq->desc_ring_len =0 ;memset (&rxq->gdma_rq,0 ,sizeof (rxq->gdma_rq));memset (&rxq->gdma_cq,0 ,sizeof (rxq->gdma_cq));
@@ -560,6 +563,7 @@ mana_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) rxq->desc_ring_tail =0 ; rxq->gdma_rq.tail += desc->wqe_size_in_bu; + rxq->desc_ring_len--;/* Record the number of the RX WQE we need to post to replenish * consumed RX requests
drivers/net/mana/tx.c +1 -1
@@ -39,7 +39,7 @@ mana_stop_tx_queues(struct rte_eth_dev *dev) }/* Drain and free posted WQEs */ -while (txq->desc_ring_tail != txq->desc_ring_head) { +while (txq->desc_ring_len >0 ) {struct mana_txq_desc *desc = &txq->desc_ring[txq->desc_ring_tail];
Signature · 1 line
2.43.0
Stephen Hemminger
AppliedQuoted 6 lines · On Wed, 8 Apr 2026 18:55:19 -0700 Long Li <[email protected]> wrote:
The RX descriptor ring drain loop in
mana_stop_rx_queues()uses 'while (tail != head)' to free posted mbufs. The RX ring is likely completely full because every consumed WQE is immediately replenished, so head == tail when the ring is full. The drain loop never executes, leaking all RX mbufs on every port stop.
Quoted 8 lines
Fix by adding a
desc_ring_lencounter tomana_rxq(matchingmana_txq) and using 'while (desc_ring_len> 0)' as the drain condition. Apply the same change to the TX drain loop for consistency.Fixes 5f705ac26259 ("net/mana: start/stop Rx queues")Signed-off-by Long Li <[email protected]>
Applied to next-net