watchthelight labs

MT7925 (0489:E14F) fails USB enumeration after a warm restart from macOS, in macOS and Windows, until a cold power-off #11

open
xieshuanglin2 2026-11-07

Laptop model

Desktop: MSI AM5 board (MS-7E66), Ryzen 7 9800X3D, MT7925/RZ717 (BT 0489:E14F on chipset XHCI 1022:43FC port 17), dual boot Windows 11

macOS build, OpenCore version, MtkBt and BlueToolFixup versions

26.7.2 (25G332), OpenCore DBG-109 (2026-10-23), MtkBt 0.2.4, BlueToolFixup 2.7.2, LegionBtFix 0.3.0, MtkWlan 0.12.1 + MtkWlanNative 0.4.14

Output of ioreg -rc MtkBt -l | grep MtkBt

While it is wedged: `ioreg -rc MtkBt -l` is empty (the device never enumerates, so MtkBt never attaches).

From a good warm restart after Windows on the same machine (stock 0.2.4):
"MtkBtVersion" = "0.2.4"
"MtkBtState" = "ready"
"MtkBtTries" = 2
"MtkBtWarmPath" = "half-loaded, subsys reset"
"MtkBtSubsysReset" = "done"
"MtkBtLastError" = "wmt op 6 flag 0: no event"
"MtkBtSlpProt" = "was already bypassed"
"MtkBtChipId" = 31013
"MtkBtFwVersion" = 16896
"MtkBtFirmwareBuild" = "20260813113236"
"MtkBtElapsedMs" = 24428
"MtkBtLog" = "chip 7925 fw_ver 00004200 flavor 0;slpprot before download: 18100006 -> 18100006;section 0: already loaded;section 1: already loaded;section 2: 41472 bytes in 166 blocks;slpprot after activation: 18100006 -> 18100006;wmt op 6 flag 0: no event;func ctrl silent after reusing 2 loaded sections;pass 1: half-loaded, subsys reset;subsys reset done;ep 81 resync 00000000;ep 82 resync 00000000;ep 02 resync 00000000;slpprot after subsys reset: 18100006 -> 18100006;section 0: 74176 bytes in 297 blocks;section 1: 332224 bytes in 1329 blocks;section 2: 41472 bytes in 166 blocks;slpprot after activation: 18100006 -> 18100006;bluetooth function on (flag 0 status ffff);ready in 24428 ms, 0 interrupt packets dropped;"

Output of system_profiler SPBluetoothDataType (first 20 lines, remove addresses if you like)

While wedged (placeholder controller only):
Bluetooth:

      Bluetooth Controller:
          State: Off
          Chipset: BCM_4350C2
          Discoverable: Off
          Firmware Version: v0 c0
          Supported services: 0x392039 < HFP AVRCP A2DP HID Braille LEA AACP GATT SerialPort >
          Transport: UART
          Vendor ID: 0x004C (Apple)

What happened

What happens

With Bluetooth on in macOS, a warm restart (Apple menu > Restart) sometimes leaves the Bluetooth part of the card dead on the USB bus:

  • the next OS, macOS or Windows, does not see it at all
  • Windows can restart any number of times and it stays gone; macOS too
  • only a cold power-off (PSU switch off ~30 s) brings it back
  • restarting Windows -> Windows never causes it; it starts after a macOS session

In macOS the port sees a device but every enumeration fails:

HS08@01e00000: AppleUSBHostPort::cableChangeOccurred: powering on
HS08@01e00000: AppleUSBHostPort::createDevice: failed to create device (0xe00002bc)
... (8 times, ~1.5 s apart)
HS08@01e00000: AppleUSBHostPort::disconnect: persistent enumeration failures

Windows (USBToolBox port scan) shows the same port as DeviceFailedEnumeration.

Frequency here: about 1 in 3-5 warm restarts from macOS (macOS -> macOS and macOS -> Windows both hit it).

What the good restarts look like

After a warm restart that does work, MtkBt reports the firmware of the previous session still in the chip:

section 0: already loaded
section 1: already loaded
section 2: 41472 bytes in 166 blocks
bluetooth function on (flag 0 status ffff)
ready in 3159 ms

After a restart from Windows it takes the half-loaded path (func ctrl silent after reusing 2 loaded sections, pass 1: half-loaded, subsys reset, full download, ready in ~24 s). Both recover fine; the problem is only the restarts where the device never enumerates.

What I tried (local build, now removed)

  1. Diagnostics on the power off path (notes on kIOMessageSystemWillRestart, FUNC_CTRL 0 result) via an NVRAM variable and os_log. Neither survived to the next boot on this machine: NVRAM written from the kext was visible in the same boot but gone after a restart (NVRAM > WriteFlash is true), and nothing from the kext (IOLog or os_log_error) showed up in log show at all. So I could not see whether funcOff ran or what it returned. Maybe something on my side; mentioning it in case it matters for your own logging.
  2. In funcOff, after the WMT FUNC_CTRL 0, call subsysReset() (and let its RST_DONE poll run with offPath set) before endSession(), so the chip is back to its power-on state for the next OS. This did take effect: the next boots showed full sections (section 0: 74176 bytes ..., ready in ~19.4 s) instead of "already loaded", three macOS -> macOS restarts and one macOS -> Windows -> macOS were clean. But the fifth restart (macOS -> Windows, after a macOS session that had itself started from Windows and gone through the half-loaded subsys reset at boot) still ended with the device failing enumeration in both systems. So a reset at shutdown makes most restarts clean but does not prevent the wedge.

Possibly related

WTLMtkWireless #9 (Wi-Fi gone after a restart, card missing in Windows until a cold power-off) is the same pattern on the Wi-Fi side of the card. MtkWlan 0.12.1 with its restart quiesce is installed here and Wi-Fi itself has been fine.

Workaround for now

Shut down instead of restart when leaving macOS, with ErP enabled in the BIOS so the M.2 slot loses standby power, or a cold power-off after it happens.

Happy to test a build.


中文摘要

MT7925(0489:E14F)蓝牙:在 macOS 下蓝牙开着时热重启,有时蓝牙会卡死在 USB 上,下一次不管进 macOS 还是 Windows 都识别不到(failed to create device,最后 persistent enumeration failures),只有彻底断电才能恢复。Windows 之间重启不会出现。约 3 到 5 次重启出现一次。曾在本地给 MtkBt 关机流程加了 FUNC_CTRL 0 之后的子系统重置,能让多数重启变干净(下次开机固件从头完整加载),但仍然挡不住卡死。另外,从 kext 写的 NVRAM 和系统日志在这台机器上重启后都留不下来,无法记录关机过程。临时办法:离开 macOS 用关机并在 BIOS 开 ErP,或出问题后断电。愿意帮忙测试新版本。

watchthelight 2026-11-10

Thanks, this is a very complete report, and your shutdown-reset experiment saves me a step.

Where I am: I haven't seen this on my laptop (Intel, 0489:E111, MtkBt 0.2.4). Every boot since 0.2.0 came up with MtkBtTries = 1. That doesn't prove much, since my card has never taken the half-loaded path either. So I can't reproduce it yet and have no fix to offer.

What your test tells me: a subsystem reset at shutdown gives the next boot a clean chip and the wedge still happens, so leftover firmware state alone isn't the cause. A device that fails enumeration in both systems until the slot loses power has stopped answering on USB altogether, before any driver talks to it.

Two runs would narrow it down, if you have the patience for about ten restarts each:

  1. MtkBt disabled in config.plist (BlueToolFixup can stay), then warm restarts from macOS. The chip never gets firmware in those sessions. If it still wedges, the cause is how macOS leaves the USB port or the card at restart, not anything MtkBt loads.
  2. MtkBt enabled, but Bluetooth switched off in Control Centre before each restart.

Also useful: after a wedge, does a normal shutdown and power-on with the PSU left on bring it back, or only the PSU switch?

On the logging: MtkBt writes through IOLog, and at restart the log daemon has most likely stopped before those lines are written, so they wouldn't reach log show. I don't know why your NVRAM write didn't survive.

I've linked this from WTLMtkWireless #9, the same pattern on the Wi-Fi half.

watchthelight 2026-11-10

I counted my own restarts so "I haven't seen it" has a number behind it.

The system log on my laptop goes back to 31 October and holds 14 boots. Bluetooth came up on all 14. Ten of them were warm restarts from macOS with MtkBt loaded, which is the case you are hitting, and all ten were clean. The other four were a reset after a kernel panic, a restart out of the macOS installer, and two starts after Windows.

Ten clean restarts don't rule out a fault at your rate. If mine failed 1 time in 5, I'd still see ten clean ones about 11 % of the time; at 1 in 3 it would be about 2 %. So it is likely, not certain, that my 0489:E111 on an Intel laptop doesn't share the problem with your 0489:E14F on the MSI board. I'll keep counting.

How I counted, in case you want the same numbers from your side: one Darwin Kernel Version line per boot, and bluetoothd's Found external Bluetooth dongle line when the controller enumerated.

log show --last 14d --style compact --predicate '(process == "kernel" AND eventMessage BEGINSWITH "Darwin Kernel Version") OR (process == "bluetoothd" AND eventMessage CONTAINS "Found external Bluetooth dongle")'

A boot with the kernel line and no dongle line after it is a failed one. The two runs from my last comment are still the most useful thing.

Reply on GitHub