From: Paolo Abeni <pabeni@redhat.com>
To: maxime.chevallier@bootlin.com
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, linux@armlinux.org.uk,
hkallweit1@gmail.com, alexis.lothore@bootlin.com,
mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com,
kernel@esmil.dk, minda.chen@starfivetech.com,
neil.armstrong@linaro.org, khilman@baylibre.com,
jbrunet@baylibre.com, martin.blumenstingl@googlemail.com,
jan.petrous@oss.nxp.com, ovidiu.panait.rb@renesas.com,
Jose.Abreu@synopsys.com, nb@tipi-net.de, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com,
linux-arm-kernel@lists.infradead.org,
linux-stm32@st-md-mailman.stormreply.com, PKneuper@dspace.de,
david.laight.linux@gmail.com
Subject: Re: [PATCH net v3 5/6] net: stmmac: size the RX buffers from the frame length, not the MTU
Date: Tue, 15 Sep 2026 10:45:58 +0200 [thread overview]
Message-ID: <20260915084558.75283-1-pabeni@redhat.com> (raw)
In-Reply-To: <20260911212028.1497613-6-maxime.chevallier@bootlin.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
net: stmmac: size the RX buffers from the frame length, not the MTU
The patch stops feeding the bare MTU into the RX buffer size selection and
instead computes a frame length that includes the L2 header, two VLAN tags,
the FCS and NET_IP_ALIGN. stmmac_set_bfsize() is renamed to take a length
and its boundary comparisons are switched from '>=' to '>'.
A few questions below.
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 62c3441911e71..29b970574a380 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1536,17 +1536,17 @@ static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)
> return NET_SKB_PAD + NET_IP_ALIGN;
> }
>
> -static int stmmac_set_bfsize(int mtu)
> +static int stmmac_set_bfsize(int len)
> {
> int ret;
>
> - if (mtu >= BUF_SIZE_8KiB)
> + if (len > BUF_SIZE_8KiB)
> ret = BUF_SIZE_16KiB;
[Severity: High]
This isn't a bug introduced by this patch, but the 16 KiB selection here is
reachable in configurations whose descriptors cannot express a buffer that
large, and this patch moves the threshold about 28 bytes of MTU lower.
In chain mode mac->mode points at chain_mode_ops, which does not implement
set_16kib_bfsize, so stmmac_do_callback() returns -EINVAL, bfsize is forced
to 0 and stmmac_set_bfsize(len) runs unconditionally. For enhanced
descriptors the programmed buffer 1 is clamped:
drivers/net/ethernet/stmicro/stmmac/enh_desc.c:enh_desc_init_rx_desc() {
bfsize1 = min(bfsize, BUF_SIZE_8KiB);
p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK);
}
and for normal descriptors:
drivers/net/ethernet/stmicro/stmmac/norm_desc.c:ndesc_init_rx_desc() {
bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1);
p->des1 |= cpu_to_le32(bfsize1 & RDES1_BUFFER1_SIZE_MASK);
}
while the RX path still reports the software value for every non-last
descriptor:
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c:stmmac_rx_buf1_len() {
/* First descriptor, not last descriptor and not split header */
if (status & rx_not_ls)
return priv->dma_conf.dma_buf_sz;
}
That value then drives dma_sync_single_range_for_cpu() and
skb_add_rx_frag(). Can this hand the stack more bytes than the engine
wrote, padding the frame with recycled page pool contents? Chain mode is
reachable through the chain_mode module parameter and is forced for
dwmac-sun8i, which uses normal descriptors.
> - else if (mtu >= BUF_SIZE_4KiB)
> + else if (len > BUF_SIZE_4KiB)
> ret = BUF_SIZE_8KiB;
> - else if (mtu >= BUF_SIZE_2KiB)
> + else if (len > BUF_SIZE_2KiB)
> ret = BUF_SIZE_4KiB;
> - else if (mtu > DEFAULT_BUFSIZE)
> + else if (len > DEFAULT_BUFSIZE)
> ret = BUF_SIZE_2KiB;
[Severity: High]
This is a pre-existing issue and not something this patch introduces, but
the new thresholds widen the MTU range in which it applies (the step up to
BUF_SIZE_2KiB/BUF_SIZE_4KiB now happens roughly 28 bytes of MTU earlier).
For normal descriptors in ring mode, a second data buffer is advertised
whose bus address is never programmed:
drivers/net/ethernet/stmicro/stmmac/descs_com.h:ndesc_rx_set_on_ring() {
if (bfsize >= BUF_SIZE_2KiB) {
int bfsize2;
bfsize2 = min(bfsize - BUF_SIZE_2KiB + 1, BUF_SIZE_2KiB - 1);
p->des1 |= cpu_to_le32(FIELD_PREP(RDES1_BUFFER2_SIZE_MASK,
bfsize2));
}
}
RDES3 is only ever written through ring_mode.c init_desc3()/refill_desc3(),
and the driver only calls those when dma_buf_sz equals BUF_SIZE_16KiB:
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c:stmmac_init_rx_buffers() {
if (dma_conf->dma_buf_sz == BUF_SIZE_16KiB)
stmmac_init_desc3(priv, p);
}
Devices on ndesc_ops are capped at max_mtu = SKB_MAX_HEAD(NET_SKB_PAD +
NET_IP_ALIGN), so they can only pick 2048 or 4096 and RDES3 stays 0 from
dma_alloc_coherent(). Since the second-address-chained bit is not set in
ring mode, does the RX DMA spill the part of the frame beyond the 2047-byte
buffer 1 to bus address 0? This is driven by an inbound frame on cores
using normal descriptors (MAC100, or GMAC with plat->enh_desc == 0) with an
MTU above ~2 KiB.
> else
> ret = DEFAULT_BUFSIZE;
>
> @@ -4063,7 +4063,7 @@ static struct stmmac_dma_conf *
> stmmac_setup_dma_desc(struct stmmac_priv *priv, unsigned int mtu)
> {
> struct stmmac_dma_conf *dma_conf;
> - int bfsize, ret;
> + int bfsize, len, ret;
> u8 chan;
>
> dma_conf = kzalloc_obj(*dma_conf);
> @@ -4073,13 +4073,15 @@ stmmac_setup_dma_desc(struct stmmac_priv *priv, unsigned int mtu)
> return ERR_PTR(-ENOMEM);
> }
>
> - /* Returns 0 or BUF_SIZE_16KiB if mtu > 8KiB and dwmac4 or ring mode */
> - bfsize = stmmac_set_16kib_bfsize(priv, mtu);
> + len = mtu + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
[Severity: Low]
Should NET_IP_ALIGN be part of this sum? It is head room that lives
outside the window described by dma_buf_sz, and it is already reserved
separately:
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c:__alloc_dma_rx_desc_resources() {
dma_buf_sz_pad = stmmac_rx_offset(priv) + dma_conf->dma_buf_sz +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
...
pp_params.offset = stmmac_rx_offset(priv);
pp_params.max_len = dma_conf->dma_buf_sz;
}
with stmmac_rx_offset() returning NET_SKB_PAD + NET_IP_ALIGN, and
stmmac_init_rx_buffers() programming the descriptor at page dma address
plus buf->page_offset == stmmac_rx_offset(priv).
Counting it again inside len makes the selected buffer class, and therefore
the page pool order, depend on the architecture for a 2-byte wide MTU
window at each boundary. For example MTU 4069/4070 with NET_IP_ALIGN == 2
gives len 4097/4098 and selects BUF_SIZE_8KiB, whereas the same MTU on
x86 (NET_IP_ALIGN == 0) selects BUF_SIZE_4KiB.
The commit message also lists "the NET_IP_ALIGN" alongside ETH_HLEN, the
VLAN tags and the FCS as if it were part of the frame. Would it be more
accurate to describe it as head room, or drop the term?
> +
> + /* Returns 0 or BUF_SIZE_16KiB if len > 8KiB and dwmac4 or ring mode */
> + bfsize = stmmac_set_16kib_bfsize(priv, len);
> if (bfsize < 0)
> bfsize = 0;
>
> if (bfsize < BUF_SIZE_16KiB)
> - bfsize = stmmac_set_bfsize(mtu);
> + bfsize = stmmac_set_bfsize(len);
[Severity: Medium]
The argument handed to the set_16kib_bfsize callback changes unit here from
MTU to frame length, but neither the ops prototype nor the two
implementations were updated.
hwif.h still declares:
int (*set_16kib_bfsize)(int mtu);
dwmac4_descs.c:set_16kib_bfsize() keeps the inclusive test:
if (unlikely(mtu >= BUF_SIZE_8KiB))
ret = BUF_SIZE_16KiB;
while ring_mode.c:set_16kib_bfsize() uses the other operator:
if (unlikely(mtu > BUF_SIZE_8KiB))
ret = BUF_SIZE_16KiB;
Since dwmac4/dwmac5 use dwmac4_ring_mode_ops, does the new comment "Returns
0 or BUF_SIZE_16KiB if len > 8KiB" match what actually happens on those
cores? A len of exactly BUF_SIZE_8KiB (MTU 8160 with NET_IP_ALIGN == 2)
fits an 8188-byte buffer and stmmac_set_bfsize() would return
BUF_SIZE_8KiB, but the unchanged '>=' returns BUF_SIZE_16KiB and the
'if (bfsize < BUF_SIZE_16KiB)' guard then skips the corrected helper, so
dma_buf_sz becomes 16368 instead of 8188. That roughly doubles the pages
backing each RX buffer (order 2 to order 3) across the default
dma_rx_size of 512.
The commit message says the change lets us "use more consistent comparison
operators in stmmac_set_bfsize" - should the two set_16kib_bfsize
implementations and the 'mtu' parameter name be converted at the same time?
--
This is an AI-generated review.
next prev parent reply other threads:[~2026-09-15 8:46 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 21:20 [PATCH net v3 0/6] net: stmmac: More selftest-related fixes Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 1/6] net: stmmac: selftests: Support running selftests on DSA conduits Maxime Chevallier
2026-09-15 8:45 ` Paolo Abeni
2026-09-15 9:22 ` Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 2/6] net: stmmac: selftests: Validate EEE based on the actual LPI timer value Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 3/6] net: stmmac: selftests: Check the dev->features for S-TAG offload testing Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 4/6] net: stmmac: selftests: Capture all packets for vlan checks Maxime Chevallier
2026-09-15 8:45 ` Paolo Abeni
2026-09-15 11:54 ` Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 5/6] net: stmmac: size the RX buffers from the frame length, not the MTU Maxime Chevallier
2026-09-15 8:45 ` Paolo Abeni [this message]
2026-09-11 21:20 ` [PATCH net v3 6/6] net: stmmac: selftests: Account for alignment shift on dwmac1000 for Jumbo test Maxime Chevallier
2026-09-15 8:50 ` [PATCH net v3 0/6] net: stmmac: More selftest-related fixes Paolo Abeni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915084558.75283-1-pabeni@redhat.com \
--to=pabeni@redhat.com \
--cc=Jose.Abreu@synopsys.com \
--cc=PKneuper@dspace.de \
--cc=alexandre.torgue@foss.st.com \
--cc=alexis.lothore@bootlin.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=david.laight.linux@gmail.com \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=jan.petrous@oss.nxp.com \
--cc=jbrunet@baylibre.com \
--cc=kernel@esmil.dk \
--cc=khilman@baylibre.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=linux@armlinux.org.uk \
--cc=martin.blumenstingl@googlemail.com \
--cc=maxime.chevallier@bootlin.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=minda.chen@starfivetech.com \
--cc=nb@tipi-net.de \
--cc=neil.armstrong@linaro.org \
--cc=netdev@vger.kernel.org \
--cc=ovidiu.panait.rb@renesas.com \
--cc=thomas.petazzoni@bootlin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.