Skip to content

A9000 on the Pi 5

Software on the Pi

As installed on 2026-10-13, after apt full-upgrade.

Item Version
OS Raspberry Pi OS Lite 64-bit, Debian 13 (trixie)
Kernel 6.18.50+rpt-rpi-2712 (linux-image-rpi-2712 1:6.18.50-1+rpt1)
firmware-mediatek 1:20260519-1~bpo13+1+rpt1
raspi-firmware 1:1.20260915-1 (read on 2026-10-24, held since 2026-10-13)
MT7925 firmware files WIFI_RAM_CODE_MT7925_1_1.bin, WIFI_MT7925_PATCH_MCU_1_1_hdr.bin, BT_RAM_CODE_MT7925_1_1_hdr.bin

Driver and firmware

From dmesg with stick A on a USB 3 port (bus 2, SuperSpeed 5000M):

mt7925u 2-1:1.0: HW/SW Version: 0x8a108a10, Build Time: 20260414153001a
mt7925u 2-1:1.0: WM Firmware Version: ____000000, Build Time: 20260414153105

Both sticks in the Pi

Each A9000 on its own blue USB 3 port, both at 5000M: capA (stick A) on bus 4 (usb=4-1, xhci-hcd.1), capB (stick B) on bus 2 (usb=2-1, xhci-hcd.0). linkside-radio up: all checks ok=1, separate-controllers with xhci-hcd.1,xhci-hcd.0. Idle: throttled=0x0, no over-current in dmesg, 42 °C with the fan off (the Active Cooler starts at 50 °C).

Channels in NL

iw phy phy0 channels with cfg80211.ieee80211_regdom=NL: disabled are only 2484 MHz [14], 5885 MHz [177] and 6 GHz from 6435 MHz [97] up. Open are 6 GHz 1–93 (5955–6415 MHz) and 5 GHz up to and including 173: 169 and 173 are the SRD band (5725–5875 MHz) in the regdb. The default channel list of linkside-radio stops at 165.

Monitor reception

Stick A on 6 GHz channel 37 at 160 MHz (tune capA 6135 160, center1 6185), next to a U7 Pro Max on the same channel, 5 s of beacons with linkside-cap -f 'type mgt subtype beacon': about 47 beacons per BSSID at −43/−44 dBm, kernel_filter=yes, drop=0, utrunc=0. Monitor reception works on kernel 6.18.50; the RX regression of 6.17/6.18 does not show.

rfkill

A newly plugged-in A9000 comes up soft-blocked: ip link set capA up gives RTNETLINK answers: Operation not possible due to RF-kill. NetworkManager's state file has WirelessEnabled=false; at boot it sets the kernel's global Wi-Fi rfkill state to blocked, and a new rfkill device takes that state. From the NetworkManager journal:

manager: rfkill: Wi-Fi enabled by radio killswitch; disabled by state file
rfkill0: found Wi-Fi radio killswitch (at …/xhci-hcd.0/usb2/2-1/2-1:1.0/ieee80211/phy0/rfkill0) (driver mt7925u)
manager: rfkill: Wi-Fi now disabled by radio killswitch

linkside-radio up lifts the block per radio (rfkill unblock <index>), so the global state stays blocked for any other Wi-Fi device. rfkill unblock wifi lifts the global state too, until the next boot.

Pinned on 2026-10-13, after the EHT check passed on this combination: apt-mark hold linux-image-rpi-2712 raspi-firmware firmware-mediatek. The headers are not installed yet; they get the same hold when the ath9k modules are built.

Warm reboots, 2026-10-23

Thirty sudo reboots of the Pi 5 in a row (a temporary sudoers rule for /usr/sbin/reboot), driven from the Mac over SSH on eth0, both sticks on their USB 3 ports, the software above. After each reboot the Mac waited for a new boot ID (/proc/sys/kernel/random/boot_id, polled every 5 s), then read lsusb -t, dmesg for unable to enumerate, error -32, -71 or -110 and device not accepting address, and vcgencmd get_throttled.

  • 30 of 30: both sticks back on SuperSpeed (mt7925u, 5000M), no enumeration error, throttled=0x0. SSH answered 25 to 32 s after the reboot (mean 27.8 s). The warm reboot bug of the WLAN Pi report, on a CM4, did not show.
  • Whether the Pi 5 keeps the USB ports powered through a reboot, this test does not show: a reboot that switches them off is a cold start for the sticks.
  • After a reboot the sticks come up as wlan0 and wlan1, down, until linkside-radio up.
  • sudo linkside-radio usb-reset after the thirtieth: hubs 2 and 4 off and on in 6 s, both sticks back on SuperSpeed as capA and capB in monitor, every check ok=1, the SSH session over eth0 up throughout.

USB current, 2026-10-23

The 27 W supply, recognized as 5 A (usb_max_current_enable=1: 1.6 A for the USB ports). The KW-1850 between a blue port and one stick at a time, the other stick out, read by eye to 0.01 A, 5.15 V at the meter. Through the meter both sticks came up at 480M on the USB 2 root hub: the meter passes only the USB 2 data lines, so the table is the current on USB 2. The load: the Mac on the AP's channel 48 at 80 MHz running fast.com again and again, the stick on 5240/80 with linkside-cap -f 'type data'.

State Stick A Stick B
Idle, 2412/20 0.10 A 0.10 A
Idle, 6135/160 0.15 A 0.15 A
Sweep, nine channels on 2.4, 5 and 6 GHz at 20 MHz, 150 ms dwell peaks 0.35 A about 0.20 A, peaks 0.45 A
Capture on 5240/80 under load, up to about 12,000 data frames/s about 0.16 A 0.15 to 0.17 A
  • The retunes cost the current: the sweep peaks at two to three times idle, while a busy channel adds little over idle at the same width.
  • Both sticks without the meter on USB 3 (5000M, separate controllers): two minutes both capturing 5240/80 under the same load (1.49 and 1.62 million data frames, drop=0), then a minute both sweeping (108 hops each, failed=0). throttled=0x0 in all 88 readings every 2 s, EXT5V_V 5.06 to 5.12 V, no over-current in dmesg, 44 °C.
  • On USB 2 the two sticks together peak at 0.8 A, half the 1.6 A. Their current on USB 3, with the SuperSpeed link up, this meter cannot show; nothing on USB 3 pointed at the limit.

2.4 GHz on USB 3 and USB 2, 2026-10-23

Stick A alone in the Pi, first on its USB 3 port (xhci-hcd.1, 5000M), then on the USB 2 port of the same controller (480M); 20 s of beacons on ch 1, 6 and 11 each, the Mac on 5 GHz with awdl0 down and Bluetooth off. 100 TU is 9.8 beacons a second.

Channel AP USB 3: beacons/s, median RSSI USB 2
1 AP45 9.8, −47 dBm 9.7, −46 dBm
1 a neighbor 0.5, −75 dBm 4.0, −80 dBm
6 AP A, AP B 9.8 and 9.6, −37 and −51 dBm 9.7 and 9.4, −35 and −55 dBm
11 three neighbors 7.9, 8.4 and 3.3; −61, −66 and −76 dBm 8.8, 9.4 and 3.6; −64, −64 and −80 dBm
1, 6, 11 BSSIDs heard 3, 4, 3 8, 5, 10
the weakest beacon heard −76 dBm −85 dBm

On USB 3 the stick loses about 9 dB at 2.4 GHz: the strong APs read the same within a few dB (another port, another spot), the neighbors below about −76 dBm drop out. On a 2.4 GHz focus the sensor on USB 3 sees the channel emptier than it is.

Frames 260 MHz off the channel, 2026-10-25

Both sticks on their USB 3 ports, in the recording of 2026-10-25 15:17 (roam-u7.md): capA on AP A's 5 GHz (5240/80, center 5210), capB on AP B's (5500/80, center 5530), AP A at the desk by the sensor, the phone 1 m from it on AP A until 15:19:15. Each radio decoded frames of the BSS on the other's channel, 260 MHz from its own primary, with its own frequency in radiotap:

Transmitter On its own channel Heard by Frames off the channel Median there
AP A −45 dBm on capA capB on 5500 104: NDP Announcements, RTS, Block Acks −82 dBm
The phone, to AP A −44 dBm on capA capB on 5500 47: Block Acks, RTS, action frames −80 dBm
AP B −49 dBm on capB capA on 5240 395: Block Acks, NDP Announcements, RTS; 32 beacons at −93 dBm −83 dBm

Only frames at the legacy rates of 6 and 24 Mbit/s came through, none of the HE data, which needs far more signal than the −80 to −83 dBm they arrived at. Three transmitters, two sticks and both directions show the same 34 to 37 dB below the signal on the channel, which points at the receivers rather than at a transmitter's spurious emission; the mechanism is not known, and only this offset was measured. capB on 6 GHz ch 37 heard nothing of the two 5 GHz channels.

A radio anywhere in 5 GHz may therefore hear the legacy frames of a transmitter of about −45 dBm or stronger at the sensor, the client next to it among them. Here the copies did not count, as capA was on AP A's primary channel and capB on AP B's (txop-loss.md). Since 2026-10-25 a copy counts nowhere: the engine counts a frame of a link only from a radio listening within the channel of the BSS it names (LinkMetrics), and the live session takes the client as heard for the search after 60 s and for the Overview's "Client not seen" only so (LivePlan.hear, LinkAnalyzer.lastCounted). AP B's beacons on capA put AP B's own channel in the BSS table, from its elements. A BSS whose channel the table does not hold counts on a radio only where that radio decoded a PPDU of it above the legacy rates (below).

A BSS the table did not hold, 2026-10-25

18:38, 453 s, the app and the sensor at 996309f-dirty as session.json records them; the recording is outside the repo. AP A's 5 GHz on ch 48/80 at Auto power, AP B's on ch 100/80. The phone 1 m from the sensor at the desk by AP A with a video; capA on AP A (5240/80), capB chosen on 6 GHz ch 37 (6135/160), the Mac on the IoT SSID with awdl0 down. The discovery found the phone on ch 48 and stopped there: AP B's 5 GHz BSS was not in the BSS table. AP B's 2.4 GHz beacon was, from the discovery, and its RNR names only AP B's 6 GHz BSSs.

At 18:40:05 AP A's 5 GHz transmit power went to disabled: AP A deauthenticated every client (reason 3) and sent the phone a disassociation, and the phone went to AP B. From then to the end, 18:45:41, capA on 5240 decoded the phone's exchange with AP B 260 MHz away, every frame at a legacy rate (wlan_radio.phy 5):

Frames Count
The phone's Block Acks and RTS to AP B 746, at −80 to −84 dBm (−44 on its own channel)
AP B's Block Acks, RTS and action frames to the phone 499
CTS and ACK to the phone 599
AP B's beacons or probe responses 0

No search started in the 5.5 minutes left: the copies kept the phone heard, since a frame of a BSS whose channel the table did not hold set no limit. The replay on that build put the copies on the phone's last link, AP A's 5240, as its link without a channel: 1052 Block Acks towards the phone instead of 603, a downlink capture share of 36 % instead of 87 %, and 161 downlink TXOPs of which 122 unanswered (85 % failed) instead of 29 with none unanswered, AP B's RTS without the CTS that capA did not decode. The same replay on b2fb41c, from before the limit of a BSS's channel, gave the same numbers.

Since then a BSS whose channel the table does not hold counts on a radio, and keeps the client heard, only where that radio decoded a PPDU of it above the legacy rates, HT, VHT, HE or EHT, and from then on its legacy-rate frames there too (LinkMetrics.decodedWide, LivePlan.listensWithin). No copy is such a PPDU; a BSS within the radio's channel that the table misses sends them, as AP B did on ch 40 inside capA's 80 MHz in testlab-client-leaves-psk, where the reference client was on it. Over this recording the phone's last frame heard is 18:40:04 with the rule, which would start the search a minute later; without it the phone stayed heard to the end, with no gap above 13 s.

20:39, 326 s, the same setup with the app and the sensor at cc85b5a, the rule in (the session u7-phone-search-copies, cut one minute after the find). At 20:41:21 AP A's 5 GHz went to disabled: AP A deauthenticated every client (reason 3), the phone's four authentications to AP A went unanswered, and it deauthenticated itself (reason 3). Its last frame heard was at 20:41:23. In the minute after it capA on 5240 decoded 71 of the phone's frames to AP B and 46 of AP B's to it, RTS, Block Acks and action frames, all at legacy rates, the phone's at −83 to −94 dBm, with no gap above 10 s between the phone's; AP B's beacon reached capA only at 20:42:30, during the search. The search started at 20:42:23, 60 s after the last frame (capB to 5240, the phone's last channel, capA sweeping), and found the phone on AP B at 20:42:31; capA locked on AP B (5500/80), capB went back to 6135. The replay counts no frame of the phone from its last frame on AP A to the find, and the roaming question reads one roam, not seen by the sensor.

The survey, 2026-11-04

Both sticks in monitor mode, capA on 5180 and capB on 2437 at 20 MHz, iw dev <role> survey dump read every 5 s for 15 s. Kernel 6.18.50, WM firmware 20260414153105.

  • Every counter sits on one entry on both radios: 5955 MHz, the first 6 GHz channel, where neither listens. No channel reads in use.
  • Active time follows the clock from linkside-radio up.
  • Busy time grew by 273,279, 261,892 and 273,278 ms in those three intervals, about 54 times the time that passed: 24, 23 and 24 times 11,386.6 ms, on both radios alike, on two bands. Receive and transmit time stay 0.

11,386.6 ms is 0xADBEEF µs. A tester on linux-wireless saw the same growth on an A9000 and reads it as a MIB busy register returning 0xDEADBEEF, of which the driver keeps 24 bits. The survey of this kernel says nothing about the channel.

Upstream has both halves of a fix. 68342a7bd7e5, accepted and tested on the MT7925 over USB, moves the survey with the channel; it is not in rpi-6.18.y. An RFC of 2026-10-23 takes busy, receive and transmit time from the firmware (GET_MIB_INFO), as mt7996 does; it is not merged, its offsets are undocumented and no maintainer has answered. Its tester ran an A9000 on USB 2 in monitor mode, unassociated, on WM firmware 20260605184805, hopping 98 channels for 102 minutes:

Busy Wi-Spy DBx2, RF occupancy
Channel 1, normal air 50.8 % 69.1 %
Channel 1, a phone playing 2160p video 69.4 % 85.0 %

No reading had busy over active time or going backwards, quiet 6 GHz channels read 0.1 to 0.3 %, and there were no MCU timeouts. Receive time counts strong signals only, so busy is the one figure to use. The busy counter wraps at 32 bits, which the RFC does not handle yet.

Neither is built here; item 169 holds the work. The RFC needs its MT7927 block dropped on this kernel, as the tester did on 7.0, and the channel patch a hunk rebased in mt7921/main.c. The headers of this kernel and build-essential are on the Pi. Not known: whether busy counts energy that is not Wi-Fi, what it reads at more than 20 MHz, the Pi's older firmware, and what the firmware query costs a capture under load. There is no noise floor on any of these: mt792x_phy_get_nf returns 0.