From: Jijie Shao Date: Sat, 22 Nov 2025 03:46:56 +0000 (+0800) Subject: net: hibmcge: reduce packet drop under stress testing X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e68bb2e0f7712239711cabc22ceeb56c011c69d;p=thirdparty%2Fkernel%2Flinux.git net: hibmcge: reduce packet drop under stress testing Under stress test scenarios, hibmcge driver may not receive packets in a timely manner, which can lead to the buffer of the hardware queue being exhausted, resulting in packet drop. This patch doubles the software queue depth and uses half of the buffer to fill the hardware queue before receiving packets, thus preventing packet loss caused by the hardware queue buffer being exhausted. Signed-off-by: Jijie Shao Link: https://patch.msgid.link/20251122034657.3373143-3-shaojijie@huawei.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c index 5f2e48f1dd257..ea691d5641614 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c @@ -377,7 +377,8 @@ static int hbg_rx_fill_one_buffer(struct hbg_priv *priv) struct hbg_buffer *buffer; int ret; - if (hbg_queue_is_full(ring->ntc, ring->ntu, ring)) + if (hbg_queue_is_full(ring->ntc, ring->ntu, ring) || + hbg_fifo_is_full(priv, ring->dir)) return 0; buffer = &ring->queue[ring->ntu]; @@ -396,6 +397,26 @@ static int hbg_rx_fill_one_buffer(struct hbg_priv *priv) return 0; } +static int hbg_rx_fill_buffers(struct hbg_priv *priv) +{ + u32 remained = hbg_hw_get_fifo_used_num(priv, HBG_DIR_RX); + u32 max_count = priv->dev_specs.rx_fifo_num; + u32 refill_count; + int ret; + + if (unlikely(remained >= max_count)) + return 0; + + refill_count = max_count - remained; + while (refill_count--) { + ret = hbg_rx_fill_one_buffer(priv); + if (unlikely(ret)) + break; + } + + return ret; +} + static bool hbg_sync_data_from_hw(struct hbg_priv *priv, struct hbg_buffer *buffer) { @@ -420,6 +441,7 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget) u32 packet_done = 0; u32 pkt_len; + hbg_rx_fill_buffers(priv); while (packet_done < budget) { if (unlikely(hbg_queue_is_empty(ring->ntc, ring->ntu, ring))) break; @@ -497,6 +519,16 @@ static int hbg_ring_init(struct hbg_priv *priv, struct hbg_ring *ring, u32 i, len; len = hbg_get_spec_fifo_max_num(priv, dir) + 1; + /* To improve receiving performance under high-stress scenarios, + * in the `hbg_napi_rx_poll()`, we first use the other half of + * the buffer to receive packets from the hardware via the + * `hbg_rx_fill_buffers()`, and then process the packets in the + * original half of the buffer to avoid packet loss caused by + * hardware overflow as much as possible. + */ + if (dir == HBG_DIR_RX) + len += hbg_get_spec_fifo_max_num(priv, dir); + ring->queue = dma_alloc_coherent(&priv->pdev->dev, len * sizeof(*ring->queue), &ring->queue_dma, GFP_KERNEL); @@ -545,21 +577,16 @@ static int hbg_tx_ring_init(struct hbg_priv *priv) static int hbg_rx_ring_init(struct hbg_priv *priv) { int ret; - u32 i; ret = hbg_ring_init(priv, &priv->rx_ring, hbg_napi_rx_poll, HBG_DIR_RX); if (ret) return ret; - for (i = 0; i < priv->rx_ring.len - 1; i++) { - ret = hbg_rx_fill_one_buffer(priv); - if (ret) { - hbg_ring_uninit(&priv->rx_ring); - return ret; - } - } + ret = hbg_rx_fill_buffers(priv); + if (ret) + hbg_ring_uninit(&priv->rx_ring); - return 0; + return ret; } int hbg_txrx_init(struct hbg_priv *priv)