Skip to content

fix(esp_eth): recover EMAC RX from descriptor exhaustion under bursts (IDFGH-17916)#18799

Open
scrambletools wants to merge 2 commits into
espressif:masterfrom
scrambletools:fix/p4-emac-rx-stall
Open

fix(esp_eth): recover EMAC RX from descriptor exhaustion under bursts (IDFGH-17916)#18799
scrambletools wants to merge 2 commits into
espressif:masterfrom
scrambletools:fix/p4-emac-rx-stall

Conversation

@scrambletools

@scrambletools scrambletools commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Two related EMAC RX defects that leave reception stalled after traffic bursts exhaust the RX descriptor ring, found on ESP32-P4 under sustained ~16k pkt/s bidirectional AVB traffic:

  1. RX task is never woken on RBU. With the ring completely full, no RECEIVE_FINISH interrupt can occur, and RECEIVE_BUFF_UNAVAILABLE is neither in EMAC_LL_CONFIG_ENABLE_INTR_MASK (whose comment already lists it as required) nor handled by the ISR. The ring is never drained and reception stalls with the DMA missed-frame counter climbing.
  2. Descriptors of overflow-truncated frames leak. A frame whose tail is cut by an RX FIFO overflow leaves first-without-last CPU-owned descriptors; the receive-length walk skips them without returning them to the DMA. Each event permanently shrinks the ring until reception stops entirely (remaining frames = 0, free descriptors = 0, DMA suspended, no interrupts possible).

Testing

Validated on ESP32-P4 (chip rev 1.3) at v6.1-dev-4859 and rebased onto master (the touched code is identical). Repro: a boot burst combining AVDECC controller enumeration with bidirectional 8000 pkt/s Class A streams wedged RX on ~50% of boots; with both fixes, 10/10 boot cycles ran clean, DMA overflow counters stayed at zero throughout, and no RX stalls occurred in extended runs.

Related

On ESP32-P4 the 256 B RX FIFO forces threshold mode (emac_hal_init_dma_default disables receive store-forward for this reason), and an RX FIFO overflow can additionally latch the MTL FIFO itself — unrecoverable by poll demand or receiver toggle; only a DMA software reset clears it. That is filed as #18800 since the proper fix likely needs silicon-errata knowledge; the two fixes here make the trigger rare and keep the descriptor state always recoverable.

With the RX descriptor ring completely full the DMA suspends and no
further RECEIVE_FINISH interrupts can occur, so the RX task was never
woken to drain the ring and reception stalled under traffic bursts.
Enable the RECEIVE_BUFF_UNAVAILABLE interrupt (an abnormal-class
interrupt, so the abnormal summary enable is required too — the mask's
own comment already listed it as required) and notify the RX task on
it; draining frees descriptors and issues the receive poll demand that
resumes the DMA.

Observed on ESP32-P4 under sustained ~16k pkt/s bidirectional load:
without this, ring exhaustion during multi-millisecond RX-task
starvation (e.g. flash-cache-disable windows) left reception stalled
with the DMA missed-frame counter climbing.
A frame whose tail is cut by an RX FIFO overflow leaves CPU-owned
descriptors with FirstDescriptor set but no LastDescriptor ever
arriving. The receive-length walk skipped past them to the next frame
without returning them to the DMA, so each such event permanently
shrank the usable RX ring; enough overflow bursts leaked every
descriptor and reception stopped for good (remaining frames = 0, free
descriptors = 0, DMA suspended, no interrupts possible).

Reclaim the orphaned segments when the walk passes a stale rx_desc:
hand their descriptors back to the DMA and issue a receive poll
demand. Most relevant on targets whose small RX FIFO forces threshold
mode (ESP32-P4: 256 B FIFO), where overflow-truncated frames are
common under bursts.
@github-actions github-actions Bot changed the title fix(esp_eth): recover EMAC RX from descriptor exhaustion under bursts fix(esp_eth): recover EMAC RX from descriptor exhaustion under bursts (IDFGH-17916) Jul 7, 2026
@espressif-bot espressif-bot added the Status: Opened Issue is new label Jul 7, 2026

@kostaond kostaond left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! I left just one minor nitpick comment. Please also squash the commits into a single one.

* RX descriptor ring is completely full the DMA suspends and no
* further RECEIVE_FINISH interrupts occur, so RBU is the only signal
* left to trigger draining (which frees descriptors and issues the
* receive poll demand that resumes the DMA). */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scrambletools really nice job identifying this issue! Just please make the comments more brief - one or two lines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Opened Issue is new

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants