Commit 3125fc17 authored by Tomas Hlavacek's avatar Tomas Hlavacek Committed by Jakub Kicinski
Browse files

net: spacemit: k1-emac: fix jumbo frame support



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: bfec6d7f ("net: spacemit: Add K1 Ethernet MAC")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarTomas Hlavacek <tmshlvck@gmail.com>
Link: https://patch.msgid.link/20260130102301.477514-1-tmshlvck@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 79987ce1
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -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);