[Intel-wired-lan] [PATCH iwl-next v2 2/2] igc: enable build_skb on the non-XDP small-frame RX path

Kohei Enju
2026-03-17T06:22:46Z

igc implements igc_build_skb(), but it is currently unused because the
IGC_RING_FLAG_RX_BUILD_SKB_ENABLED bit is never set. Enable the
build_skb path when XDP is not active and the configured maximum frame
size fits within IGC_MAX_FRAME_BUILD_SKB.

In a single-queue small-packet (64-byte) RX microbenchmark on my setup,
enabling build_skb improved the receive rate from about 3.11 Mpps to
about 3.30 Mpps, while reducing missed packets from about 484 kpps to
about 300 kpps.

Keep the XDP path unchanged for now, since it uses a different RX buffer
layout based on XDP_PACKET_HEADROOM, and enabling it there would need
separate validation and buffer layout adjustments.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Kohei Enju <kohei@enjuk.jp>
---
drivers/net/ethernet/intel/igc/igc.h | 4 ++++
drivers/net/ethernet/intel/igc/igc_main.c | 4 ++++
2 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index e66799507f81..acbd2c237667 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -734,6 +734,10 @@ enum igc_ring_flags_t {

#define ring_uses_build_skb(ring) \
test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+#define set_ring_uses_build_skb(ring) \
+ set_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+#define clear_ring_uses_build_skb(ring) \
+ clear_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)

static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
{
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 79192b02e6be..b44f89311a4e 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -474,6 +474,7 @@ static void igc_clean_rx_ring(struct igc_ring *ring)
igc_clean_rx_ring_page_shared(ring);

clear_ring_uses_large_buffer(ring);
+ clear_ring_uses_build_skb(ring);

ring->next_to_alloc = 0;
ring->next_to_clean = 0;
@@ -654,6 +655,9 @@ static void igc_configure_rx_ring(struct igc_adapter *adapter,

if (igc_xdp_is_enabled(adapter))
set_ring_uses_large_buffer(ring);
+ else if (!(adapter->flags & IGC_FLAG_RX_LEGACY) &&
+ adapter->max_frame_size <= IGC_MAX_FRAME_BUILD_SKB)
+ set_ring_uses_build_skb(ring);

/* disable the queue */
wr32(IGC_RXDCTL(reg_idx), 0);
--
2.51.0