[BUG] arch/arm/rp23xx: SPI DMA completion waits are uninterruptible with no timeout — one stalled transfer wedges the whole network stack
- Dominant language
- C
- Stars
- 4k
- Forks
- 1.7k
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 237
Description
> **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.
*Vs `arch/arm/src/rp23xx/rp23xx_spi.c` at master `50f91ef502`.*
## Description
The SPI DMA exchange path waits for completion with two back-to-back
untimed, uninterruptible semaphore waits (l. 1196 and l. 1201):
```c
if (nxsem_wait_uninterruptible(&priv->dmasem) != OK)
{
spierr("dma error\n");
}
if (nxsem_wait_uninterruptible(&priv->dmasem) != OK)
{
spierr("dma error\n");
}
```
If a DMA transfer never completes, the calling thread sleeps forever with
no escape. DMA is on by default (`RP23XX_DMAC` default y,
`RP23XX_SPI_DMA` default y, threshold 4), so effectively all bulk SPI
transfers take this path.
## Impact observed on real hardware
With a W5500 Ethernet controller on SPI0 (W5500-EVB-Pico2), network
drivers run their transfers from the LP work queue while holding the
network lock. When the wait stalled, the LP worker slept forever holding
`net_lock`: ping stopped, every shell command touching the network
(`ifconfig`, ...) blocked immediately after echo, and even the driver's
own TX-timeout recovery could not run (it is queued to the same blocked
LP worker). The system was otherwise alive (non-network shell paths
responsive).
A/B on the same board and workload: with `CONFIG_RP23XX_SPI_DMA=n` the
identical external event left the system fully healthy. (The same
untimed-wait pattern appears worth checking in `rp2040_spi.c`, from which
this port derives.)
## Suggested fix
Use a bounded wait (e.g. `nxsem_tickwait_uninterruptible()` with a
transfer-size-derived timeout); on timeout, stop the DMA channels, log,
and fall back to polled PIO or return an error — degrade instead of
deadlocking.
---
*Disclosure: found during an AI-assisted (Claude Code) audit; the A/B
observation is from my own hardware testing.*
Contributor guide
Research direction
Start in arch/arm/src/rp23xx/rp23xx_spi.c at the two DMA semaphore waits around lines 1196 and 1201, then review the RP23XX_DMAC and RP23XX_SPI_DMA defaults. Compare the related wait pattern in rp2040_spi.c. Done means a stalled transfer no longer blocks indefinitely and instead reaches the proposed timeout recovery or error path; validate against the W5500 SPI workload if hardware is available.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100