[PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames

Tomas Hlavacek posted 1 patch 1 week, 4 days ago
drivers/net/ethernet/spacemit/k1_emac.c | 6 ++++++
1 file changed, 6 insertions(+)
[PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames
Posted by Tomas Hlavacek 1 week, 4 days ago
The driver allows changing MTU up to 4K via emac_change_mtu() and
allocates appropriately sized DMA buffers, but it never programs the
MAC_MAXIMUM_FRAME_SIZE and MAC_RECEIVE_JABBER_SIZE registers.

This causes the MAC hardware to reject frames larger than the default
1518 bytes, even when larger buffers are allocated. Frames exceeding
the default size trigger jabber errors and are discarded.

Fixes: bfec6d7f2001 ("net: spacemit: Add K1 Ethernet MAC")
Cc: stable@vger.kernel.org
Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
v2: Added Fixes tag and Cc stable.

 drivers/net/ethernet/spacemit/k1_emac.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
index 220eb5ce7583..31b1bdb2827e 100644
--- a/drivers/net/ethernet/spacemit/k1_emac.c
+++ b/drivers/net/ethernet/spacemit/k1_emac.c
@@ -228,6 +228,12 @@ static void emac_init_hw(struct emac_priv *priv)
 		DEFAULT_TX_THRESHOLD);
 	emac_wr(priv, MAC_RECEIVE_PACKET_START_THRESHOLD, DEFAULT_RX_THRESHOLD);
 
+	/* Set maximum frame size and jabber size based on configured buffer
+	 * size.
+	 */
+	emac_wr(priv, MAC_MAXIMUM_FRAME_SIZE, priv->dma_buf_sz);
+	emac_wr(priv, MAC_RECEIVE_JABBER_SIZE, priv->dma_buf_sz);
+
 	/* Configure flow control (enabled in emac_adjust_link() later) */
 	emac_set_mac_addr_reg(priv, fc_dest_addr, MAC_FC_SOURCE_ADDRESS_HIGH);
 	emac_wr(priv, MAC_FC_PAUSE_HIGH_THRESHOLD, DEFAULT_FC_FIFO_HIGH);
-- 
2.52.0
Re: [PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames
Posted by Vivian Wang 1 week, 4 days ago
On 1/27/26 01:14, Tomas Hlavacek wrote:
> The driver allows changing MTU up to 4K via emac_change_mtu() and
> allocates appropriately sized DMA buffers, but it never programs the
> MAC_MAXIMUM_FRAME_SIZE and MAC_RECEIVE_JABBER_SIZE registers.
>
> This causes the MAC hardware to reject frames larger than the default
> 1518 bytes, even when larger buffers are allocated. Frames exceeding
> the default size trigger jabber errors and are discarded.
>
> Fixes: bfec6d7f2001 ("net: spacemit: Add K1 Ethernet MAC")
> Cc: stable@vger.kernel.org
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
> v2: Added Fixes tag and Cc stable.
>
>  drivers/net/ethernet/spacemit/k1_emac.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
> index 220eb5ce7583..31b1bdb2827e 100644
> --- a/drivers/net/ethernet/spacemit/k1_emac.c
> +++ b/drivers/net/ethernet/spacemit/k1_emac.c
> @@ -228,6 +228,12 @@ static void emac_init_hw(struct emac_priv *priv)
>  		DEFAULT_TX_THRESHOLD);
>  	emac_wr(priv, MAC_RECEIVE_PACKET_START_THRESHOLD, DEFAULT_RX_THRESHOLD);
>  
> +	/* Set maximum frame size and jabber size based on configured buffer
> +	 * size.
> +	 */
> +	emac_wr(priv, MAC_MAXIMUM_FRAME_SIZE, priv->dma_buf_sz);
> +	emac_wr(priv, MAC_RECEIVE_JABBER_SIZE, priv->dma_buf_sz);
> +

Oh and... maybe these should be priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN?
Re: [PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames
Posted by Jakub Kicinski 1 week, 3 days ago
On Tue, 27 Jan 2026 12:58:21 +0800 Vivian Wang wrote:
> Oh and... maybe these should be priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN?

+ 2 * VLAN_HLEN perhaps?
Re: [PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames
Posted by Vivian Wang 1 week, 3 days ago
On 1/28/26 09:24, Jakub Kicinski wrote:
> On Tue, 27 Jan 2026 12:58:21 +0800 Vivian Wang wrote:
>> Oh and... maybe these should be priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN?
> + 2 * VLAN_HLEN perhaps?

... yeah looks like I've simply messed up the whole MTU and max frame
size configuration thing.

* Tomas: Do you still want to deal with all this and figure out all the
MTU stuff that needs to be fixed? I can give it a go but I don't want to
steal your credit.

Regards,
Vivian "dramforever" Wang
Re: [PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames
Posted by Vivian Wang 1 week, 4 days ago
Hi Tomas,

Thanks for the fix. Just a few more things...

Firstly, I believe it is preferred to send a new patch version in its
own thread with a link to the previous version. See
Documentation/process/maintainer-netdev.rst:

  The new version of patches should be posted as a separate thread,
  not as a reply to the previous posting. Change log should include a link
  to the previous posting (see :ref:`Changes requested`).

You can do that for v3.

Secondly...

On 1/27/26 01:14, Tomas Hlavacek wrote:
> [...]
>
> diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
> index 220eb5ce7583..31b1bdb2827e 100644
> --- a/drivers/net/ethernet/spacemit/k1_emac.c
> +++ b/drivers/net/ethernet/spacemit/k1_emac.c
> @@ -228,6 +228,12 @@ static void emac_init_hw(struct emac_priv *priv)
>  		DEFAULT_TX_THRESHOLD);
>  	emac_wr(priv, MAC_RECEIVE_PACKET_START_THRESHOLD, DEFAULT_RX_THRESHOLD);
>  
> +	/* Set maximum frame size and jabber size based on configured buffer
> +	 * size.
> +	 */
> +	emac_wr(priv, MAC_MAXIMUM_FRAME_SIZE, priv->dma_buf_sz);
> +	emac_wr(priv, MAC_RECEIVE_JABBER_SIZE, priv->dma_buf_sz);
> +

I tested this (also setting MAC_TRANSMIT_JABBER_SIZE, as Yixun
described) and it appears that this has surfaced a latent bug in the code.

I found that the hardware can't actually handle 4096-byte buffers, since
the size field is only 12-bit. (It was my fault to assume that existing
code was right in this regard...) So MTU larger than ~2000 breaks the
hardware, and also triggers the WARN_ON_ONCE() in emac_rx_frame_good().
4095 works just fine.

Can you include this in v3 as well? Maybe also reword the commit
messages a bit. Thanks.

(Here's hoping Thunderbird hasn't destroyed the whitespace...)

diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
index 31b1bdb2827e..78306a06a329 100644
--- a/drivers/net/ethernet/spacemit/k1_emac.c
+++ b/drivers/net/ethernet/spacemit/k1_emac.c
@@ -38,7 +38,7 @@
 
 #define EMAC_DEFAULT_BUFSIZE		1536
 #define EMAC_RX_BUF_2K			2048
-#define EMAC_RX_BUF_4K			4096
+#define EMAC_RX_BUF_MAX			FIELD_MAX(RX_DESC_1_BUFFER_SIZE_1_MASK)
 
 /* Tuning parameters from SpacemiT */
 #define EMAC_TX_FRAMES			64
@@ -937,7 +937,7 @@ static int emac_change_mtu(struct net_device *ndev, int mtu)
 	else if (frame_len <= EMAC_RX_BUF_2K)
 		priv->dma_buf_sz = EMAC_RX_BUF_2K;
 	else
-		priv->dma_buf_sz = EMAC_RX_BUF_4K;
+		priv->dma_buf_sz = EMAC_RX_BUF_MAX;
 
 	ndev->mtu = mtu;
 
@@ -2011,7 +2011,7 @@ static int emac_probe(struct platform_device *pdev)
 	ndev->hw_features = NETIF_F_SG;
 	ndev->features |= ndev->hw_features;
 
-	ndev->max_mtu = EMAC_RX_BUF_4K - (ETH_HLEN + ETH_FCS_LEN);
+	ndev->max_mtu = EMAC_RX_BUF_MAX - (ETH_HLEN + ETH_FCS_LEN);
 	ndev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
 
 	priv = netdev_priv(ndev);
Re: [PATCH net v2] net: spacemit: k1-emac: program frame size registers for jumbo frames
Posted by Yixun Lan 1 week, 4 days ago
Hi Tomas,

On 18:14 Mon 26 Jan     , Tomas Hlavacek wrote:
> The driver allows changing MTU up to 4K via emac_change_mtu() and
> allocates appropriately sized DMA buffers, but it never programs the
> MAC_MAXIMUM_FRAME_SIZE and MAC_RECEIVE_JABBER_SIZE registers.
> 
> This causes the MAC hardware to reject frames larger than the default
> 1518 bytes, even when larger buffers are allocated. Frames exceeding
> the default size trigger jabber errors and are discarded.
> 
> Fixes: bfec6d7f2001 ("net: spacemit: Add K1 Ethernet MAC")
> Cc: stable@vger.kernel.org
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
> v2: Added Fixes tag and Cc stable.
> 
>  drivers/net/ethernet/spacemit/k1_emac.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
> index 220eb5ce7583..31b1bdb2827e 100644
> --- a/drivers/net/ethernet/spacemit/k1_emac.c
> +++ b/drivers/net/ethernet/spacemit/k1_emac.c
> @@ -228,6 +228,12 @@ static void emac_init_hw(struct emac_priv *priv)
>  		DEFAULT_TX_THRESHOLD);
>  	emac_wr(priv, MAC_RECEIVE_PACKET_START_THRESHOLD, DEFAULT_RX_THRESHOLD);
>  
> +	/* Set maximum frame size and jabber size based on configured buffer
> +	 * size.
> +	 */
> +	emac_wr(priv, MAC_MAXIMUM_FRAME_SIZE, priv->dma_buf_sz);
> +	emac_wr(priv, MAC_RECEIVE_JABBER_SIZE, priv->dma_buf_sz);
> +
I'm no expert here, but just notice there is additional MAC_TRANSMIT_JABBER_SIZE
register which is no need to set? or is the problem on receive side only?

>  	/* Configure flow control (enabled in emac_adjust_link() later) */
>  	emac_set_mac_addr_reg(priv, fc_dest_addr, MAC_FC_SOURCE_ADDRESS_HIGH);
>  	emac_wr(priv, MAC_FC_PAUSE_HIGH_THRESHOLD, DEFAULT_FC_FIFO_HIGH);
> -- 
> 2.52.0
> 

-- 
Yixun Lan (dlan)