mipi_rx/isp: move openipc_frame_ts MIPI_FS push from MIPI vsync IRQ to ISP FSTART (cv500 + V4)#199
Merged
Merged
Conversation
The original openipc_frame_ts MIPI_FS source (#155) unmasked the MIPI controller's vsync IRQ and W1C-cleared the bit inside the ISR top half. Empirically this desyncs the MIPI controller's row state machine on V4 (gk7205v300/hi3516ev300, see #195) and on cv500/av300 under sustained 4K30fps load (IMX415 on hi3516av300_lite: persistent magenta cast + intermittent `Timeout from venc channel 0` in majestic). #195 fixed V4 by gating the entire vsync block off — but that left V4 without any MIPI_FS event source, regressing the feature for that family. cv500's parallel block in kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c carried the same hazard. Move the MIPI_FS push to the ISP front-end FSTART status bit instead, mirroring the existing FEND push added in #178: - kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c drop the vsync block - kernel/mipi_rx/hi3516cv500/mipi_rx_hal.h revert mask to pre-#155 - kernel/isp/arch/hi3516cv500/mkp/src/isp.c + MIPI_FS push on isp_raw_int & FSTART - kernel/isp/mkp/src/isp.c + MIPI_FS push on u32IspRawIntStatus & FSTART (V4 path) The ISP front-end IRQ already fires twice per frame on these SoCs (once with FSTART set, once with FEND set; both W1C-cleared by the existing end-of-ISR ack). Edge-detect mirrors the FEND block above. No MIPI controller mask changes, no W1C in atomic context. cv200 retains its tasklet-deferred MIPI_FS push from #186 — its ISP IRQ doesn't expose a separate FEND, and its vsync-equivalent hook on VI_PT0_INT_FSTART has always been non-disruptive on V2/V2A. Verified on hardware against this branch's build of opensdk overlaid on the firmware nightly-20260527 master: cv500 av300 IMX415 4K30 | luma stdev 0.03 | MIPI_FS 188 + FEND 188 / 3 s V4 gk7205v300 IMX335 | luma stdev 0.01 | MIPI_FS 200 + FEND 201 / 3 s V2A hi3518ev200 soi_f22 | luma stdev 0.14 | MIPI_FS 89 + FEND 0 / 3 s (cv200 HW lacks FEND, expected) All three: 0 VENC timeouts in 90 s soak, 0 rt_mutex_trylock WARN. Reported-by: OpenIPC/firmware users — V4 sibling regression #195, V4A magenta cast on hi3516av300_lite (this PR), and V2A AE-runaway #197 (separate cv200 sensor_i2c fix). Closes: cv500/V4 MIPI_FS regression that #195 worked around by disabling rather than rerouting.
This was referenced May 28, 2026
widgetii
pushed a commit
that referenced
this pull request
May 28, 2026
Per-channel ring depth was hard-coded to 256 events, sized for the SR-anchor consumer in #155 which reads cached state every ~5 s and tolerates stale entries. For consumers that want every frame's (pts_us, wall_ns) — frame-by-frame latency histograms, evidence chains, multi-sensor sync correlators — 256 is too small when the reader's dispatch latency is bursty. Empirically on cv500 / hi3516av300_lite (#200 Obs 3): under RTSP+RTCP load through libevent, ~52 dropped/s accumulate over 30 s sessions with the consumer draining in batches of 8 per on_readable until EAGAIN. The consumer is not under-draining; libevent just isn't dispatched often enough between the network event ticks, and a 256-slot ring fills in the gap. Convert OPENIPC_FT_DEPTH from a compile-time #define to a ring_depth module_param (default 256, range 16..65536, rounded up to next power-of-2 at init for the head/tail wrap mask). Per-channel rings now kmalloc'd in __init; freed in __exit. Operators wanting per-frame consumers under load can: insmod open_openipc_frame_ts.ko ring_depth=4096 (16× default, ~8 s buffer at 240 fps × 2 types; 128 KiB/chn × 8 chn = 1 MiB worst case). Default 256 keeps the memory footprint identical for existing builds. The fix is non-disruptive: at default params the binary behaviour is identical to before (same depth, same wrap math, same drop semantics). Only the storage moved from BSS to heap. xref: #155 (chrdev introduction), #199 (cv500 / V4 / V4A MIPI_FS push moved to ISP_INT_FE_FSTART — non-disruptive event source that yields the high push rate driving the drops on cv500).
widgetii
added a commit
that referenced
this pull request
May 28, 2026
Per-channel ring depth was hard-coded to 256 events, sized for the SR-anchor consumer in #155 which reads cached state every ~5 s and tolerates stale entries. For consumers that want every frame's (pts_us, wall_ns) — frame-by-frame latency histograms, evidence chains, multi-sensor sync correlators — 256 is too small when the reader's dispatch latency is bursty. Empirically on cv500 / hi3516av300_lite (#200 Obs 3): under RTSP+RTCP load through libevent, ~52 dropped/s accumulate over 30 s sessions with the consumer draining in batches of 8 per on_readable until EAGAIN. The consumer is not under-draining; libevent just isn't dispatched often enough between the network event ticks, and a 256-slot ring fills in the gap. Convert OPENIPC_FT_DEPTH from a compile-time #define to a ring_depth module_param (default 256, range 16..65536, rounded up to next power-of-2 at init for the head/tail wrap mask). Per-channel rings now kmalloc'd in __init; freed in __exit. Operators wanting per-frame consumers under load can: insmod open_openipc_frame_ts.ko ring_depth=4096 (16× default, ~8 s buffer at 240 fps × 2 types; 128 KiB/chn × 8 chn = 1 MiB worst case). Default 256 keeps the memory footprint identical for existing builds. The fix is non-disruptive: at default params the binary behaviour is identical to before (same depth, same wrap math, same drop semantics). Only the storage moved from BSS to heap. xref: #155 (chrdev introduction), #199 (cv500 / V4 / V4A MIPI_FS push moved to ISP_INT_FE_FSTART — non-disruptive event source that yields the high push rate driving the drops on cv500). Co-authored-by: Vasiliy Yakovlev <vixand@openipc.org>
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
The original openipc_frame_ts MIPI_FS source from #155 unmasked the MIPI controller's vsync IRQ and W1C-cleared the bit inside the ISR top half. That hook is disruptive under sustained load:
hi3516ev200/gk7205v200) — frames tore, VENC channel timeouts. mipi_rx: skip the openipc_frame_ts vsync IRQ block on V4 #195 worked around by gating the hook off, leaving V4 without any MIPI_FS event source.hi3516av300_lite+ Sony IMX415 4K30fps production board) — persistent magenta colour cast + intermittentTimeout from venc channel 0. The same hazard pattern that bit V4; cv500's per-arch copy of Add openipc_frame_ts: sensor frame-start (PTS, CLOCK_REALTIME) chrdev #155's block carried it too.Move the MIPI_FS push to the ISP front-end FSTART status bit instead, mirroring the existing FEND push added in #178. The ISP FE IRQ already fires twice per frame (FSTART entry + FEND entry, both bits W1C-cleared by the existing end-of-ISR ack). No MIPI controller mask changes, no W1C in atomic context.
kernel/mipi_rx/hi3516cv500/mipi_rx_hal.ckernel/mipi_rx/hi3516cv500/mipi_rx_hal.hkernel/isp/arch/hi3516cv500/mkp/src/isp.cisp_raw_int & ISP_INT_FE_FSTARTnext to existing FEND pushkernel/isp/mkp/src/isp.cu32IspRawIntStatus & ISP_INT_FE_FSTARTnext to existing FEND push (V4 path)cv200 (V2A) keeps its existing tasklet-deferred MIPI_FS push from #186 — cv200 hardware doesn't expose an
ISP_INT_FE_FENDIRQ source, but theVI_PT0_INT_FSTARTtasklet hook has always been non-disruptive on V2/V2A.Verified on hardware
Three lab boards, master + opensdk @ this branch overlaid via the firmware
HISILICON_OPENSDK_OVERRIDE_SRCDIRbuild path:hi3516av300_litegk7205v300_litehi3518ev200_lite_switcam-hs303Per-channel ratios on cv500/V4 are within scene-correct range (no magenta cast); pre-fix cv500 was ~R/G=1.4 B/G=3.0.
Refs
🤖 Generated with Claude Code