Wi-Fi for MediaTek MT7921 / MT7921K (AMD RZ608) / MT7922 PCIe cards on macOS.
An experimental macOS kernel extension, based on the OpenBSD mwx(4) driver and
the itlwm-style net80211 port. It comes in two flavours with the same
hardware layer:
AirportMtkWlan.kext— the card is a real macOS Wi-Fi interface: the native Wi-Fi menu, System Settings, private Wi-Fi addresses, Keychain passwords. Built for macOS 26 Tahoe (and Sequoia 15.2+), no OCLP root patch, no IOSkywalkFamily downgrade.SimpleMtkWlan.kext— the card is an Ethernet interface (enX); networks are scanned and joined with the SimpleMTK menu-bar client. Works on any macOS version the kext loads on.
Bluetooth for the same card: SimpleMtkBtFw (firmware loader + patcher; AirPods audio works).
This fork contains the fixes needed to make MT7921 / RZ608 actually work (it was attaching but never passing traffic), plus 802.11n, 802.11ac (VHT80) and the native Wi-Fi menu on Tahoe. See What changed in this fork.
| Feature | State |
|---|---|
| Probe, firmware load, MSI interrupts | ✅ |
| Scan (2.4 GHz + 5 GHz) | ✅ |
| WPA2-PSK (CCMP) association, 4-way handshake | ✅ |
| Hardware RX decryption (software fallback for anything the chip misses) | ✅ |
| Switching between networks / bands | ✅ |
| 802.11n (HT20/HT40, MCS 0–15, SGI, RX STBC, WMM) | ✅ |
| 802.11ac (VHT20/40/80, 2×2 MCS 0–9, RX STBC) | ✅ |
| A-MPDU: RX Block Ack + TX aggregation | ✅ |
| Hardware TX A-MSDU (inside A-MPDU), VHT beamformee | ✅ |
| Auto-join at boot, 5 GHz preferred over 2.4 GHz of the same router | ✅ |
| AUTH / ASSOC retransmission (lost frames no longer cost a full rescan) | ✅ |
| Auto-recovery of a wedged chip (DMA stall watchdog, PCIe FLR at attach) | ✅ |
| Native macOS Wi-Fi menu (IO80211Family / Skywalk), Tahoe | ✅ AirportMtkWlan |
| Native Wi-Fi menu, Sequoia 15.2+ | |
| 802.11ax (HE) | ❌ not yet |
| WPA3-only (SAE) networks | ❌ |
| Sleep / wake (firmware reloaded on wake, reconnects by itself) | ✅ |
| AirDrop / Handoff / Continuity (AWDL) | ❌ |
| Card | PCI ID | macOS | Result |
|---|---|---|---|
| MediaTek MT7921K (AMD RZ608) | 14c3:0608 |
26.7.1 Tahoe, Intel desktop | AirportMtkWlan: native Wi-Fi menu, joins from Keychain, 50+ Mbit/s on 5 GHz VHT80 (weak signal, 100 Mbit/s line) |
| MediaTek MT7921K (AMD RZ608) | 14c3:0608 |
15.8.1 Sequoia, Intel desktop | SimpleMtkWlan: 30–50 Mbit/s on 5 GHz VHT80 (a MacBook in the same spot gets ~85); 2.4 GHz works; joins automatically at boot |
| MediaTek MT7922 (RZ616) | 14c3:0616 |
15.8.1 Sequoia | native Wi-Fi menu in pengubow's fork (its own HAL) |
| MediaTek MT7922 | 14c3:7922 |
Tahoe (upstream PR #5) | legacy 20 MHz on 5 GHz |
| MediaTek MT7921 | 14c3:7961 |
— | same chip family as RZ608, expected to work |
Other MediaTek devices are not supported.
Use either AirportMtkWlan.kext or SimpleMtkWlan.kext, never both:
they match the same card.
- Download
AirportMtkWlan-Tahoe-x.y.z-RELEASE.zip(or-Sequoia-for macOS 15.2+) from Releases. - Copy
AirportMtkWlan.kexttoEFI/OC/Kexts/and add it toKernel → Add(same entry as below,BundlePathAirportMtkWlan.kext,ExecutablePathContents/MacOS/AirportMtkWlan). SetMinKernel25.0.0/MaxKernel25.99.99for the Tahoe build (24.2.0/24.99.99for Sequoia): each build only fits that IO80211 version and would panic on the other. Kernel → Quirks → DisableIoMapper=true(the driver does not support AppleVTD DMA remapping yet).- Do not apply OCLP "Modern Wireless" root patches and do not block
or replace
IOSkywalkFamily/ injectIO80211FamilyLegacy: this kext uses the system's own Wi-Fi stack. Remove such leftovers from Intel/Broadcom guides. - Disable
SimpleMtkWlan.kextif present and quit / remove the SimpleMTK app. - Make sure the card is not hidden (step 4 below), reboot and pick a network in the Wi-Fi menu.
itlwm_he=1 turns on 802.11ax capabilities (experimental, off by default).
-
Download the latest
SimpleMtkWlan-x.y.z-RELEASE.zipfrom Releases (or build it yourself, see below). -
Copy
SimpleMtkWlan.kexttoEFI/OC/Kexts/. -
Add it to
config.plist → Kernel → Add:<dict> <key>Arch</key> <string>x86_64</string> <key>BundlePath</key> <string>SimpleMtkWlan.kext</string> <key>Comment</key> <string>MediaTek Wi-Fi</string> <key>Enabled</key> <true/> <key>ExecutablePath</key> <string>Contents/MacOS/SimpleMtkWlan</string> <key>MaxKernel</key> <string></string> <key>MinKernel</key> <string></string> <key>PlistPath</key> <string>Contents/Info.plist</string> </dict>
-
Make sure the card is not hidden. Many prebuilt EFIs ship an SSDT (e.g.
SSDT-Disable_Network_*.aml) that replaces the card'svendor-id/device-idwith0xFFFFso macOS ignores it. Disable it, otherwise the driver never matches.ioreg -l | grep -A40 'pci14c3'should showvendor-id = <c3140000>. -
Install SimpleMTK, reboot and join a network from the menu bar.
Optional boot-args: -novht, -noht40, -mtknoamsdu (no TX A-MSDU).
-
Read the driver log. The driver keeps a persistent ring buffer that survives a failed start and is readable without root:
./tools/mtklog.sh > mtk.txtA periodic
statsline shows RX counters, hardware vs software decryption (rx_hwdec/rx_swdec) and the reasons frames are dropped. Both kexts write the same log. -
No Wi-Fi in the menu with AirportMtkWlan. Check that only one of the two kexts is enabled, that no OCLP wireless patch /
IOSkywalkFamilyblock is active, thatDisableIoMapperis on and that the build matches your macOS (Tahoe vs Sequoia).ioreg -l -w0 | grep IO80211InterfaceRoleshould printInfrastructure. -
"SimpleMtkWlan is not running" after a reboot. A warm reboot does not power-cycle an M.2 card. The driver now recovers the chip automatically (WFSYS reset, then PCIe function-level reset); if it still fails, shut the machine down completely and power it on again.
-
Slow speed. Check
rx_swdecin the stats line: it should stay small compared torx_hwdec. Speed tests are only meaningful with the SimpleMTK menu closed (the client triggers scans; they are throttled to one per two minutes while connected). -
A 2.4 GHz wireless mouse/keyboard stutters while Wi-Fi is on 2.4 GHz. That is RF coexistence in the same band, not a driver bug: keep the card on 5 GHz (leave only the 5 GHz network in SimpleMTK) or move the dongle away from the antennas with a USB extension.
-
Slow to connect after boot. The network is chosen by the SimpleMTK app, which only starts after login; the driver scans until then.
-
Throughput below a real Mac. On weak signal the AP mostly sends VHT MCS 3–4 (see the
rxrateline). Block Ack Request frames are not delivered by the firmware, so the rare reorder gaps close by a 100 ms timeout (ba gap_timeout). -
Unrelated kernel panics (
element modified after freeat ~2 s of uptime) were caused byNVMeFix.kexton the test machine, not by this driver.
Requirements: macOS with Xcode (command line tools are not enough). The kernel headers come from acidanthera/MacKernelSDK, which is a git submodule.
git clone --recurse-submodules https://github.com/flxxxxddd/SimpleMtkWlan.git
cd SimpleMtkWlan
xcodebuild -project SimpleMtkWlan.xcodeproj -scheme SimpleMtkWlan \
-configuration Release -derivedDataPath build CODE_SIGNING_ALLOWED=NO build
# -> build/Build/Products/Release/SimpleMtkWlan.kextAlready cloned without submodules? git submodule update --init.
Do a clean build (
rm -rf build) after editing headers inmtk80211/orinclude/. They are on the system header search path, which Xcode does not track for dependencies, so stale objects would otherwise be linked.
The native Wi-Fi kext is built with a script (not part of the Xcode project):
./build-macos.sh Release AirportMtkWlan # Tahoe (default)
AIRPORT_OS=sequoia ./build-macos.sh Release AirportMtkWlan # Sequoia 15.2+
# -> build/Release/{tahoe,sequoia}/AirportMtkWlan.kextHost tests (extract real driver functions and run them against stubs with ASan/UBSan):
./tests/run-all.shCI builds Debug and Release on every push and pull request; pushing a tag
vX.Y.Z publishes a GitHub release with the zipped kexts.
| Path | Contents |
|---|---|
SimpleMtkWlan/SimpleMtkWlan.cpp |
IOEthernetController front end (SimpleMtkWlan.kext), watchdog |
AirportMtkWlan/ |
IO80211 / Skywalk front end (AirportMtkWlan.kext), from AirportItlwm (WCL) |
include/Airport/ |
IO80211Family / Skywalk headers (macOS15, macOS26 ABI sets) |
SimpleMtkWlan/MtkLog.cpp |
persistent debug log shared by both kexts |
build-macos.sh |
builds AirportMtkWlan (and SimpleMtkWlan) without Xcode project changes |
SimpleMtkWlan/MtkWlanUserClient.cpp |
IOUserClient used by the SimpleMTK app |
SimpleMtkWlan/hal_mwx/ |
MT7921/MT7922 hardware layer (port of OpenBSD mwx) |
mtk80211/ |
net80211 and BSD/Linux compatibility layer |
include/ |
HAL interfaces, embedded firmware (FwBinary.cpp), client API |
tests/ |
host tests |
tools/mtklog.sh |
dumps the driver log |
MacKernelSDK/ |
submodule with kernel headers |
On top of upstream and PR #5 (association context, TX serialization, packet ownership):
- Firmware load: firmware chunks no longer need 16 KB jumbo mbuf clusters
(they were unavailable at boot →
ENOMEM, no MAC address, no interface). - Interrupts: register the real MSI vector instead of INTx and stop setting the MSI enable bit by hand (the device stopped raising INTx and only got serviced through a shared line); drain pending status before re-enabling.
- TX DMA stall: multi-mbuf frames are linearized into one cluster; the WFDMA stalled forever on the first DHCP frame.
- Group traffic: the chip does not decrypt group-addressed frames, so
broadcast ARP/DHCP was dropped. Keys are now also set up for
net80211software CCMP as a fallback. - Network switching: send the deauth to the old AP on its channel before switching, ignore stale disassoc frames while authenticating, and remove the peer station / disable the BSS in firmware when leaving (otherwise hardware decryption stopped after the first switch).
- Roaming: RSSI-triggered background roaming is disabled (it hopped between 2.4 and 5 GHz networks of the same router every few seconds).
- Throughput: background scans while associated are throttled.
- 802.11n: HT capabilities, WMM, full peer STA record on association, RX Block Ack and TX A-MPDU sessions passed to the firmware. HT 20/40 is advertised (APs only send 80 MHz to clients that claim 40 MHz support).
- 802.11ac: VHT capabilities, STA_REC_VHT, operating width (20/40/80 MHz) taken from the association, RX STBC; per-interval RX rate histogram in the debug log.
- Joining: 5 GHz preferred when within 15 RSSI points of 2.4 GHz, stale peer records and stale scan results cleaned up, deauth before the first AUTH and on stop, AUTH/ASSOC retransmitted up to 3 times (one lost association response used to cost ~20 s).
- Robustness: DMA stall watchdog with hard reset + firmware reload, chip recovery at attach (WFSYS reset → PCIe FLR), TXWI leak fix.
- Debuggability: persistent
MtkDebugLogring buffer published on the PCI device, periodic hardware/stats dump, quiet logging on the data path. - Native Wi-Fi menu (AirportMtkWlan): laobamac's AirportItlwm Tahoe/Sequoia (WCL) front end, as adapted to the MediaTek HAL by pengubow, on top of this fork's MT7921 hardware layer. Changes for this card: Tahoe ABI build, the front end's watchdog drives the HAL housekeeping (stall recovery, AUTH/ASSOC retransmit), no manual MSI enable, shared persistent log, link rate from the measured RX rate, and short scans macOS asks for allowed while connected (full sweeps stay throttled).
- TX path: data frames go to the hardware queue of their access category (everything was on VO), no per-frame TX status events, Block Ack disabled for TIDs without an agreement, output pauses when the TX ring is full instead of dropping packets, hardware A-MSDU inside A-MPDU when the AP allows it. VHT SU/MU beamformee and HT LDPC are advertised (Linux defaults).
- Sleep / wake: the card is powered off in S3. On sleep the driver leaves the network and masks interrupts; on wake it takes the chip back (WFSYS reset / PCIe FLR if needed) and reloads the firmware. Before, the first interrupt after wake read a stale DMA ring and panicked.
- Build: builds from a clean clone (MacKernelSDK submodule, no absolute paths), host tests fixed, CI + releases.
GPLv2, see LICENSE. Some files carry additional or more specific notices inherited from upstream GPL/BSD/OpenBSD/NetBSD/FreeBSD components; those apply to their respective files. Firmware is redistributed under the MediaTek firmware license (as in linux-firmware).
- laobamac (王孝慈) — SimpleMtkWlan and SimpleMTK
- mavizao — PR #5 (MT7922 association/TX fixes, host tests)
- pengubow — AirportMtkWlan: AirportItlwm's native Wi-Fi front end on the MediaTek HAL (WCL scan/join hooks, private address, Infrastructure role fix, passphrase joins, command-gate sleep)
- laobamac/itlwm — AirportItlwm for Sequoia/Tahoe (WCL layer, macOS 15/26 IO80211 headers, TX pull model, link quality)
- OpenBSD
mwx(4)driver authors - OpenIntelWireless/itlwm (zxystd) — net80211 port, driver architecture and the original AirportItlwm
- Linux mt76 — hardware reference
- acidanthera — MacKernelSDK
Related: SimpleMtkBtFw — Bluetooth for MT7921 / RZ608 / MT7922.
See also CREDITS.md.