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 <danieloak@gmail.com>
This commit is contained in:
Daniel P. Carvalho 2026-10-04 00:54:54 -03:00 • committed by Alan C. Assis
parent 8eae6d950d
commit a8338c1add

View file

@ -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 */