Merge branch 'code/majorair/steam-deck-wifi-flap-article'
This commit is contained in:
commit
cf5e35da1d
3 changed files with 135 additions and 0 deletions
|
|
@ -0,0 +1,133 @@
|
|||
---
|
||||
title: "Steam Deck Wi-Fi Flapping: IWD Periodic Scan + rtw88 Power Save"
|
||||
domain: troubleshooting
|
||||
category: networking
|
||||
tags: [wifi, steam-deck, steamos, iwd, networkmanager, rtw88, rtl8822ce, power-save, supplicant-disconnect, flapping]
|
||||
status: published
|
||||
created: 2026-06-19
|
||||
updated: 2026-06-19
|
||||
---
|
||||
|
||||
# Steam Deck Wi-Fi Flapping: IWD Periodic Scan + rtw88 Power Save
|
||||
|
||||
## 🛑 Problem
|
||||
|
||||
An OG Steam Deck (LCD model, Realtek **RTL8822CE** on the `rtw88_8822ce` driver) kept "losing" Wi-Fi — it would connect, hold for around a minute, drop, then reconnect a second later, over and over. From the router side the device looked like it was constantly coming and going; from the couch it felt like the network "wouldn't stay connected."
|
||||
|
||||
Crucially, **this was not a router problem.** The AP config was correct, RF was clean (strong signal, zero tx retries / beacon loss), and every other client on the network was rock-solid. The fault was entirely on the Deck.
|
||||
|
||||
## 🔍 Diagnosis
|
||||
|
||||
SteamOS uses **NetworkManager with the `iwd` backend** (not `wpa_supplicant`). That detail is the whole ballgame.
|
||||
|
||||
### Step 1 — Confirm the flap and its cadence
|
||||
|
||||
```bash
|
||||
# how many disconnects this boot?
|
||||
journalctl -b -u NetworkManager --no-pager | grep -c supplicant-disconnect
|
||||
# 50
|
||||
|
||||
# when did they happen?
|
||||
journalctl -b -u NetworkManager --no-pager | grep supplicant-disconnect \
|
||||
| awk '{print $1,$2,$3}' | tail
|
||||
# 10:20:52 · 10:21:54 · 10:22:57 · 10:24:00 · 10:25:03 · 10:26:05 · 10:27:08 ...
|
||||
```
|
||||
|
||||
**~63 seconds between every drop.** A fixed, metronome-like interval is the tell — this is a *timer*, not RF noise. The NetworkManager log shows the pattern plainly:
|
||||
|
||||
```
|
||||
activated -> failed (reason 'supplicant-disconnect')
|
||||
... -> activated # reconnects ~1s later
|
||||
```
|
||||
|
||||
### Step 2 — Prove the link is healthy *when it's up*
|
||||
|
||||
```bash
|
||||
iw dev wlan0 station dump | grep -iE 'signal|bitrate|failed|retries|beacon loss'
|
||||
# signal: -65 dBm
|
||||
# tx retries: 0
|
||||
# tx failed: 0
|
||||
# beacon loss: 0
|
||||
```
|
||||
|
||||
Strong signal, zero retries, zero beacon loss — the association is clean while it lasts. So the drop is being *commanded*, not caused by a bad radio link.
|
||||
|
||||
### Step 3 — Identify the chip and the backend
|
||||
|
||||
```bash
|
||||
lspci -k | grep -A3 -iE 'network|wireless'
|
||||
# Realtek RTL8822CE ... Kernel driver in use: rtw88_8822ce
|
||||
```
|
||||
|
||||
The `~63s` interval is **IWD's default periodic background scan**. With no `/etc/iwd/main.conf` present, IWD scans on a timer even while connected, and on the `rtw88` driver that scan knocks the current association over — producing the `supplicant-disconnect` every minute.
|
||||
|
||||
A secondary annoyance: `iw dev wlan0 get power_save` reported `on`, which showed up as wildly jittery LAN latency (8–69 ms to the gateway over Wi-Fi, where a healthy 5 GHz link is 2–10 ms).
|
||||
|
||||
## ✅ Fix
|
||||
|
||||
Two independent changes — the first stops the flap, the second smooths latency.
|
||||
|
||||
### 1. Disable IWD's periodic scan (stops the flap)
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/iwd
|
||||
printf '[Scan]\nDisablePeriodicScan=true\n' | sudo tee /etc/iwd/main.conf
|
||||
sudo systemctl restart iwd # briefly drops Wi-Fi; NetworkManager auto-reconnects
|
||||
```
|
||||
|
||||
Trade-off: with periodic scanning off, the Deck roams to a different/stronger AP (e.g. another AiMesh node) more lazily. Fine for a device that mostly sits in one spot.
|
||||
|
||||
### 2. Disable Wi-Fi power save (kills the latency jitter)
|
||||
|
||||
The obvious `nmcli connection modify <name> 802-11-wireless.powersave 2` **does not work under the IWD backend** — NetworkManager doesn't enforce that property when `iwd` is managing the radio. Use a dispatcher script instead, with a retry loop because `rtw88` won't accept the setting in the first instant after association on a cold boot:
|
||||
|
||||
```bash
|
||||
sudo tee /etc/NetworkManager/dispatcher.d/90-wifi-powersave >/dev/null <<'SCRIPT'
|
||||
#!/bin/sh
|
||||
# Disable Wi-Fi power save on the wireless iface (retry: rtw88 may not accept it instantly on boot)
|
||||
case "$2" in
|
||||
up|dhcp4-change|connectivity-change)
|
||||
case "$1" in
|
||||
wl*)
|
||||
for n in 1 2 3 4 5; do
|
||||
/usr/bin/iw dev "$1" set power_save off 2>/dev/null
|
||||
[ "$(/usr/bin/iw dev "$1" get power_save 2>/dev/null)" = "Power save: off" ] && break
|
||||
sleep 1
|
||||
done
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
SCRIPT
|
||||
sudo chmod +x /etc/NetworkManager/dispatcher.d/90-wifi-powersave
|
||||
sudo iw dev wlan0 set power_save off # apply now without waiting for a reconnect
|
||||
```
|
||||
|
||||
> 💡 A single-shot dispatcher (no retry) **silently fails on a cold boot** — it fires before the interface is ready, the `iw` call no-ops, and power save stays on. Verify with `iw get power_save` *after a real reboot*, not just after a service restart.
|
||||
|
||||
## 🔁 Verification
|
||||
|
||||
```bash
|
||||
# was 50/boot, ~once a minute:
|
||||
journalctl -b -u NetworkManager --no-pager | grep -c supplicant-disconnect
|
||||
# 0
|
||||
iw dev wlan0 get power_save
|
||||
# Power save: off
|
||||
```
|
||||
|
||||
A 3-minute continuous `ping` showed **180/180 replies, 0 loss**, latency tightened to **6–11 ms**. Confirmed across a full cold reboot: the Deck auto-rejoins Wi-Fi, both settings persist, and the disconnect counter stays at 0.
|
||||
|
||||
## 📌 Notes
|
||||
|
||||
- **Persistence:** `/etc/iwd/main.conf` and the dispatcher live in `/etc`, which survives reboots. A major SteamOS update *can* reset `/etc` — re-apply if the flapping returns after an OS update.
|
||||
- **Fully reversible:**
|
||||
```bash
|
||||
sudo rm /etc/iwd/main.conf /etc/NetworkManager/dispatcher.d/90-wifi-powersave
|
||||
sudo systemctl restart iwd
|
||||
```
|
||||
- **Interface name** is usually `wlan0`; confirm with `iw dev` if different.
|
||||
- The same IWD-periodic-scan behavior can affect other `iwd`-based distros (Arch, some Fedora spins) on flaky/older Wi-Fi chips — the `DisablePeriodicScan` fix is general, not Deck-specific.
|
||||
|
||||
## 🔗 Related
|
||||
|
||||
- [Wi-Fi Game Streaming Stutter: 160 MHz Channel Width Saturating the 5 GHz Radio](wifi-160mhz-airtime-saturation-game-streaming.md) — the *other* Steam Deck Wi-Fi issue (airtime contention, router-side), distinct from this client-side flap.
|
||||
|
|
@ -109,6 +109,7 @@ The PHY peak dropped (narrower channel) but that is irrelevant — Steam Remote
|
|||
|
||||
## Related
|
||||
|
||||
- [Steam Deck Wi-Fi Flapping: IWD Periodic Scan + rtw88 Power Save](steam-deck-wifi-flapping-iwd-periodic-scan-rtw88.md) — the *other* Steam Deck Wi-Fi issue (client-side flap), distinct from this router-side airtime problem.
|
||||
- [Network Overview](../../02-selfhosting/dns-networking/network-overview.md)
|
||||
- [Wake-on-LAN via Router SSH](../../02-selfhosting/dns-networking/wake-on-lan-router-ssh.md)
|
||||
- [Pi-hole v6 Group Management — Per-Client DNS Rules](../../02-selfhosting/dns-networking/pihole-v6-group-management.md)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ updated: 2026-06-19T10:05
|
|||
* [Plex Transcoding Troubleshooting](04-streaming/plex/plex-transcoding-troubleshooting.md)
|
||||
* [Troubleshooting](05-troubleshooting/index.md)
|
||||
* [Wi-Fi Game Streaming Stutter: 160 MHz Channel Width Saturating the 5 GHz Radio](05-troubleshooting/networking/wifi-160mhz-airtime-saturation-game-streaming.md)
|
||||
* [Steam Deck Wi-Fi Flapping: IWD Periodic Scan + rtw88 Power Save](05-troubleshooting/networking/steam-deck-wifi-flapping-iwd-periodic-scan-rtw88.md)
|
||||
* [Apache Outage: Fail2ban Self-Ban + Missing iptables Rules](05-troubleshooting/networking/fail2ban-self-ban-apache-outage.md)
|
||||
* [Postfix + SendGrid: TLS Handshake Failure (Port 465 vs 587)](05-troubleshooting/networking/postfix-sendgrid-tls-handshake-failure.md)
|
||||
* [Mail Client Stops Receiving: Fail2ban IMAP Self-Ban](05-troubleshooting/networking/fail2ban-imap-self-ban-mail-client.md)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue