ricardgb opened a new issue, #19304:
URL: https://github.com/apache/nuttx/issues/19304
> **Disclaimer:** This report was prepared with AI assistance (Claude Code).
I reviewed it, verified the code citations against master myself, and validated
the behaviour on real hardware where noted before filing.
*Line numbers vs `drivers/net/w5500.c` at master `50f91ef502`.*
## Description
The driver treats every unexpected condition in its interrupt and receive
paths as fatal and responds with `w5500_fence()` — which disables the IRQ,
asserts hardware RST **and keeps it asserted**, and sets `w_bifup = false`
(l. 932–937). Nothing ever unfences again from these paths, and
`netdev_carrier_off()` is never called, so the network stack keeps queueing
into a dead device forever. The link LEDs go dark and the interface is
unrecoverable until a power cycle or manual `ifdown`/`ifup`.
Paths that fence permanently:
- `w5500_interrupt_work()`: a SIR bit for any socket other than 0
(l. 1542–1548), or `SN_IR == 0`, or any `SN_IR` bit outside
`RECV|SEND_OK` (l. 1563–1568) → `goto error` → fence (l. 1603–1605).
These "unexpected" bits are reachable in normal operation: spurious
CON/DISCON/TIMEOUT-shaped events, or a single glitched SPI read during
an interrupt burst.
- `w5500_receive()`: `read16_atomic` failure (l. 1266–1269),
`s0_rx_rsr < 2` (l. 1282–1286), `pktlen > s0_rx_rsr` (l. 1300–1307) →
fence (l. 1437–1438). One inconsistent length read bricks the interface
(see also the separate missing-`Sn_CR`-wait issue, which can produce this
with a perfect SPI bus).
- After an internal fence, `w5500_interrupt_work()` still falls through to
`done:` and unconditionally re-enables the level-low GPIO IRQ (l. 1599)
with the chip in reset and INTn floating. On the rp2040 reference glue,
`rp2040_common_initialize.c` (l. 195–197) leaves the pad's default
pull-down on the open-drain INTn, so this can become a level-low
interrupt storm / LPWORK livelock.
## Reproduction (real hardware)
Bursts of short-lived TCP connections (e.g. 200 × connect/close against
telnetd) wedge a W5500-EVB-Pico within 1–2 bursts with the stock driver.
With tolerant error handling (below) the same board survives repeated
bursts, flood ping, and a 40-minute soak with zero loss. Reproduced on
both W5500-EVB-Pico (rp2040) and W5500-EVB-Pico2 (rp23xx).
## Suggested fix
- `w5500_interrupt_work()`: acknowledge **all** pending `Sn_IR` bits, act
only on `RECV|SEND_OK`, warn on the rest — never fence from the
interrupt path.
- `w5500_receive()` error path: resync socket 0 (CLOSE + OPEN in MACRAW +
reset the local TX-ring mirror) and drop the partial frame instead of
fencing.
- Only re-enable the IRQ at `done:` if `w_bifup` is still true.
- Where a fence is genuinely terminal, report `netdev_carrier_off()`.
A reference implementation, validated on both boards above, is at:
`https://github.com/ricardgb/nuttx/tree/w5500-driver-fixes`
---
*Disclosure: analysis and reference fixes developed with AI assistance
(Claude Code), reviewed and hardware-validated by me. All citations can be
verified directly against master.*
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]