# MT7921/WiFi 6E USB adapter working on BalenaOS with PREEMPT\_RT kernel (5.10.x)

**URL:** <https://forums.balena.io/t/mt7921-wifi-6e-usb-adapter-working-on-balenaos-with-preempt-rt-kernel-5-10-x/375606>\
**Category:** Show and Tell\
**Created:** [February 25, 2026, 8:15am UTC](https://forums.balena.io/t/mt7921-wifi-6e-usb-adapter-working-on-balenaos-with-preempt-rt-kernel-5-10-x/375606 "2026-02-25T08:15:36Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Spunky](https://avatars.discourse-cdn.com/v4/letter/s/b38774/32.png) [@Spunky](https://forums.balena.io/u/Spunky)\
**Post date:** [February 25, 2026, 8:15am UTC](https://forums.balena.io/t/mt7921-wifi-6e-usb-adapter-working-on-balenaos-with-preempt-rt-kernel-5-10-x/375606/1 "2026-02-25T08:15:36Z")

</div>

## 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:

1. **The mt7921u driver was only merged into Linux 5.12** — it simply doesn’t exist in the 5.10 kernel that BalenaOS ships.
2. **The mt76 driver has a PREEMPT\_RT bug** — even on newer kernels that include the driver, it crashes with `BUG: scheduling while atomic` on any RT kernel. This is a known issue in the mt76 worker thread (`__mt76_worker_fn` in `util.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](https://github.com/openwrt/mt76) 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-safe `usleep_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 atomic` errors

## 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.path` in `/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**](https://github.com/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.
