Collect received skbs on a local list during RX polling and pass the completed batch to netif_receive_skb_list(). This lets the networking stack process packets from a poll cycle in bulk instead of handing each skb up individually.
Speedup tested with bidirectional iperf3. Before: [ ID][Role] Interval Transfer Bitrate Retr [ 5][TX-C] 0.00-10.00 sec 490 MBytes 411 Mbits/sec sender [ 5][TX-C] 0.00-10.01 sec 488 MBytes 409 Mbits/sec receiver [ 7][RX-C] 0.00-10.00 sec 176 MBytes 147 Mbits/sec 167 sender [ 7][RX-C] 0.00-10.01 sec 175 MBytes 146 Mbits/sec receiver After: [ ID][Role] Interval Transfer Bitrate Retr [ 5][TX-C] 0.00-10.00 sec 502 MBytes 421 Mbits/sec sender [ 5][TX-C] 0.00-10.01 sec 501 MBytes 420 Mbits/sec receiver [ 7][RX-C] 0.00-10.00 sec 212 MBytes 178 Mbits/sec 148 sender [ 7][RX-C] 0.00-10.01 sec 211 MBytes 177 Mbits/sec receiver Assisted-by: Codex:GPT-5.5 Signed-off-by: Rosen Penev <[email protected]> --- drivers/net/ethernet/freescale/ucc_geth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 7af4b5e3f38e..bce1079fc06a 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -2894,6 +2894,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit u32 bd_status; u8 *bdBuffer; struct net_device *dev; + LIST_HEAD(rx_list); ugeth_vdbg("%s: IN", __func__); @@ -2934,7 +2935,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit dev->stats.rx_bytes += length; /* Send the packet up the stack */ - netif_receive_skb(skb); + list_add_tail(&skb->list, &rx_list); } skb = get_new_skb(ugeth, bd); @@ -2960,6 +2961,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit bd_status = in_be32((u32 __iomem *)bd); } + netif_receive_skb_list(&rx_list); + ugeth->rxBd[rxQ] = bd; return howmany; } -- 2.54.0
