]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: spacemit: k1-emac: fix jumbo frame support
authorTomas Hlavacek <tmshlvck@gmail.com>
Fri, 30 Jan 2026 10:23:01 +0000 (11:23 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 3 Feb 2026 03:15:02 +0000 (19:15 -0800)
The driver never programs the MAC frame size and jabber registers,
causing the hardware to reject frames larger than the default 1518
bytes even when larger DMA buffers are allocated.

Program MAC_MAXIMUM_FRAME_SIZE, MAC_TRANSMIT_JABBER_SIZE, and
MAC_RECEIVE_JABBER_SIZE based on the configured MTU. Also fix the
maximum buffer size from 4096 to 4095, since the descriptor buffer
size field is only 12 bits. Account for double VLAN tags in frame
size calculations.

Fixes: bfec6d7f2001 ("net: spacemit: Add K1 Ethernet MAC")
Cc: stable@vger.kernel.org
Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
Link: https://patch.msgid.link/20260130102301.477514-1-tmshlvck@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/spacemit/k1_emac.c

index 88e9424d2d51aa7e3e76c3318172901ec1240c8b..b49c4708bf9eb10c96c966571e9d0ddc6b3ebee3 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
@@ -38,7 +39,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
@@ -202,8 +203,7 @@ static void emac_init_hw(struct emac_priv *priv)
 {
        /* Destination address for 802.3x Ethernet flow control */
        u8 fc_dest_addr[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x01 };
-
-       u32 rxirq = 0, dma = 0;
+       u32 rxirq = 0, dma = 0, frame_sz;
 
        regmap_set_bits(priv->regmap_apmu,
                        priv->regmap_apmu_offset + APMU_EMAC_CTRL_REG,
@@ -228,6 +228,15 @@ 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 MTU,
+        * accounting for Ethernet header, double VLAN tags, and FCS.
+        */
+       frame_sz = priv->ndev->mtu + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN;
+
+       emac_wr(priv, MAC_MAXIMUM_FRAME_SIZE, frame_sz);
+       emac_wr(priv, MAC_TRANSMIT_JABBER_SIZE, frame_sz);
+       emac_wr(priv, MAC_RECEIVE_JABBER_SIZE, frame_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);
@@ -924,14 +933,14 @@ static int emac_change_mtu(struct net_device *ndev, int mtu)
                return -EBUSY;
        }
 
-       frame_len = mtu + ETH_HLEN + ETH_FCS_LEN;
+       frame_len = mtu + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN;
 
        if (frame_len <= EMAC_DEFAULT_BUFSIZE)
                priv->dma_buf_sz = EMAC_DEFAULT_BUFSIZE;
        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;
 
@@ -2025,7 +2034,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 + 2 * VLAN_HLEN + ETH_FCS_LEN);
        ndev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
 
        priv = netdev_priv(ndev);