The Problem
I needed WiFi 6E connectivity on a Revolution Pi Connect S running BalenaOS 3.0.8+rev2 (kernel 5.10.152-rt75-v8) using an EDUP AX3000M USB adapter (MediaTek MT7961, USB ID 0e8d:7961).
Two problems stood in the way:
- The mt7921u driver was only merged into Linux 5.12 — it simply doesn’t exist in the 5.10 kernel that BalenaOS ships.
- The mt76 driver has a PREEMPT_RT bug — even on newer kernels that include the driver, it crashes with
BUG: scheduling while atomicon any RT kernel. This is a known issue in the mt76 worker thread (__mt76_worker_fninutil.c).
Since BalenaOS uses a CONFIG_PREEMPT_RT kernel, both problems hit at once.
The Solution
I created a reproducible Docker-based build system that:
- Cross-compiles the mt76/mt7921u driver from the OpenWrt mt76 project for aarch64
- Applies 11 compatibility patches to backport the driver from kernel 5.18 APIs down to 5.10
- Includes a critical PREEMPT_RT fix that replaces the unsafe
set_current_state()+schedule()pattern with RT-safeusleep_range() - Handles CONFIG_MODVERSIONS CRC injection via direct ELF binary patching (needed because BalenaOS enables
CONFIG_MODVERSIONS)
The result: 5 kernel modules that load cleanly on the stock BalenaOS kernel with zero RT scheduling bugs.
What’s working
- WiFi 6E on both 2.4 GHz and 5 GHz bands
- Automatic module loading on boot via systemd service
- Firmware loading from the persistent data partition (
/mnt/data/) - NetworkManager integration (connect via
nmcli) - Zero
scheduling while atomicerrors
BalenaOS-specific challenges & solutions
BalenaOS has a read-only root filesystem, which makes persistent kernel module loading tricky. Here’s what I learned:
What didn’t work:
/mnt/state/root-overlay/etc/modprobe.d/— BalenaOS doesn’t apply root-overlay for modprobe.d/etc/udev/rules.d/on mmcblk0p5 — BalenaOS clears custom udev rules on every boot
What works:
mount -o remount,rw /+ systemd service — survives reboots, but not BalenaOS OTA updates- Kernel cmdline
firmware_class.path=in/mnt/boot/cmdline.txt— persistent, survives everything
The final setup uses:
- Modules + firmware on
/mnt/data/mt76-modules/(persistent across updates) firmware_class.pathin/mnt/boot/cmdline.txt(persistent on boot partition)- Systemd service installed via
mount -o remount,rw /(needs reinstall after OTA)
Get it
Everything is open source:
GitHub: Spunky84/mt76-rt-backport
The repo includes:
- Reproducible Dockerfile build
- All 11 patches with detailed descriptions
- Step-by-step device setup guide
- The PREEMPT_RT fix as a standalone patch (useful for any mt76 driver on any RT kernel)
Who this helps
- Anyone running BalenaOS on older kernels (5.10.x, 5.11.x) who needs MT7921/MT7961 WiFi
- Anyone running any mt76-based driver on a PREEMPT_RT kernel (the RT fix applies to mt7915, mt7603, etc. too)
- Anyone struggling with CONFIG_MODVERSIONS CRC mismatches when loading custom kernel modules on BalenaOS
Hardware tested
- Device: RevPi Connect S (BCM2711)
- OS: BalenaOS 3.0.8+rev2
- Kernel: 5.10.152-rt75-v8
- Adapter: EDUP AX3000M (MT7961)
- Status: Working
Happy to answer questions or help adapt this for other kernel versions.