Skip to content

arch/rp23xx: add bounded timeout to SPI DMA completion wait - #20587

Open
Sarthak-Pandey wants to merge 1 commit into
apache:masterfrom
Sarthak-Pandey:fix/rp23xx-spi-dma-timeout
Open

Sarthak-Pandey wants to merge 1 commit into
apache:masterfrom
Sarthak-Pandey:fix/rp23xx-spi-dma-timeout

Conversation

@Sarthak-Pandey

Copy link
Copy Markdown

Summary

Fixes #19305

The SPI DMA exchange path in rp23xx_spi.c previously waited for DMA completion using two back-to-back untimed, uninterruptible semaphore waits (nxsem_wait_uninterruptible()). If a DMA transfer never completes (e.g. stalled slave device or bus glitch), the calling thread sleeps indefinitely without timeout.

In network drivers such as W5500 Ethernet on SPI0 running from the LP work queue while holding net_lock, this stalled wait causes the LP worker to sleep forever while holding the network lock, wedging the whole network stack (ping hangs, network shell commands block, and driver TX-timeout recovery cannot run).

This patch addresses the issue for both ARM and RISC-V ports of rp23xx:

  • Uses bounded waiting with nxsem_tickwait_uninterruptible() and a dynamic timeout calculated from transfer size, SPI clock frequency, and a safety margin (100 ms).
  • On timeout/failure:
    • Stops both TX and RX DMA channels via rp23xx_dmastop().
    • Disables DMA requests in the SPI control register (SSPDMACR).
    • Resets the semaphore count (nxsem_reset(&priv->dmasem, 0)) to avoid residual posts corrupting subsequent transfers.
    • Flushes any stale bytes remaining in the RX FIFO.
    • Logs the error via spierr() and returns instead of hanging forever.

Impact

  • Architecture: ARM and RISC-V (arch/arm/src/rp23xx/rp23xx_spi.c, arch/risc-v/src/rp23xx-rv/rp23xx_spi.c).
  • User Impact: Prevents system-wide network stack deadlocks when an SPI transfer stalls. The network driver can gracefully degrade, release net_lock, and run its TX timeout recovery handlers.
  • Compatibility: Fully backwards-compatible.

Testing

  • Verified syntax and NuttX coding style compliance using nxstyle.
  • Tested build and static verification against RP23xx SPI DMA paths.

@github-actions github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Arch: risc-v Issues related to the RISC-V (32-bit or 64-bit) architecture Size: M The size of the change in this PR is medium labels Oct 11, 2026
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

The SPI DMA exchange path previously waited for completion with two untimed, uninterruptible semaphore waits (nxsem_wait_uninterruptible). If a DMA transfer never completes (e.g. stalled slave or bus glitch), the calling thread sleeps indefinitely.

In network drivers like W5500 on SPI0 running from the LP work queue while holding net_lock, this causes the worker to hang permanently, wedging the whole network stack and blocking recovery handlers.

This patch updates both ARM and RISC-V ports of rp23xx:

- Switches to nxsem_tickwait_uninterruptible() with a transfer-size-derived timeout plus a safety margin.

- On timeout, forcibly stops both DMA channels with rp23xx_dmastop(), disables SPI DMA in the control register, resets the semaphore count, drains leftover RX FIFO bytes, and logs an error to degrade gracefully instead of deadlocking.

Fixes apache#19305

Signed-off-by: Sarthak Pandey <sarthak@email.com>
@Sarthak-Pandey
Sarthak-Pandey force-pushed the fix/rp23xx-spi-dma-timeout branch from bd07013 to 631c1ec Compare October 12, 2026 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Arch: risc-v Issues related to the RISC-V (32-bit or 64-bit) architecture Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] arch/arm/rp23xx: SPI DMA completion waits are uninterruptible with no timeout — one stalled transfer wedges the whole network stack

2 participants