Skip to content

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

Description

@ricardgb

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):

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions