v3.8.0 — cpcd native TCP bus + soft-lockup post-mortem that names the culprit
v3.8.0 — cpcd native TCP bus + soft-lockup post-mortem that names the culprit
No EFR32 firmware change — the .gbl artefacts are identical to v3.7.0.
This release improves the RCP host stack, hardens the kernel, and turns the
watchdog panic post-mortem into a real diagnostic for issue #99.
RCP host stack — cpcd native TCP bus (drops the socat PTY shim)
cpcd now speaks bus_type: TCP and dials the gateway's in-kernel
UART↔TCP bridge (TCP:8888) directly, owning its own reconnection. The old
path put a socat in front of cpcd to fake a PTY; on any TCP blip that
PTY went stale and cpcd + zigbeed restarted in cascade. Now a bridge
drop loses only the host-side TCP (not the EFR32), and CPC's reliability
layer (sequence numbers + ACK + RTO retransmit) resumes the session with
sequence continuity — no secondary reset, no daemon restart. Validated
against a live EFR32MG1B RCP including a mid-session bridge disarm/re-arm.
- Docker stack (
ghcr.io/jnilo1/cpcd-zigbeed) is wired for it:bus_type: TCP, no moresocat-cpcprogram. The nativercp-stack(systemd
--user) flow is migrated too. Fall back withbus_type: UART+
uart_device_fileif you need the classic socat-PTY path.
Docker — socat-zigbeed serves one Z2M client at a time (#112)
socat tcp-listen:9999,…,fork forked a handler per connection, so two
overlapping Z2M sessions (e.g. a Z2M restart racing the old session) both
relayed onto the same zigbeed PTY and interleaved bytes, corrupting EZSP
and rebooting zigbeed. The fork is dropped (max-children=1) so a single
client owns the PTY at a time.
Kernel — Ethernet driver rtl8196e-eth 2.5 → 2.6
Correctness hardening at no throughput cost (TCP RX 93.9 / TX 71.5 Mbit/s,
zero interface errors across the iperf3 suite):
- RX poll indexes the shadow skb by the hardware mbuf index (guarded by
mbuf_index < rx_cnt), so a switch that links a pkthdr to a mbuf at a
different ring index under saturation can't hand the stack the wrong skb. rtl8196e_ptr_in_pool()range/alignment-checks descriptor pointers read
back from the rings; a corrupt TX descriptor returns-EIOinstead of a
wild dereference. 24 ring-anomaly stats viaethtool -S eth0(zero in
nominal flow).mm/c-lexraD-cache range-flush is bounded to the rounded 16-byte-line
range — no more 128-byte blast radius spilling onto adjacent buffers on
this non-coherent platform.
Kernel — Watchdog rtl819x_wdt 1.1 → 1.2: the panic post-mortem now names the soft-lockup culprit
The v3.7.0 post-mortem recorded only the running timer callback, but an
issue-#99 soft-lockup storm sits between timer callbacks where
running_timer is already NULL — so it read running=0x0 and could not
name the culprit (confirmed by the first field captures of #99 on v3.7.0
units). The record (format v2) now also captures, all in the panic path
and resolved to symbols only on the next boot:
previous boot ended in panic: uptime=<s> pc=<fn> ra=<fn> running=<fn> \
softirq=0x<mask>[NAMES] timers=[...] hrtimers=[...] reason="<msg>"
pc+ra— the program counter and return address of the stuck
context (get_irq_regs()), which the watchdog hrtimer interrupted. Names
the stuck frame even on a console-less gateway.softirq—local_softirq_pending()decoded to vector names (e.g.
softirq=0x102[TIMER|HRTIMER]): which softirq is storming.timers/hrtimers— up to 6 candidate callbacks queued near
expiry on the panicking CPU; the self-rearming culprit is among them, the
one recurring across captures. These walks run only in the panic path
(cold) — no normal-operation cost.
It surfaces on the next boot in dmesg and is persisted to
/userdata/panic/history (first occurrence only; re-arm with
rm /userdata/panic/history).
Tooling
flash_efr32.sh— fixed a false-negativeradio.conf-write abort on
RCP/NCP/Router flashes (emptyMODE=); genuine SSH failures still
surface.cpcd.conf— dropped the unrecognizedsocket_folderkey (cpcd v4.5.3
ignores it; the/dev/shmdefault already yields the right path).
Upgrading
- Gateway (Zigbee/Thread): the only on-device change vs v3.7.0 is the
kernel (Ethernet 2.6 + watchdog 1.2) — reflash thekernel
partition. Userdata/rootfs are unchanged. See35-Migration/. - RCP / multi-PAN Docker users: pull the refreshed
ghcr.io/jnilo1/cpcd-zigbeed:latest(or pin:3.8.0).