From a8338c1addd205df6716abaa85a9784ed083ae33 Mon Sep 17 00:00:00 2001 From: "Daniel P. Carvalho" Date: Sun, 4 Oct 2026 00:54:54 -0300 Subject: [PATCH] arch/mips/pic32mz: receive full size Ethernet frames. The RX byte count and the EMAC1MAXF limit both include the 4-byte FCS, but the driver did not account for it: - RXBUFSZ was programmed with CONFIG_NET_ETH_PKTSIZE, rounded down to 16 bytes (1504 for 1514), so longer frames were split into fragments and dropped. - EMAC1MAXF was set to CONFIG_NET_ETH_PKTSIZE, so the MAC rejected frames longer than CONFIG_NET_ETH_PKTSIZE - 4. - d_len included the FCS. Make room for the FCS in the buffers, program RXBUFSZ with the aligned buffer size and EMAC1MAXF with CONFIG_NET_ETH_PKTSIZE + 4, and remove the FCS from d_len. The largest ping that got an answer was 1458 bytes; it is now 1472, the full 1500-byte MTU. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Daniel P. Carvalho --- arch/mips/src/pic32mz/pic32mz_ethernet.c | 26 +++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/mips/src/pic32mz/pic32mz_ethernet.c b/arch/mips/src/pic32mz/pic32mz_ethernet.c index c2358940f27..77fd4c741ab 100644 --- a/arch/mips/src/pic32mz/pic32mz_ethernet.c +++ b/arch/mips/src/pic32mz/pic32mz_ethernet.c @@ -146,6 +146,10 @@ #define DESC_SIZE 20 #define DESC_PADSIZE DMA_ALIGN_UP(DESC_SIZE) +/* The RX DMA also stores the 4-byte frame check sequence in the buffer */ + +#define PIC32MZ_FCS_SIZE 4 + /* Make sure that the size of each buffer is a multiple of 4 bytes. This * will force alignment of all buffers to 4-byte boundaries (this is needed * by the queuing logic which will cast each buffer address to a pointer @@ -158,7 +162,8 @@ * above by aligning the buffer to D-Cache size. */ -#define PIC32MZ_ALIGNED_BUFSIZE DMA_ALIGN_UP(CONFIG_NET_ETH_PKTSIZE) +#define PIC32MZ_ALIGNED_BUFSIZE DMA_ALIGN_UP(CONFIG_NET_ETH_PKTSIZE + \ + PIC32MZ_FCS_SIZE) /* The number of buffers will, then, be one for each descriptor plus one * extra @@ -1479,10 +1484,16 @@ static void pic32mz_rxdone(struct pic32mz_driver_s *priv) pic32mz_putreg(ETH_CON1_BUFCDEC, PIC32MZ_ETH_CON1SET); - /* Get the packet length */ + /* Get the packet length, without the FCS included in the byte + * count. + */ priv->pd_dev.d_len = (rxdesc->rsv2 & RXDESC_RSV2_BYTECOUNT_MASK) >> RXDESC_RSV2_BYTECOUNT_SHIFT; + if (priv->pd_dev.d_len >= PIC32MZ_FCS_SIZE) + { + priv->pd_dev.d_len -= PIC32MZ_FCS_SIZE; + } /* Update statistics */ @@ -2275,9 +2286,11 @@ static int pic32mz_ifup(struct net_driver_s *dev) * untagged maximum size Ethernet frame is 1518 octets. A tagged frame adds * four octets for a total of 1522 octets. If a shorter/longer maximum * length restriction is desired, program this 16-bit field. + * The maximum includes the FCS. */ - pic32mz_putreg(CONFIG_NET_ETH_PKTSIZE, PIC32MZ_EMAC1_MAXF); + pic32mz_putreg(CONFIG_NET_ETH_PKTSIZE + PIC32MZ_FCS_SIZE, + PIC32MZ_EMAC1_MAXF); /* Configure the MAC station address in the EMAC1SA0, EMAC1SA1 and * EMAC1SA2 registers. On PIC32MZ EC/EF these registers are loaded at @@ -2354,10 +2367,13 @@ static int pic32mz_ifup(struct net_driver_s *dev) /* Set the size of the RX buffers in the RXBUFSZ bit (ETHCON2:4-10) (all * receive descriptors use the same buffer size). Keep in mind that using * packets that are too small leads to packet fragmentation and has a - * noticeable impact on the performance. + * noticeable impact on the performance. RXBUFSZ is in units of 16 + * bytes: use the aligned buffer size, which has room for the FCS, so + * that a full size frame is not truncated into two fragments. */ - pic32mz_putreg(ETH_CON2_RXBUFSZ(CONFIG_NET_ETH_PKTSIZE), PIC32MZ_ETH_CON2); + pic32mz_putreg(ETH_CON2_RXBUFSZ(PIC32MZ_ALIGNED_BUFSIZE), + PIC32MZ_ETH_CON2); /* Reset state variables */