Describe the bug
drivers/ethernet/eth_w5500.c only services one received frame per interrupt, but Sn_IR is a latch that gets cleared for everything that arrived up to that point. If a second frame lands between the read and the clear of Sn_IR, its notification is gone. The frame itself is fine and sits in the W5500's RX buffer, but there's nothing left pending to tell the driver to go get it.
This piles up over time. Eventually the 16 KB RX buffer fills, the chip stops accepting new frames, and you're left with a node that transmits fine and reports link up, but answers nothing.
Target platform: nRF54L15 + W5500 over SPI @ 8 MHz, nRF Connect SDK v3.4.0 (Zephyr 4.4.0).
Workaround tried: none possible from the application side — by the time anything else can look, the notification for that frame is already gone, and the driver only ever reads RX off the back of S0_IR_RECV.
Regression: not a regression from a known-good version as far as I can tell — checked the same code path against current main and the bug is unchanged there too, so this isn't something that broke recently.
Regression
Steps to reproduce
- Build and flash a board with the eth_w5500 driver in interrupt mode, with steady incoming traffic (e.g.
ping -i 0.1 from another host).
- Watch round-trip latency over a few minutes — it climbs steadily rather than staying flat.
- Read
Sn_RX_RSR and Sn_IR directly over SPI from the application: Sn_RX_RSR keeps growing while Sn_IR reads 0x00 and INTn is de-asserted, meaning bytes are sitting in the chip's RX buffer with nothing pending to trigger a read.
- Left long enough (a few minutes on a busy LAN), the 16 KB buffer fills and RX stops entirely. TX keeps working and link status stays up.
Relevant log output
uptime Sn_RX_RSR Sn_IR INTn
28 s 2350 B 0x00 de-asserted
130 s 9741 B 0x00 de-asserted
244 s 15415 B 0x00 de-asserted
(buffer size 16384 B)
Latency vs. inbound rate on one node:
~1.7 pkt/s -> median ping 13.1 s (0% loss)
~11.7 pkt/s -> median ping 1.8 s (0% loss)
With the suggested fix applied, Sn_RX_RSR reads 0 on every sample,
including right after three back-to-back 40-frame bursts.
Impact
Annoyance – Minor irritation; no significant impact on usability or functionality.
Environment
- OS: MacOS 26.6.2 (build host)
- Toolchain: nRF Connect SDK v3.4.0 (Zephyr 4.4.0)
- Board: nRF54L15 + W5500 over SPI @ 8 MHz
- Confirmed same code path unchanged on current Zephyr
main
Additional Context
The relevant code is w5500_check_for_ir():
w5500_spi_read(dev, W5500_S0_IR, &ir, 1);
if (ir != 0U) {
w5500_spi_write(dev, W5500_S0_IR, &ir, 1); /* clears everything pending */
if (ir & S0_IR_RECV) {
w5500_rx(dev); /* but only reads ONE frame */
}
}
w5500_rx() reads Sn_RX_RSR only to check if it's zero, never loops on it. The
-EAGAIN branch in w5500_thread_interrupt() (monitor-period timeout) only calls
w5500_update_link_status(), so it doesn't drain anything either — no safety net.
Suggested fix:
- loop
w5500_rx() until Sn_RX_RSR == 0 instead of once per interrupt
- have the monitor-period timeout branch drain too, so a missed notification just
costs latency instead of eventually killing RX
- break the service loop if
INTn is asserted but Sn_IR reads 0, to avoid spinning
Describe the bug
drivers/ethernet/eth_w5500.conly services one received frame per interrupt, butSn_IRis a latch that gets cleared for everything that arrived up to that point. If a second frame lands between the read and the clear ofSn_IR, its notification is gone. The frame itself is fine and sits in the W5500's RX buffer, but there's nothing left pending to tell the driver to go get it.This piles up over time. Eventually the 16 KB RX buffer fills, the chip stops accepting new frames, and you're left with a node that transmits fine and reports link up, but answers nothing.
Target platform: nRF54L15 + W5500 over SPI @ 8 MHz, nRF Connect SDK v3.4.0 (Zephyr 4.4.0).
Workaround tried: none possible from the application side — by the time anything else can look, the notification for that frame is already gone, and the driver only ever reads RX off the back of
S0_IR_RECV.Regression: not a regression from a known-good version as far as I can tell — checked the same code path against current
mainand the bug is unchanged there too, so this isn't something that broke recently.Regression
Steps to reproduce
ping -i 0.1from another host).Sn_RX_RSRandSn_IRdirectly over SPI from the application:Sn_RX_RSRkeeps growing whileSn_IRreads 0x00 andINTnis de-asserted, meaning bytes are sitting in the chip's RX buffer with nothing pending to trigger a read.Relevant log output
Impact
Annoyance – Minor irritation; no significant impact on usability or functionality.
Environment
mainAdditional Context
The relevant code is
w5500_check_for_ir():w5500_rx()readsSn_RX_RSRonly to check if it's zero, never loops on it. The-EAGAINbranch inw5500_thread_interrupt()(monitor-period timeout) only callsw5500_update_link_status(), so it doesn't drain anything either — no safety net.Suggested fix:
w5500_rx()untilSn_RX_RSR == 0instead of once per interruptcosts latency instead of eventually killing RX
INTnis asserted butSn_IRreads 0, to avoid spinning