Skip to content

cv500/hi3516av300 frame-ts chrdev: zero MIPI_RX IRQs, zero coalesced events, ring drops under reader load #200

Description

@widgetii

Surfaced while verifying #155 from the majestic side (widgetii/majestic#83 / widgetii/majestic#86). The SR-anchor functionality of #155 works on cv500 — drift signature matches the hi3516ev300 reference. But the chrdev counters and /proc/interrupts numbers on this board don't match what #155's design assumed.

Setup

  • Board: openipc-hi3516av300.dlab.torturelabs.com (cv500 family)
  • Sensor: imx415 over MIPI, 20 fps, h264
  • Kernel: 4.9.37 #1 SMP Wed May 27 23:56:21 UTC 2026 armv7l
  • Modules loaded: open_openipc_frame_ts (from Add openipc_frame_ts: sensor frame-start (PTS, CLOCK_REALTIME) chrdev #155 merged), open_isp, full HiSilicon MPP stack
  • chrdev: /dev/openipc-frame-ts minor=58, event types=2 (MIPI_FS + ISP_FEND mask supported)
  • majestic: master+f5207b6, with the openipc_frame_ts_consumer.c from widgetii/majestic#87 (v2 ABI). Consumer fd persistently open, "SR will anchor to sensor frame-start..." marker prints.

Observation 1 — /proc/interrupts MIPI_RX stays at 0 since boot

 43:          0          0     GIC-0  89 Level     MIPI_RX
 45:      81374          0     GIC-0  88 Level     VI_CAP0
 46:      40681          0     GIC-0  76 Level     VI_PROC0

Sampled 30 s apart with S95majestic running and a live RTSP session: MIPI_RX delta = 0; VI_CAP0 increments ~40 Hz (~2× framerate); VI_PROC0 ~20 Hz (= framerate). Yet the chrdev consumer is clearly receiving MIPI_FS events — dropped accumulates under load (see Observation 3), meaning the kernel is calling openipc_frame_ts_push(.., OPENIPC_FT_EVT_MIPI_FS) from somewhere.

Contrast with the same board's reading in #177:

MIPI_RX    IRQ 43: 64371   ← per-frame (matches sensor rate)

Either the cv500 MIPI_RX hook moved off IRQ 43 between then and the current build, or the per-SoC FS push is now sourced from a different IRQ path (VI_CAP0 candidate, ~2× framerate would explain the high push rate that drives Observation 3). Worth nailing down which IRQ the cv500 build is actually using for OPENIPC_FT_EVT_MIPI_FS.

Observation 2 — OPENIPC_FT_IOC_GET_COALESCED stays at 0

The cv500 dedupe rationale in #155 cites ~4% of frames double-firing the MIPI vsync IRQ at ~30-80 µs intervals, absorbed by the 1 ms per-channel dedupe window. Over a full verification run (multiple RTSP sessions, two 30 s correlator passes, ~30 min uptime), GET_COALESCED returned 0.

If Observation 1's hypothesis is correct (FS events sourced from VI_CAP0 not MIPI_RX on this build), the doubles described in #155 may be specific to the MIPI_RX path and simply don't manifest from the alternative source. Functionally fine — fewer doubles to dedupe means no harm — but the design assumption "cv500 needs ~4% dedupe" doesn't hold on this build, which is worth knowing for sizing decisions.

(Sanity: GET_COALESCED ioctl itself returns success; the counter is just 0. So it's not an ioctl wiring bug.)

Observation 3 — GET_DROPPED accumulates under reader load

Counter readings:

  • Idle (no RTSP clients, majestic libevent base running): 0 drops/s over a 30 s window — chrdev drains cleanly.
  • During the active correlator runs (two 30 s RTSP sessions back-to-back): dropped went from 3758 → 7403 = +3645 drops over ~70 s of busy event loop, i.e. ~52 drops/s.

The consumer's on_readable drains in batches of 8 per dispatch (for (;;) read(fd, buf[8], ...) until EAGAIN). It's not under-draining; it's not dispatched often enough. Under RTSP+RTP+RTCP traffic the libevent base spends more time per dispatch and the kernel ring (which appears small) overflows in between.

For #83's SR-anchor use case this is non-impacting — the consumer cache only holds the latest event per channel and is read every ~5 s at SR-tick time. With the 100 ms max_age staleness gate, drops at this rate still leave a fresh enough cache. The empirical SR drift was +73 ms median, +68 to +88 ms range — no fallback to clock_gettime() observed, which would have shown up as drift jumps to the unanchored (~−60 ms) regime.

But for any future consumer that wants every frame's (pts_us, wall_ns) — per-frame evidence chains, frame-by-frame latency histograms, multi-sensor sync correlators — the ring size as currently configured won't suffice on cv500 under load. Worth sizing the ring (or making it sizable via module param) before such consumers ship.

Reproduction

# On the cv500 board:
lsmod | grep open_openipc_frame_ts                  # module present
ls -la /dev/openipc-frame-ts                         # chrdev present
cat /proc/interrupts | grep -E "MIPI_RX|VI_CAP0|VI_PROC0"

# Cross-compile tiny ioctl helper (host side, arm-himix200-linux-gcc -static):
#   ioctl(fd, _IOR('o',2,u64), &dropped)
#   ioctl(fd, _IOR('o',4,u64), &coalesced)
# Push, run before/after a busy majestic RTSP session.

# Hold an RTSP session ~30s with majestic streaming, then snapshot counters.

Suggested follow-ups (no fix proposed here, just framing)

  1. Confirm which IRQ source cv500 currently routes OPENIPC_FT_EVT_MIPI_FS through (instrument openipc_frame_ts_push at module load to log the IRQ it's hooked off of, or just grep the per-SoC hook code).
  2. If FS is now sourced from VI_CAP0 (~2× framerate), is one of those two pushes the actual sensor-FS-equivalent and the other something else (line-start? half-frame? skip?) that should be filtered before push? If so, the high apparent push rate driving Observation 3's drops would resolve.
  3. Ring size on the chrdev: currently sufficient for the SR-anchor consumer pattern; document a module_param knob or auto-size based on the push rate observed at init.

The merged #155 + widgetii/majestic#83 chain is working as designed for the SR-anchor use case on cv500 — this issue is to track the divergence between the design assumptions and what the running cv500 build actually does, so future consumers and other SoC families can be sized correctly.

xref: #155 (chrdev introduction + dedupe), #177 (FEND IRQ routing on the same family), widgetii/majestic#83 (SR-anchor consumer), widgetii/majestic#86 (cv500 verification — closed).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions