From 54a7e093299b212c5090886aa767ba72cefbd46c Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Thu, 16 Jul 2026 09:44:31 +0200 Subject: [PATCH] realtek: eth: Adapt SKB defines Testing shows that the existing performance boost by aligning the data to 2 bytes (NET_IP_ALIGN) breaks fragment handling on RTL838x devices. The SoC silently drops 2 bytes between each fragment. Use this tricky alignment only when it is supported. This will bring down performance on RTL838x SoCs by 30%. All other SoCs are unaffected. This is a legitimate tradeoff for allowing multiple fragments. While we are here make clearer what the definies are about and rename them to a SKB_ prefix. Link: https://github.com/openwrt/openwrt/pull/24245 Signed-off-by: Markus Stockhausen --- .../drivers/net/ethernet/rtl838x_eth.c | 27 ++++++++++++------- .../drivers/net/ethernet/rtl838x_eth.h | 1 + 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c index c8591541e3..b955219c92 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c @@ -30,7 +30,6 @@ #define RING_OWN_HW BIT(0) #define RING_WRAP BIT(1) -#define RTETH_SKB_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN) #define RTETH_RX_RING_SIZE 128 #define RTETH_RX_RINGS 2 #define RTETH_TX_RING_SIZE 16 @@ -42,7 +41,11 @@ #define RX_TRUNCATE_EN_93XX BIT(6) #define RX_TRUNCATE_EN_83XX BIT(4) #define TX_PAD_EN_838X BIT(5) -#define RING_BUFFER 1600 + +#define SKB_FRAG_SIZE 1600 +#define SKB_PAD MAX(32, L1_CACHE_BYTES) +#define SKB_HEADROOM_FAST (SKB_PAD + NET_IP_ALIGN) +#define SKB_HEADROOM_SLOW SKB_PAD /* Define page pool that holds 2KB fragments in 4KB pages and has 8 safety pages */ #define PPOOL_FRAG_SIZE 2048 @@ -668,7 +671,7 @@ static int rteth_setup_ring_buffer(struct rteth_ctrl *ctrl) * and the DMA capabilities of the network adapter. Be defensive and add some checks to * assist further error analysis. */ - BUILD_BUG_ON(RTETH_SKB_HEADROOM + RING_BUFFER + + BUILD_BUG_ON(SKB_HEADROOM_FAST + SKB_FRAG_SIZE + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PPOOL_FRAG_SIZE); for (int r = 0; r < RTETH_RX_RINGS; r++) { @@ -686,8 +689,9 @@ static int rteth_setup_ring_buffer(struct rteth_ctrl *ctrl) highmem |= PageHighMem(page); paddr = max(paddr, page_to_phys(page)); - packet->size = RING_BUFFER; - packet->dma = page_pool_get_dma_addr(page) + RTETH_SKB_HEADROOM + offset; + packet->size = SKB_FRAG_SIZE; + packet->dma = page_pool_get_dma_addr(page) + + ctrl->r->skb_headroom + offset; packet->page = page; packet->page_offset = offset; ctrl->rx_data[r].ring[i] = ctrl->rx_data_dma + @@ -1126,7 +1130,7 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) packet = &ctrl->rx_data[ring].packet[slot]; len = packet->len - ETH_FCS_LEN; - if (unlikely(len > RING_BUFFER)) { + if (unlikely(len > SKB_FRAG_SIZE)) { netdev_err(dev, "invalid packet with %d bytes received\n", len); dev->stats.rx_errors++; goto recycle; @@ -1144,10 +1148,11 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) packet->page = new_page; packet->page_offset = new_offset; - packet->dma = page_pool_get_dma_addr(new_page) + new_offset + RTETH_SKB_HEADROOM; + packet->dma = page_pool_get_dma_addr(new_page) + + new_offset + ctrl->r->skb_headroom; page_pool_dma_sync_for_cpu(ctrl->rx_qs[ring].page_pool, old_page, - old_offset + RTETH_SKB_HEADROOM, len); + old_offset + ctrl->r->skb_headroom, len); skb = napi_build_skb(page_address(old_page) + old_offset, PPOOL_FRAG_SIZE); if (unlikely(!skb)) { @@ -1156,7 +1161,7 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) goto recycle; } - skb_reserve(skb, RTETH_SKB_HEADROOM); + skb_reserve(skb, ctrl->r->skb_headroom); skb_mark_for_recycle(skb); skb_put(skb, len); @@ -1448,6 +1453,7 @@ static const struct rteth_config rteth_838x_cfg = { .dma_tx_base = RTETH_838X_DMA_TX_BASE, .mac_force_mode_ctrl = RTETH_838X_MAC_FORCE_MODE_CTRL, .rst_glb_ctrl = RTL838X_RST_GLB_CTRL_0, + .skb_headroom = SKB_HEADROOM_SLOW, .mac_reg = { RTETH_838X_MAC_ADDR_CTRL, RTETH_838X_MAC_ADDR_CTRL_ALE, RTETH_838X_MAC_ADDR_CTRL_MAC }, @@ -1494,6 +1500,7 @@ static const struct rteth_config rteth_839x_cfg = { .dma_tx_base = RTETH_839X_DMA_TX_BASE, .mac_force_mode_ctrl = RTETH_839X_MAC_FORCE_MODE_CTRL, .rst_glb_ctrl = RTL839X_RST_GLB_CTRL, + .skb_headroom = SKB_HEADROOM_FAST, .mac_reg = { RTETH_839X_MAC_ADDR_CTRL }, .l2_tbl_flush_ctrl = RTL839X_L2_TBL_FLUSH_CTRL, .update_counter = rteth_83xx_update_counter, @@ -1540,6 +1547,7 @@ static const struct rteth_config rteth_930x_cfg = { .l2_ntfy_if_intr_msk = RTL930X_L2_NTFY_IF_INTR_MSK, .mac_force_mode_ctrl = RTETH_930X_MAC_FORCE_MODE_CTRL, .rst_glb_ctrl = RTL930X_RST_GLB_CTRL_0, + .skb_headroom = SKB_HEADROOM_FAST, .mac_reg = { RTETH_930X_MAC_L2_ADDR_CTRL }, .l2_tbl_flush_ctrl = RTL930X_L2_TBL_FLUSH_CTRL, .update_counter = rteth_93xx_update_counter, @@ -1585,6 +1593,7 @@ static const struct rteth_config rteth_931x_cfg = { .l2_ntfy_if_intr_msk = RTL931X_L2_NTFY_IF_INTR_MSK, .mac_force_mode_ctrl = RTETH_931X_MAC_FORCE_MODE_CTRL, .rst_glb_ctrl = RTL931X_RST_GLB_CTRL, + .skb_headroom = SKB_HEADROOM_FAST, .mac_reg = { RTETH_930X_MAC_L2_ADDR_CTRL }, .l2_tbl_flush_ctrl = RTL931X_L2_TBL_FLUSH_CTRL, .update_counter = rteth_93xx_update_counter, diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.h index 36ba386dd3..9d6837e915 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.h @@ -209,6 +209,7 @@ struct rteth_config { int dma_rx_base; int dma_tx_base; int rst_glb_ctrl; + int skb_headroom; u32 mac_reg[RTETH_MAX_MAC_REGS]; int l2_tbl_flush_ctrl; void (*create_tx_header)(struct rteth_packet *h, unsigned int dest_port, int prio);