fix(esp_eth): recover EMAC RX from descriptor exhaustion under bursts (IDFGH-17916)#18799
Open
scrambletools wants to merge 2 commits into
Open
fix(esp_eth): recover EMAC RX from descriptor exhaustion under bursts (IDFGH-17916)#18799scrambletools wants to merge 2 commits into
scrambletools wants to merge 2 commits into
Conversation
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.
kostaond
reviewed
Jul 8, 2026
kostaond
left a comment
Collaborator
There was a problem hiding this comment.
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). */ |
Collaborator
There was a problem hiding this comment.
@scrambletools really nice job identifying this issue! Just please make the comments more brief - one or two lines.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
RECEIVE_BUFF_UNAVAILABLEis neither inEMAC_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.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_defaultdisables 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.