mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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.


  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®