Setup
- Jetson AGX Orin, L4T R36.4.7, RT kernel
5.15.148-rt-tegra(CONFIG_PREEMPT_RT=y) - ZED Link Duo driver
stereolabs-zedlink-duo 1.4.3-LI-MAX96712-rt-L4T36.4.0 - One ZED X One 4K (
zedxone_uhd), ZED SDK 5.4.1, zed-ros2-wrapper 5.4.1 (zed_camera_onecomponent)
What happens
Every few hours to days, the zed_node_main process gets stuck in a kernel I2C read of the IMU temperature (/sys/class/bmi_spsc/spsc_bmi0/accel_temperature). It doesn’t recover. CPU 0 stays busy in that thread, and the kernel reports a new rcu_preempt self-detected stall on CPU every 63 s for 1 to 4 hours, until the Jetson hard-resets with no panic message.
On this module every interrupt is handled by CPU 0: the I350 PCIe Ethernet, Wi-Fi, NVMe, the USB host controller and the I2C controller. So the whole system degrades during the stall:
- the Ethernet and Wi-Fi links stop answering;
- USB devices disconnect;
- the last minutes of the logs never reach the disk.
Since we installed ZED Link 1.4.3 on 2026-09-08, kern.log has collected about 5,700 such stall reports. Every one has this stack:
rcu: INFO: rcu_preempt self-detected stall on CPU
rcu: 0-....: (1 GPs behind) idle=30f/1/0x4000000000000002 softirq=0/0 fqs=2120
Task dump for CPU 0:
task:zed_node_main state:R running task stack: 0 pid: 9707 ppid: 4620 flags:0x0000000c
...
el1h_64_irq+0x7c/0x80
rt_spin_unlock+0x44/0xb0
rpm_resume+0x9c/0x730
__pm_runtime_resume+0x44/0xb0
tegra_i2c_xfer+0x54/0x880
__i2c_transfer+0x1dc/0x860
i2c_smbus_xfer_emulated+0x114/0x700
__i2c_smbus_xfer+0x134/0x580
pca954x_select_chan+0x88/0xe0
__i2c_mux_master_xfer+0x4c/0xb0
__i2c_transfer+0x1dc/0x860
i2c_transfer+0xa0/0x130
bmi_i2c_rd+0x90/0xf8 [bmi088]
bmi_temp+0x70/0xf8 [bmi088]
accel_temperature_show+0x68/0x100 [bmi_spsc]
dev_attr_show+0x44/0xa0
sysfs_kf_seq_show+0x94/0x160
...
ksys_read+0x7c/0x110
The I2C bus is 3180000.i2c, behind the pca9546 mux, on the channel holding sl_max96712, zedxone_uhd and bmi088.
What we think is going on
These are our own conclusions; we haven’t confirmed them in the driver source.
- The reading thread is real-time.
zed_node_maincontains twoSCHED_FIFOthreads, at priorities 99 and 50, both pinned to CPU 0. The wrapper didn’t create them: itsadvanced.thread_sched_policyis the defaultSCHED_BATCHand it logs “Change thread priority: FALSE”. We assumelibsl_zed.socreates them; it does callpthread_setschedparamandpthread_setaffinity_np. - The wake-up becomes a busy-wait.
tegra_i2c_xfercallspm_runtime_resumeon an irq-safe device. If the controller is in the middle of autosuspending,rpm_resumebusy-waits (thert_spin_unlock/cpu_relaxloop seen in the trace) for the suspend to finish. - On PREEMPT_RT the suspend can’t finish. The suspend runs in a preemptible context. With a priority-99 thread spinning on the same CPU, it never gets to run, so the read never returns: a livelock.
- It’s rare and random because the temperature read has to land exactly in an autosuspend window. The IMU daemon’s 200 Hz traffic on the same bus makes those windows frequent.
What we did
- We stopped the wrapper’s 1 Hz temperature polling when
publish_tempis off. That made the stalls rarer, but they still happen, because something inside the SDK still reads the temperature. - Workaround: keep the I2C controller out of runtime suspend:
It’s been applied and we’re watching for new stalls.echo on | sudo tee /sys/bus/platform/devices/3180000.i2c/power/control
Questions
- Does the SDK read the IMU temperature, through
accel_temperature, from its priority-99 thread pinned to CPU 0? Can that priority or CPU pinning be configured? - Could the ZED Link driver avoid runtime autosuspend of this I2C controller on RT kernels, or read the temperature in a way that can’t spin?
- Is this known, and is a fix planned?
We can provide full logs if useful.