Exclusive: why Wi-Fi collapses after you enable CSI (firmware ATF and the 40 MHz client trap)
2026-10-11 · 3 min read
This is the hardest problem we hit after putting CSI into a real home network, and we have not found it documented anywhere else:
On the same router, once CSI was enabled, one Mac's downlink dropped from 300–400 Mbps to 6–10 Mbps, while its uplink stayed at ~45 Mbps.
Below is the full isolation process, the two root causes, and the two fixes. Every number is a reproducible first-party measurement (grade E) — raw data, the A/B method and the scripts are published [2] [3]; the driver involved is the upstream open-source mt76 [1].
1. Narrow it to "wireless downlink"
Four control experiments ruled out everything else:
| Hypothesis | Experiment | Result |
|---|---|---|
| WAN / ISP problem | download a domestic mirror from the router itself | 264–300 Mbps (391 Mbps with 4 threads) — normal |
| Wired problem | check WAN link negotiation | 1000 Mbps full duplex, zero error counters |
| CSI capture overhead | disable CSI (CSI enable: 0) and retest |
still collapses → not caused by CSI capture |
| Client TX capability | Mac uplink over SSH | 188 Mbps, AP-side rx rate 600 Mbps 3SS — normal |
Conclusion: only the AP→client (downlink) direction collapses, pinned to VHT-MCS0 1SS (13.5 Mbps PHY).
2. The key clue: it collapses when idle, and does not recover
Watching the client's live rate from the router side:
iw dev <iface> station dump | grep -E "tx bitrate|rx bitrate|signal"
What we saw:
- about 1 second after going idle, the AP's transmit rate for that client drops to MCS0;
- under continuous traffic it sometimes climbs back to MCS9 (~400 Mbps) — and sometimes never recovers;
- ping between client and AP: 0% loss, but RTT jitter up to 243 ms (a power-save / buffering signature).
In the "stuck" state, even a continuous 36-second saturated download stayed at 7–10 Mbps.
3. Root cause #1: firmware VoW ATF pins the rate
mt76 exposes a firmware feature switch in debugfs:
cat /sys/kernel/debug/ieee80211/phy*/mt76/vow_atf # default = 1
A/B test (same client, same time window, only this switch changed; each run is "60 s idle, then 6 consecutive downloads"):
vow_atf |
Results over 6 runs (Mbps) | Behaviour |
|---|---|---|
| 1 (firmware default) | 9.5 / 7.3 / 9.5 / 7.4 / 9.6 / 7.2 | 36 s of continuous download never recovers |
| 0 (disabled) | 7.8 / 8.8 / 20 / 146 / 387 / 393 | climbs back to full speed within ~15–20 s |
| 0 + client re-association | 369 / 374 / 376 / 390 / 409 / 397 | full speed immediately, 6/6 |
Fix (made persistent): disable vow_atf and replay the setting at boot and every minute in the watchdog, so it
survives driver reloads and reboots:
echo 0 > /sys/kernel/debug/ieee80211/phy*/mt76/vow_atf
4. Root cause #2: a 40 MHz client inside an 80 MHz BSS
With ATF fixed, a periodic collapse remained. Further A/B testing showed:
| Client | Width | Stability |
|---|---|---|
| older Mac (Broadcom, VHT 3SS) | 40 MHz | collapses repeatedly |
| phone (HE 2SS) | 80 MHz | stable at 1200 Mbps |
| other devices (VHT 1SS) | 80 MHz | stable |
Switching the 5 GHz radio from 80 MHz to 40 MHz (htmode=HE40):
| Setting | 60 s idle, then 6 consecutive downloads |
|---|---|
| HE80 (80 MHz) | 7.4 / 7.3 / 9.3 / 9.5 / 9.6 / 9.6 Mbps (all collapsed) |
| HE40 (40 MHz) | 384 / 375 / 328 / 416 / 411 / 419 Mbps (6/6 stable) |
Conclusion: a client that only negotiates 40 MHz is dragged down by rate adaptation / PPDU handling when it sits in an 80 MHz BSS. Set the radio to the client's native width and the problem disappears.
5. Choosing between the two fixes
| Goal | Setting | Cost |
|---|---|---|
| keep high-resolution CSI (80 MHz / 256 subcarriers) | stay on HE80 |
the 40 MHz client is slow |
| keep daily usability (client at full speed) | switch to HE40 |
CSI bandwidth and subcarrier count halve |
A ~30-second switch script lets you move between them on demand:
sh /usr/bin/wifi-htmode HE80 # CSI experiment mode
sh /usr/bin/wifi-htmode HE40 # daily mode
6. A decision flow you can reuse
Wi-Fi got slow
├─ only downlink slow, uplink fine? ──▶ check the AP-side tx bitrate for MCS0
│ ├─ collapses when idle, never recovers ──▶ disable vow_atf (and persist it)
│ └─ still collapses periodically ───────▶ compare client width vs BSS width
├─ both directions slow ──▶ look at interference / channel / negotiation (not covered here)
└─ wired is slow too ─────▶ check WAN negotiation and ISP (WAN stayed 1000 Mbps in our case)
If your router is also MT7986/MT7915 class (OpenWrt + mt76), run the two tables above first — five minutes tells you which of the two cases you are in.
Related: 80 MHz vs 40 MHz · mt76 rate control deep dive · OpenWrt Wi-Fi slow after idle · router CSI guide
References and data sources
Every external claim carries a source and an evidence grade (grading scheme). Grade E marks first-party, reproducible measurements from this project.
- Grade C · official docs
openwrt/mt76 — mac80211 driver for MediaTek Wi-Fi chipsets
OpenWrt project / MediaTek
github.com/openwrt/mt76 · verified: GitHub API 2026-10-11 (stars 890, last push 2026-10-08) · Upstream of the open-source mt76 driver used here; the CSI patch is applied on top of this codebase. - Grade E · first-party measurement
This project's 10-minute raw capture (57,293 records / 600.0 s, SHA-256 00373f83…95e2)
Router CSI Lab · 2026
csi.okwujun.pw/zh/datasets/ · verified: Reassembled chunks verified byte-identical (2026-10-11) - Grade E · first-party measurement
Router CSI Toolkit — capture/analysis/watchdog scripts (MIT)
Router CSI Lab · 2026
csi.okwujun.pw/zh/tools/ · verified: Repository bundle has a SHA-256; scripts run on real hardware