* [PATCH net-next 1/3] net: hibmcge: Add tracepoint function to print some fields of rx_desc
2025-11-14 9:22 [PATCH net-next 0/3] net: hibmcge: Add tracepoint and pagepool for hibmcge driver Jijie Shao
@ 2025-11-14 9:22 ` Jijie Shao
2025-11-14 9:22 ` [PATCH net-next 2/3] net: hibmcge: reduce packet drop under stress testing Jijie Shao
2025-11-14 9:22 ` [PATCH net-next 3/3] net: hibmcge: support pagepool for rx Jijie Shao
2 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2025-11-14 9:22 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, lantao5, huangdonghua3,
yangshuaisong, jonathan.cameron, salil.mehta, netdev,
linux-kernel, shaojijie
From: Tao Lan <lantao5@huawei.com>
Add tracepoint function to print some fields of rx_desc
Signed-off-by: Tao Lan <lantao5@huawei.com>
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
.../net/ethernet/hisilicon/hibmcge/Makefile | 1 +
.../net/ethernet/hisilicon/hibmcge/hbg_reg.h | 4 +
.../ethernet/hisilicon/hibmcge/hbg_trace.h | 84 +++++++++++++++++++
.../net/ethernet/hisilicon/hibmcge/hbg_txrx.c | 4 +
4 files changed, 93 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/Makefile b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
index 1a9da564b306..d6610ba16855 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/Makefile
+++ b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
@@ -3,6 +3,7 @@
# Makefile for the HISILICON BMC GE network device drivers.
#
+ccflags-y += -I$(src)
obj-$(CONFIG_HIBMCGE) += hibmcge.o
hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o \
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
index a39d1e796e4a..30b3903c8f2d 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
@@ -252,6 +252,8 @@ struct hbg_rx_desc {
#define HBG_RX_DESC_W2_PKT_LEN_M GENMASK(31, 16)
#define HBG_RX_DESC_W2_PORT_NUM_M GENMASK(15, 12)
+#define HBG_RX_DESC_W3_IP_OFFSET_M GENMASK(23, 16)
+#define HBG_RX_DESC_W3_VLAN_M GENMASK(15, 0)
#define HBG_RX_DESC_W4_IP_TCP_UDP_M GENMASK(31, 30)
#define HBG_RX_DESC_W4_IPSEC_B BIT(29)
#define HBG_RX_DESC_W4_IP_VERSION_B BIT(28)
@@ -269,6 +271,8 @@ struct hbg_rx_desc {
#define HBG_RX_DESC_W4_L3_ERR_CODE_M GENMASK(12, 9)
#define HBG_RX_DESC_W4_L2_ERR_B BIT(8)
#define HBG_RX_DESC_W4_IDX_MATCH_B BIT(7)
+#define HBG_RX_DESC_W4_PARSE_MODE_M GENMASK(6, 5)
+#define HBG_RX_DESC_W5_VALID_SIZE_M GENMASK(15, 0)
enum hbg_l3_err_code {
HBG_L3_OK = 0,
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h
new file mode 100644
index 000000000000..b70fd960da8d
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2025 Hisilicon Limited. */
+
+/* This must be outside ifdef _HBG_TRACE_H */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hibmcge
+
+#if !defined(_HBG_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _HBG_TRACE_H_
+
+#include <linux/bitfield.h>
+#include <linux/pci.h>
+#include <linux/tracepoint.h>
+#include <linux/types.h>
+#include "hbg_reg.h"
+
+TRACE_EVENT(hbg_rx_desc,
+ TP_PROTO(struct hbg_priv *priv, u32 index,
+ struct hbg_rx_desc *rx_desc),
+ TP_ARGS(priv, index, rx_desc),
+
+ TP_STRUCT__entry(__field(u32, index)
+ __field(u8, port_num)
+ __field(u8, ip_offset)
+ __field(u8, parse_mode)
+ __field(u8, l4_error_code)
+ __field(u8, l3_error_code)
+ __field(u8, l2_error_code)
+ __field(u16, packet_len)
+ __field(u16, valid_size)
+ __field(u16, vlan)
+ __string(pciname, pci_name(priv->pdev))
+ __string(devname, priv->netdev->name)
+ ),
+
+ TP_fast_assign(__entry->index = index,
+ __entry->packet_len =
+ FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M,
+ rx_desc->word2);
+ __entry->port_num =
+ FIELD_GET(HBG_RX_DESC_W2_PORT_NUM_M,
+ rx_desc->word2);
+ __entry->ip_offset =
+ FIELD_GET(HBG_RX_DESC_W3_IP_OFFSET_M,
+ rx_desc->word3);
+ __entry->vlan =
+ FIELD_GET(HBG_RX_DESC_W3_VLAN_M,
+ rx_desc->word3);
+ __entry->parse_mode =
+ FIELD_GET(HBG_RX_DESC_W4_PARSE_MODE_M,
+ rx_desc->word4);
+ __entry->l4_error_code =
+ FIELD_GET(HBG_RX_DESC_W4_L4_ERR_CODE_M,
+ rx_desc->word4);
+ __entry->l3_error_code =
+ FIELD_GET(HBG_RX_DESC_W4_L3_ERR_CODE_M,
+ rx_desc->word4);
+ __entry->l2_error_code =
+ FIELD_GET(HBG_RX_DESC_W4_L2_ERR_B,
+ rx_desc->word4);
+ __entry->valid_size =
+ FIELD_GET(HBG_RX_DESC_W5_VALID_SIZE_M,
+ rx_desc->word5);
+ __assign_str(pciname);
+ __assign_str(devname);
+ ),
+
+ TP_printk("%s %s index:%u, port num:%u, len:%u, valid size:%u, ip_offset:%u, vlan:0x%04x, parse mode:%u, l4_err:0x%x, l3_err:0x%x, l2_err:0x%x",
+ __get_str(pciname), __get_str(devname), __entry->index,
+ __entry->port_num, __entry->packet_len,
+ __entry->valid_size, __entry->ip_offset, __entry->vlan,
+ __entry->parse_mode, __entry->l4_error_code,
+ __entry->l3_error_code, __entry->l2_error_code
+ )
+);
+
+#endif /* _HBG_TRACE_H_ */
+
+/* This must be outside ifdef _HBG_TRACE_H */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE hbg_trace
+#include <trace/define_trace.h>
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
index 8d814c8f19ea..5f2e48f1dd25 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
@@ -7,6 +7,9 @@
#include "hbg_reg.h"
#include "hbg_txrx.h"
+#define CREATE_TRACE_POINTS
+#include "hbg_trace.h"
+
#define netdev_get_tx_ring(netdev) \
(&(((struct hbg_priv *)netdev_priv(netdev))->tx_ring))
@@ -429,6 +432,7 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget)
break;
rx_desc = (struct hbg_rx_desc *)buffer->skb->data;
pkt_len = FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2);
+ trace_hbg_rx_desc(priv, ring->ntc, rx_desc);
if (unlikely(!hbg_rx_pkt_check(priv, rx_desc, buffer->skb))) {
hbg_buffer_free(buffer);
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH net-next 2/3] net: hibmcge: reduce packet drop under stress testing
2025-11-14 9:22 [PATCH net-next 0/3] net: hibmcge: Add tracepoint and pagepool for hibmcge driver Jijie Shao
2025-11-14 9:22 ` [PATCH net-next 1/3] net: hibmcge: Add tracepoint function to print some fields of rx_desc Jijie Shao
@ 2025-11-14 9:22 ` Jijie Shao
2025-11-14 9:22 ` [PATCH net-next 3/3] net: hibmcge: support pagepool for rx Jijie Shao
2 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2025-11-14 9:22 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, lantao5, huangdonghua3,
yangshuaisong, jonathan.cameron, salil.mehta, netdev,
linux-kernel, shaojijie
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 <shaojijie@huawei.com>
---
.../net/ethernet/hisilicon/hibmcge/hbg_txrx.c | 47 +++++++++++++++----
1 file changed, 37 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
index 5f2e48f1dd25..ea691d564161 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)
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH net-next 3/3] net: hibmcge: support pagepool for rx
2025-11-14 9:22 [PATCH net-next 0/3] net: hibmcge: Add tracepoint and pagepool for hibmcge driver Jijie Shao
2025-11-14 9:22 ` [PATCH net-next 1/3] net: hibmcge: Add tracepoint function to print some fields of rx_desc Jijie Shao
2025-11-14 9:22 ` [PATCH net-next 2/3] net: hibmcge: reduce packet drop under stress testing Jijie Shao
@ 2025-11-14 9:22 ` Jijie Shao
2025-11-18 1:49 ` Jakub Kicinski
2 siblings, 1 reply; 6+ messages in thread
From: Jijie Shao @ 2025-11-14 9:22 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, lantao5, huangdonghua3,
yangshuaisong, jonathan.cameron, salil.mehta, netdev,
linux-kernel, shaojijie
Support pagepool for rx, retaining the original
packet receiving process.
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
drivers/net/ethernet/hisilicon/Kconfig | 1 +
.../ethernet/hisilicon/hibmcge/hbg_common.h | 23 ++-
.../ethernet/hisilicon/hibmcge/hbg_debugfs.c | 2 +
.../net/ethernet/hisilicon/hibmcge/hbg_main.c | 7 +
.../net/ethernet/hisilicon/hibmcge/hbg_txrx.c | 170 ++++++++++++++++--
5 files changed, 185 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index 38875c196cb6..18eca7d12c20 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -151,6 +151,7 @@ config HIBMCGE
select FIXED_PHY
select MOTORCOMM_PHY
select REALTEK_PHY
+ select PAGE_POOL
help
If you wish to compile a kernel for a BMC with HIBMC-xx_gmac
then you should answer Y to this. This makes this driver suitable for use
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
index 2097e4c2b3d7..39cc18686f7e 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
@@ -7,6 +7,7 @@
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
+#include <net/page_pool/helpers.h>
#include "hbg_reg.h"
#define HBG_STATUS_DISABLE 0x0
@@ -52,8 +53,24 @@ struct hbg_buffer {
dma_addr_t state_dma;
struct sk_buff *skb;
- dma_addr_t skb_dma;
- u32 skb_len;
+ struct page *page;
+ u32 page_offset;
+
+ union {
+ void *skb_data_addr;
+ void *page_addr;
+ void *pkt_addr;
+ };
+ union {
+ dma_addr_t skb_dma;
+ dma_addr_t page_dma;
+ dma_addr_t pkt_dma;
+ };
+ union {
+ u32 skb_len;
+ u32 page_size;
+ u32 pkt_len;
+ };
enum hbg_dir dir;
struct hbg_ring *ring;
@@ -78,6 +95,7 @@ struct hbg_ring {
struct hbg_priv *priv;
struct napi_struct napi;
char *tout_log_buf; /* tx timeout log buffer */
+ struct page_pool *page_pool;
};
enum hbg_hw_event_type {
@@ -101,6 +119,7 @@ struct hbg_dev_specs {
u32 max_frame_len;
u32 rx_buf_size;
+ bool page_pool_enabled;
};
struct hbg_irq_info {
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c
index 01ad82d2f5cc..d963913def81 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c
@@ -122,6 +122,8 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
np_link_fail = !hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR,
HBG_REG_AN_NEG_STATE_NP_LINK_OK_B);
seq_printf(s, "np_link fail state: %s\n", str_true_false(np_link_fail));
+ seq_printf(s, "page_pool enabled: %s\n",
+ str_true_false(priv->dev_specs.page_pool_enabled));
return 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
index 068da2fd1fea..9d8b80db9f8b 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -19,6 +19,10 @@
#define HBG_SUPPORT_FEATURES (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
NETIF_F_RXCSUM)
+static bool page_pool_enabled = true;
+module_param(page_pool_enabled, bool, 0400);
+MODULE_PARM_DESC(page_pool_enabled, "set page_pool enabled, default is true");
+
static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
{
const struct hbg_irq_info *info;
@@ -367,6 +371,9 @@ static int hbg_init(struct hbg_priv *priv)
{
int ret;
+ if (IS_ENABLED(CONFIG_PAGE_POOL))
+ priv->dev_specs.page_pool_enabled = page_pool_enabled;
+
ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_INIT);
if (ret)
return ret;
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
index ea691d564161..b71f277419fa 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
@@ -31,6 +31,11 @@
typeof(ring) _ring = (ring); \
_ring->p = hbg_queue_next_prt(_ring->p, _ring); })
+#define hbg_get_page_order(ring) ({ \
+ typeof(ring) _ring = (ring); \
+ get_order(hbg_spec_max_frame_len(_ring->priv, _ring->dir)); })
+#define hbg_get_page_size(ring) (PAGE_SIZE << hbg_get_page_order((ring)))
+
#define HBG_TX_STOP_THRS 2
#define HBG_TX_START_THRS (2 * HBG_TX_STOP_THRS)
@@ -136,6 +141,7 @@ static void hbg_buffer_free_skb(struct hbg_buffer *buffer)
dev_kfree_skb_any(buffer->skb);
buffer->skb = NULL;
+ buffer->skb_data_addr = NULL;
}
static int hbg_buffer_alloc_skb(struct hbg_buffer *buffer)
@@ -148,7 +154,44 @@ static int hbg_buffer_alloc_skb(struct hbg_buffer *buffer)
return -ENOMEM;
buffer->skb_len = len;
- memset(buffer->skb->data, 0, HBG_PACKET_HEAD_SIZE);
+ buffer->skb_data_addr = buffer->skb->data;
+ return 0;
+}
+
+static void hbg_buffer_free_page(struct hbg_buffer *buffer)
+{
+ struct hbg_ring *ring = buffer->ring;
+
+ if (unlikely(!ring->page_pool || !buffer->page))
+ return;
+
+ page_pool_put_full_page(ring->page_pool, buffer->page, false);
+
+ buffer->page = NULL;
+ buffer->page_dma = 0;
+ buffer->page_addr = NULL;
+ buffer->page_size = 0;
+ buffer->page_offset = 0;
+}
+
+static int hbg_buffer_alloc_page(struct hbg_buffer *buffer)
+{
+ struct hbg_ring *ring = buffer->ring;
+ u32 len = hbg_get_page_size(ring);
+ u32 offset;
+
+ if (unlikely(!ring->page_pool))
+ return 0;
+
+ buffer->page = page_pool_dev_alloc_frag(ring->page_pool, &offset, len);
+ if (unlikely(!buffer->page))
+ return -ENOMEM;
+
+ buffer->page_dma = page_pool_get_dma_addr(buffer->page) + offset;
+ buffer->page_addr = page_address(buffer->page) + offset;
+ buffer->page_size = len;
+ buffer->page_offset = offset;
+
return 0;
}
@@ -371,6 +414,36 @@ static bool hbg_rx_pkt_check(struct hbg_priv *priv, struct hbg_rx_desc *desc,
return true;
}
+static int hbg_alloc_mapping_buffer(struct hbg_buffer *buffer)
+{
+ struct hbg_ring *ring = buffer->ring;
+ int ret;
+
+ if (ring->page_pool)
+ return hbg_buffer_alloc_page(buffer);
+
+ ret = hbg_buffer_alloc_skb(buffer);
+ if (unlikely(ret))
+ return ret;
+
+ ret = hbg_dma_map(buffer);
+ if (unlikely(ret))
+ hbg_buffer_free_skb(buffer);
+
+ return ret;
+}
+
+static void hbg_free_mapping_buffer(struct hbg_buffer *buffer)
+{
+ struct hbg_ring *ring = buffer->ring;
+
+ if (ring->page_pool)
+ return hbg_buffer_free_page(buffer);
+
+ hbg_dma_unmap(buffer);
+ hbg_buffer_free_skb(buffer);
+}
+
static int hbg_rx_fill_one_buffer(struct hbg_priv *priv)
{
struct hbg_ring *ring = &priv->rx_ring;
@@ -382,17 +455,15 @@ static int hbg_rx_fill_one_buffer(struct hbg_priv *priv)
return 0;
buffer = &ring->queue[ring->ntu];
- ret = hbg_buffer_alloc_skb(buffer);
+ ret = hbg_alloc_mapping_buffer(buffer);
if (unlikely(ret))
return ret;
- ret = hbg_dma_map(buffer);
- if (unlikely(ret)) {
- hbg_buffer_free_skb(buffer);
- return ret;
- }
+ memset(buffer->pkt_addr, 0, HBG_PACKET_HEAD_SIZE);
+ dma_sync_single_for_device(&priv->pdev->dev, buffer->pkt_dma,
+ HBG_PACKET_HEAD_SIZE, DMA_TO_DEVICE);
- hbg_hw_fill_buffer(priv, buffer->skb_dma);
+ hbg_hw_fill_buffer(priv, buffer->pkt_dma);
hbg_queue_move_next(ntu, ring);
return 0;
}
@@ -425,13 +496,29 @@ static bool hbg_sync_data_from_hw(struct hbg_priv *priv,
/* make sure HW write desc complete */
dma_rmb();
- dma_sync_single_for_cpu(&priv->pdev->dev, buffer->skb_dma,
- buffer->skb_len, DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(&priv->pdev->dev, buffer->pkt_dma,
+ buffer->pkt_len, DMA_FROM_DEVICE);
- rx_desc = (struct hbg_rx_desc *)buffer->skb->data;
+ rx_desc = (struct hbg_rx_desc *)buffer->pkt_addr;
return FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2) != 0;
}
+static int hbg_build_skb(struct hbg_buffer *buffer)
+{
+ if (!buffer->ring->page_pool) {
+ hbg_dma_unmap(buffer);
+ return 0;
+ }
+
+ net_prefetch(buffer->page_addr);
+ buffer->skb = napi_build_skb(buffer->page_addr, buffer->page_size);
+ if (unlikely(!buffer->skb))
+ return -ENOMEM;
+
+ skb_mark_for_recycle(buffer->skb);
+ return 0;
+}
+
static int hbg_napi_rx_poll(struct napi_struct *napi, int budget)
{
struct hbg_ring *ring = container_of(napi, struct hbg_ring, napi);
@@ -447,21 +534,25 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget)
break;
buffer = &ring->queue[ring->ntc];
- if (unlikely(!buffer->skb))
+ if (unlikely(!buffer->pkt_addr))
goto next_buffer;
if (unlikely(!hbg_sync_data_from_hw(priv, buffer)))
break;
- rx_desc = (struct hbg_rx_desc *)buffer->skb->data;
+ rx_desc = (struct hbg_rx_desc *)buffer->pkt_addr;
pkt_len = FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2);
trace_hbg_rx_desc(priv, ring->ntc, rx_desc);
+ if (unlikely(hbg_build_skb(buffer))) {
+ hbg_free_mapping_buffer(buffer);
+ goto next_buffer;
+ }
+
if (unlikely(!hbg_rx_pkt_check(priv, rx_desc, buffer->skb))) {
- hbg_buffer_free(buffer);
+ hbg_free_mapping_buffer(buffer);
goto next_buffer;
}
- hbg_dma_unmap(buffer);
skb_reserve(buffer->skb, HBG_PACKET_HEAD_SIZE + NET_IP_ALIGN);
skb_put(buffer->skb, pkt_len);
buffer->skb->protocol = eth_type_trans(buffer->skb,
@@ -470,6 +561,8 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget)
dev_sw_netstats_rx_add(priv->netdev, pkt_len);
napi_gro_receive(napi, buffer->skb);
buffer->skb = NULL;
+ buffer->page = NULL;
+ buffer->pkt_addr = NULL;
next_buffer:
hbg_rx_fill_one_buffer(priv);
@@ -484,6 +577,15 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget)
return packet_done;
}
+static void hbg_ring_page_pool_destory(struct hbg_ring *ring)
+{
+ if (!ring->page_pool)
+ return;
+
+ page_pool_destroy(ring->page_pool);
+ ring->page_pool = NULL;
+}
+
static void hbg_ring_uninit(struct hbg_ring *ring)
{
struct hbg_buffer *buffer;
@@ -497,11 +599,12 @@ static void hbg_ring_uninit(struct hbg_ring *ring)
for (i = 0; i < ring->len; i++) {
buffer = &ring->queue[i];
- hbg_buffer_free(buffer);
+ hbg_free_mapping_buffer(buffer);
buffer->ring = NULL;
buffer->priv = NULL;
}
+ hbg_ring_page_pool_destory(ring);
dma_free_coherent(&ring->priv->pdev->dev,
ring->len * sizeof(*ring->queue),
ring->queue, ring->queue_dma);
@@ -511,6 +614,33 @@ static void hbg_ring_uninit(struct hbg_ring *ring)
ring->priv = NULL;
}
+static int hbg_ring_page_pool_init(struct hbg_priv *priv, struct hbg_ring *ring)
+{
+ u32 buf_size = hbg_spec_max_frame_len(priv, ring->dir);
+ struct page_pool_params pp_params = {
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
+ .order = hbg_get_page_order(ring),
+ .pool_size = ring->len * buf_size / hbg_get_page_size(ring),
+ .nid = dev_to_node(&priv->pdev->dev),
+ .dev = &priv->pdev->dev,
+ .napi = &ring->napi,
+ .dma_dir = DMA_FROM_DEVICE,
+ .offset = 0,
+ .max_len = hbg_get_page_size(ring),
+ };
+ int ret = 0;
+
+ ring->page_pool = page_pool_create(&pp_params);
+ if (IS_ERR(ring->page_pool)) {
+ ret = PTR_ERR(ring->page_pool);
+ dev_err(&priv->pdev->dev,
+ "failed to create page pool, ret = %d\n", ret);
+ ring->page_pool = NULL;
+ }
+
+ return ret;
+}
+
static int hbg_ring_init(struct hbg_priv *priv, struct hbg_ring *ring,
int (*napi_poll)(struct napi_struct *, int),
enum hbg_dir dir)
@@ -582,6 +712,14 @@ static int hbg_rx_ring_init(struct hbg_priv *priv)
if (ret)
return ret;
+ if (priv->dev_specs.page_pool_enabled) {
+ ret = hbg_ring_page_pool_init(priv, &priv->rx_ring);
+ if (ret) {
+ hbg_ring_uninit(&priv->rx_ring);
+ return ret;
+ }
+ }
+
ret = hbg_rx_fill_buffers(priv);
if (ret)
hbg_ring_uninit(&priv->rx_ring);
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH net-next 3/3] net: hibmcge: support pagepool for rx
2025-11-14 9:22 ` [PATCH net-next 3/3] net: hibmcge: support pagepool for rx Jijie Shao
@ 2025-11-18 1:49 ` Jakub Kicinski
2025-11-18 2:34 ` Jijie Shao
0 siblings, 1 reply; 6+ messages in thread
From: Jakub Kicinski @ 2025-11-18 1:49 UTC (permalink / raw)
To: Jijie Shao
Cc: davem, edumazet, pabeni, andrew+netdev, horms, shenjian15,
liuyonglong, chenhao418, lantao5, huangdonghua3, yangshuaisong,
jonathan.cameron, salil.mehta, netdev, linux-kernel
On Fri, 14 Nov 2025 17:22:22 +0800 Jijie Shao wrote:
> Support pagepool for rx, retaining the original
> packet receiving process.
Why retain the legacy path? Page pool is 7 years old, all major NIC
vendors had dropped the support for non-page pool Rx path at this point.
If there are bugs or performance regressions we will fix them and send
the fixes to stable.
--
pw-bot: cr
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next 3/3] net: hibmcge: support pagepool for rx
2025-11-18 1:49 ` Jakub Kicinski
@ 2025-11-18 2:34 ` Jijie Shao
0 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2025-11-18 2:34 UTC (permalink / raw)
To: Jakub Kicinski
Cc: shaojijie, davem, edumazet, pabeni, andrew+netdev, horms,
shenjian15, liuyonglong, chenhao418, lantao5, huangdonghua3,
yangshuaisong, jonathan.cameron, salil.mehta, netdev,
linux-kernel
on 2025/11/18 9:49, Jakub Kicinski wrote:
> On Fri, 14 Nov 2025 17:22:22 +0800 Jijie Shao wrote:
>> Support pagepool for rx, retaining the original
>> packet receiving process.
> Why retain the legacy path? Page pool is 7 years old, all major NIC
> vendors had dropped the support for non-page pool Rx path at this point.
> If there are bugs or performance regressions we will fix them and send
> the fixes to stable.
I have seen some drivers that retain the legacy packet receiving path.
The community does not recommend this practice now, and I will remove the legacy path in v2.
Thanks,
Jijie Shao
^ permalink raw reply [flat|nested] 6+ messages in thread