DVR reencode: guarantee <4GB physical placement for RGA-touched buffers - #143
Conversation
PR Summary by QodoDVR reencode: force CMA/CONTIG (<4GB) buffers for RGA2 on large-RAM boards
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1.
|
RGA2's MMU can only address physical memory below 4GB. A kernel bug in
the Rockchip GEM allocator (__GFP_DMA32 is only ever applied under
CONFIG_ARM_LPAE, a 32-bit-only Kconfig symbol never set on arm64) means
buffers can silently land above that boundary on >=2GB RAM boards,
which a field support-package capture confirmed: RGA rejected a job
with "unsupported memory larger than 4G", caught cleanly by the
existing fail-fast guard.
MPP's own MPP_BUFFER_FLAGS_CONTIG/DMA32 flags turned out not to reliably
route to CMA on this platform -- they silently redirect through the
dma-heap backend, which expects a heap name ("cma-dma32" etc.) this
kernel's dma-heap driver doesn't expose, so the whole buffer group
fails to construct with no diagnostic output. Instead, on boards with
enough RAM for this to matter (checked via mem_info.h's runtime
/proc/meminfo probe, not a compile-time board flag), the two
FrameColorCorrect GBM render targets and FrameProcessor's proc_copy_
working buffer are allocated as raw CMA-backed KMS dumb buffers
(ROCKCHIP_BO_CONTIG) and imported directly, bypassing GBM/MPP's
allocator abstractions for just these buffers. Falls back to the
existing GBM/MPP paths when CONTIG allocation itself fails (e.g. CMA
exhausted), consistent with the project's fail-fast philosophy: a
transient allocation failure on the working buffer is fatal (stops
reencode, notifies via OSD) rather than silently risking a buffer
placed >=4GB again; the GBM render targets fall back per-target since
RGA doesn't care how a buffer was allocated once it's <4GB.
Hardware-validated via fault injection (forcing the large-RAM path on
a 1GB device): CONTIG allocation succeeds until CMA is exhausted, then
falls back cleanly; 5x rapid start/stop cycles showed no crashes, fd
leaks, or corrupted output. Confirmed inert (unchanged GBM/MPP paths)
with the real RAM check on the same 1GB device.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
close() in alloc_contig_proc_copy() compiled fine locally via a transitive include, but bullseye's older toolchain doesn't pull it in the same way: 'close' was not declared in this scope. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Set DRM_CLOEXEC alongside DRM_RDWR on the new PRIME_HANDLE_TO_FD exports, matching the existing convention in drm.c. - FrameColorCorrect::destroy_targets() was closing the CONTIG path's GEM handle via DRM_IOCTL_GEM_CLOSE; switched to DRM_IOCTL_MODE_DESTROY_DUMB to match alloc_contig_proc_copy() and the rest of the codebase's teardown for MODE_CREATE_DUMB buffers. - alloc_contig_proc_copy() only closed the exported prime fd when mpp_buffer_import() had visibly duped it (info.fd changed); a failed import leaves info.fd untouched, leaking the fd. Close it unconditionally instead, since mpp_buffer_import() always dups rather than taking ownership of what it's handed. Hardware-re-validated on the 1GB rig with platform_has_large_ram() fault-injected: 5x rapid start/stop cycles against a live feed, fd count plateaus after the first cycle's one-time GL/buffer init and stays flat across the rest (no leak), all recordings valid (ffprobe-checked). Confirmed inert with the real RAM check restored. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
e234f8d to
98a18b3
Compare
RGA2's MMU can only address physical memory below 4GB. A kernel bug in the Rockchip GEM allocator (__GFP_DMA32 is only ever applied under CONFIG_ARM_LPAE, a 32-bit-only Kconfig symbol never set on arm64) means buffers can silently land above that boundary on >=2GB RAM boards, which a field support-package capture confirmed: RGA rejected a job with "unsupported memory larger than 4G", caught cleanly by the existing fail-fast guard.
MPP's own MPP_BUFFER_FLAGS_CONTIG/DMA32 flags turned out not to reliably route to CMA on this platform -- they silently redirect through the dma-heap backend, which expects a heap name ("cma-dma32" etc.) this kernel's dma-heap driver doesn't expose, so the whole buffer group fails to construct with no diagnostic output. Instead, on boards with enough RAM for this to matter (checked via mem_info.h's runtime /proc/meminfo probe, not a compile-time board flag), the two FrameColorCorrect GBM render targets and FrameProcessor's proc_copy_ working buffer are allocated as raw CMA-backed KMS dumb buffers (ROCKCHIP_BO_CONTIG) and imported directly, bypassing GBM/MPP's allocator abstractions for just these buffers. Falls back to the existing GBM/MPP paths when CONTIG allocation itself fails (e.g. CMA exhausted), consistent with the project's fail-fast philosophy: a transient allocation failure on the working buffer is fatal (stops reencode, notifies via OSD) rather than silently risking a buffer placed >=4GB again; the GBM render targets fall back per-target since RGA doesn't care how a buffer was allocated once it's <4GB.
Hardware-validated via fault injection (forcing the large-RAM path on a 1GB device): CONTIG allocation succeeds until CMA is exhausted, then falls back cleanly; 5x rapid start/stop cycles showed no crashes, fd leaks, or corrupted output. Confirmed inert (unchanged GBM/MPP paths) with the real RAM check on the same 1GB device.