summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRosen Penev2026-10-12 18:17:57 +0000
committerJonas Jelonek2026-10-22 07:42:38 +0000
commit19a15f9c3929a5b9785009dfffb4dc418d637a49 (patch)
tree99355b752b32c910363e3cb1365c25d374552301
parenta31dd90f6974a935b16aea8c7c31eeec1aac18c1 (diff)
apm821xx: size EMAC RX buffers for the MTUHEADmastermain
A DSA conduit runs with an MTU slightly above 1500 for the switch tag, which made EMAC pick the largest 4080 byte MAL buffers and an 8K slab object per received frame. Size the RX buffers for the MTU instead, and resize the ring whenever a jumbo MTU is involved so the jumbo settings stay correct. Routing a single TCP stream through the qca8k switch of a Meraki MX60 (iperf3 median of 3, A/B in the same boot): LAN->WAN WAN->LAN (Mbit/s) before 538 476 after 564 498 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Rosen Penev <rosenp@gmail.com> Link: https://github.com/openwrt/openwrt/pull/26083 Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
-rw-r--r--target/linux/apm821xx/patches-6.18/711-v7.4-net-ibm-emac-size-RX-buffers-for-the-MTU.patch66
1 files changed, 66 insertions, 0 deletions
diff --git a/target/linux/apm821xx/patches-6.18/711-v7.4-net-ibm-emac-size-RX-buffers-for-the-MTU.patch b/target/linux/apm821xx/patches-6.18/711-v7.4-net-ibm-emac-size-RX-buffers-for-the-MTU.patch
new file mode 100644
index 0000000000..d65ebbc3be
--- /dev/null
+++ b/target/linux/apm821xx/patches-6.18/711-v7.4-net-ibm-emac-size-RX-buffers-for-the-MTU.patch
@@ -0,0 +1,66 @@
+From 73022f605c447f31610b94ed4a983d2b4bf2c721 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Wed, 7 Oct 2026 20:51:22 -0700
+Subject: [PATCH] net: ibm: emac: size RX buffers for the MTU
+
+Any MTU above ETH_DATA_LEN selects the largest MAL buffer size of 4080
+bytes. A DSA conduit always runs with a slightly larger MTU for the
+switch tag (1502 for qca8k), so every received frame then uses an 8K
+slab object and a 4K cache invalidate even though it is at most 1520
+bytes long. Size the buffers for the MTU instead, capped at the MAL
+maximum as before. Larger jumbo frames still span several descriptors.
+
+emac_change_mtu() only resized the ring, which is also where the jumbo
+mode and the APM821xx maximum jumbo size are programmed, when the RX skb
+size changed. 1500 and 1502 now share a skb size, so also resize the
+ring whenever the old or new MTU is a jumbo one. Otherwise jumbo mode
+stays off and 1502 byte frames are dropped when the MTU is raised while
+the interface is up.
+
+Routing a single TCP stream through the qca8k switch of a Meraki MX60
+(APM82181, iperf3 median of 3, A/B in the same boot):
+
+ LAN->WAN WAN->LAN (Mbit/s)
+ before 538 476
+ after 564 498
+
+Assisted-by: LLM
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
+Link: https://patch.msgid.link/20261008035122.3182851-1-rosenp@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/ibm/emac/core.c | 7 +++++--
+ drivers/net/ethernet/ibm/emac/core.h | 5 +----
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/ibm/emac/core.c
++++ b/drivers/net/ethernet/ibm/emac/core.c
+@@ -1114,8 +1114,11 @@ static int emac_change_mtu(struct net_de
+ DBG(dev, "change_mtu(%d)" NL, new_mtu);
+
+ if (netif_running(ndev)) {
+- /* Check if we really need to reinitialize RX ring */
+- if (emac_rx_skb_size(ndev->mtu) != emac_rx_skb_size(new_mtu))
++ /* Check if we really need to reinitialize RX ring. The
++ * jumbo frame settings are only updated by a resize.
++ */
++ if (emac_rx_skb_size(ndev->mtu) != emac_rx_skb_size(new_mtu) ||
++ ndev->mtu > ETH_DATA_LEN || new_mtu > ETH_DATA_LEN)
+ ret = emac_resize_rx_ring(dev, new_mtu);
+ }
+
+--- a/drivers/net/ethernet/ibm/emac/core.h
++++ b/drivers/net/ethernet/ibm/emac/core.h
+@@ -56,10 +56,7 @@
+ /* RX BD size for the given MTU */
+ static inline int emac_rx_size(int mtu)
+ {
+- if (mtu > ETH_DATA_LEN)
+- return MAL_MAX_RX_SIZE;
+- else
+- return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD);
++ return mal_rx_size(max(mtu, ETH_DATA_LEN) + EMAC_MTU_OVERHEAD);
+ }
+
+ /* Size of RX skb for the given MTU */