Repository navigation
media: apple: avd: safety fixes for the current driver (mailbox, early completion, reset, AV1, FFmpeg HEVC) - #725
Merged
Merged
Conversation
ref_frame_idx entries are -1 on frames that use no references (FFmpeg fills key frames that way), and the AV1 builder indexed reference_frame_ts with them directly: UBSAN reported index -1 into reference_frame_ts[8] in set_header and its helpers on the first AV1 decode on the J616s and the Neo. Look the timestamp up through a helper that returns a value no buffer has for an out-of-range index, so the lookup takes the existing missing-reference path. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The interrupt handler read MBOX1_RETRIEVE without checking that the mailbox held a message. Reading an empty mailbox returns the previous message again, so a spurious or early interrupt replayed the last PP DONE: the next frame finished before its PP had run, userspace got a wrong picture, the frame's own PP DONE never came and the watchdog reset the decoder. Multi-stream H.264 benchmarks on the J616s hit this as bit-exactness failures, "ignoring stale completion" and timeouts. Check the empty flag in MBOX1_STATUS (bit 17) first, give a message that is not readable yet up to 10 us, and otherwise acknowledge and ignore the interrupt. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The firmware reports VP DONE, the driver kicks PP, and PP DONE finishes the job. HEVC, VP9 and AV1 pictures with several segments kick PP once per segment, and a surplus PP DONE could arrive after the next job was submitted and finish it before its VP had even completed. Its buffers then went back to userspace while the decoder was still writing them; the J616s logged DART write faults at just-released addresses in such a run. Remember per job that its VP finished and its PP was kicked, and treat a PP DONE before that as stale. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
…fter repeated ones The J616s hung hard three times in one night, each time after decoder timeouts and resets, and the Neo hung after resetting once per frame during a burst of VP errors. The reset asserted the pmgr reset with the CM3 still running, with DMA still able to reach memory, and while the threaded interrupt handler could be reading the mailbox; nothing bounded how often it ran. Before resetting: disable the interrupt (waiting for a running handler), stop the CM3, attach the empty IOMMU domain so a transfer still in flight faults at the DART instead of writing memory that may already be reused, and wait 5 ms for such transfers to drain. Then reset, restore and check the DMA domain, and boot. Each step is logged before it runs. Recover at most twice a minute and at least 20 ms apart. A failed recovery or a third one within a minute retires the decoder until the module is reloaded. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A stream whose frame timed out or hit a VP error usually fails the next frame the same way. The Neo reset the decoder once per frame through a broken HEVC stream until it hung. After such a failure, finish every job of that stream with an error without touching the hardware, completing the request controls so the request fds still signal, until streaming is restarted. A retired decoder fails every job the same way. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The HEVC builder computes each slice's coded data address and size from GStreamer's layout: slices tile the OUTPUT buffer as whole NALs, bit_size covers the whole NAL and data_byte_offset is the slice data's offset in it. FFmpeg's V4L2 request backend gives data_byte_offset from the start of the buffer and a bit_size of the slice data only. Every slice then got a wrong address and a size short by its header, the VP raised its error interrupt on every frame, and the decoder was reset once per frame. This is the "H0 error" storm the Neo hit in an FFmpeg-based benchmark. When the slices describe a complete, unambiguous absolute layout, rewrite the run's private copy into the equivalent NAL-relative description. The GStreamer layout and anything ambiguous are left untouched. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Contributor
Author
|
Post-merge evidence from the same M2 run (tt3). A bit-flipped VP9 stream decoded through ffmpeg |
This was referenced Oct 31, 2026
media: apple: avd: park the decoder with DMA blocked; rest instead of retiring on a reset storm
#755
Closed
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.
Small safety series for the shipping AVD driver, independent of the frame-queue rewrite (#713). Each commit stands alone and is reviewable on its own.
Why
During last night's decode benchmarks the J616s hung hard three times and the Neo once. pstore was empty every time, and on the third J616s hang the hardware watchdog did not recover the machine. Every hang came after decoder timeouts and resets; runs without a reset did not hang.
The stock driver was involved directly:
Logged evidence:
reference_frame_tson the first AV1 decode.What it changes
ref_frame_idxbefore indexingreference_frame_ts. A -1 entry now takes the existing missing-reference path.Tests
ARCH=arm64 LLVM=1 W=1 KCFLAGS=-Werror, clean at every commit.reports/engines-20261101/avd/m2-725/.Results on the M2
The bench is avd-bench (FFmpeg V4L2 request, demux in memory, every displayed frame MD5-checked against software decode before and after the timed passes). Each row is the best of 3 passes in aggregate fps. Stock is the tt3 in-tree module on the same boot.
-hwaccel v4l2request) gives framemd5 identical to software decode for H.264, HEVC and VP9 at 1080p and 4K. A 4K HEVC clip decodes 120 frames in 0.39 s at 32 % of one CPU.290, VP9 3x124).H4 error,recover: stop firmware,block DMA,reset,restore DMA,boot firmware,done, thenstream stopped, and the recovery took 5 ms. The third error within the minute loggeddecoder retired after repeated resets. A clean decode then failed at once without touching the hardware, and after a module reload it decoded bit-exact at 503 fps. No DART faults appeared in any of this.The root-cause write-up (ranked hypotheses for the hangs) lives with the AVD lane's reports; the same fixes are in the rewrite branch (#713).
🤖 Generated with Claude Code