--- 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-22 --- # 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 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. - **Why `/etc` resets:** SteamOS uses an immutable A/B root filesystem. An update writes a fresh root image to the other partition and boots it, replacing everything on root โ€” `/etc`, `/usr`, installed packages. Only `/home` and `/var` (separate partitions) survive. Anything that must auto-run **as root at boot** (systemd units, NM dispatcher scripts, sudoers) has to be registered in `/etc`, so there is no clean *native* way to make this fix auto-persist. The realistic choices are a re-run-after-update script in `/home` (below) or a community overlay tool like `rwfus` that makes `/etc`+`/usr` persistent. - **One-command recovery:** a self-contained restore script is staged on the Deck at `/home/deck/restore-wifi-fix.sh` (lives in `/home`, so it survives updates). After any update that wipes the fix, re-apply with: ```bash ssh -t deck@192.168.50.173 'sudo bash ~/restore-wifi-fix.sh' ``` - **Recurrence log:** - **2026-06-22** โ€” flap returned (Wi-Fi did not reconnect after wake). A SteamOS update had wiped `/etc` (both fix files gone; `~/.ssh` and the `deck` SSH password were also reset, the smoking gun that an update ran). Re-applied via the staged `restore-wifi-fix.sh`; verified `power_save off`, `DisablePeriodicScan` present, 60/60 pings 0% loss. MajorAir's SSH public key was added to `deck@192.168.50.173:~/.ssh/authorized_keys` during this session. - **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.