Skip to content

Instantly share code, notes, and snippets.

@maxim-saplin
Last active June 29, 2026 15:47
Show Gist options
  • Select an option

  • Save maxim-saplin/b97806289ae2dd6575d1b19b2f1e9955 to your computer and use it in GitHub Desktop.

Select an option

Save maxim-saplin/b97806289ae2dd6575d1b19b2f1e9955 to your computer and use it in GitHub Desktop.
MSI Claw A1M on Bazzite: Choppy Audio After Suspend, WiFi, ZeroTier.md
Post-sleep choppy/fast-forward audio on the MSI Claw A1M was mainly a **real-time clock (RTC) bug on resume**, not a PipeWire-only issue and not something fixed by cranking CPU power. Setting the hardware clock to **UTC** (`timedatectl set-local-rtc 0`) made suspend/resume timing sane and audio recover after a brief glitch. A separate issue — **game controller dead in Proton while Steam UI still worked** — was caused by HHD **DInput mode**; disabling it and restarting the game fixed that. **Post-sleep sticks/dpad/buttons dead (Steam button OK)** is a different bug — MSI gamepad USB `3-9` breaks after sleep unless rebinded. **Sluggish pad for ~15s after wake** was our sleep hook restarting HHD after rebind (fixed — rebind only). Skip `snd_hda_intel` modprobe tweaks; this machine uses **Intel SOF** (`sof-hda-dsp`).
---
> Claw A1M Bazzite: audio glitch = `timedatectl set-local-rtc 0`; WiFi after sleep = BE200 `d3cold_allowed=0` + `claw-wifi-post-resume.sh` (ZT after WiFi, `rp_filter=0`, **no WiFi rfkill / nmcli in hook**); gamepad after sleep = USB `3-9` rebind only (**no autosuspend**, **no HHD restart in hook**); battery stuck = `claw-battery-charge-kick.sh` (HHD limit sync); ZeroTier = ensure-online service; Proton pad = HHD DInput off + restart game; sleep drain/fan in sleep ~2%/h = **same on Windows** (DRIPS 0%), shutdown for long idle; wake flash→re-sleep = try **disable Gamescope DPMS** in HHD. Skip `snd_hda_intel` and `mem_sleep_default=deep`.
## TL;DR
| Problem | Fix | Status |
|---------|-----|--------|
| Choppy / fast-forward audio after sleep | `timedatectl set-local-rtc 0` + reboot | **Fixed** |
| Controller dead in Proton, OK in Steam UI | HHD **DInput off** → restart HHD + **restart game** | **Fixed** |
| Sticks/dpad/buttons dead after sleep (Steam btn OK) | Sleep hook: **no USB autosuspend** on `3-9`; **USB rebind** on wake | **Fixed** |
| Controller sluggish ~15s after wake | Removed **redundant `systemctl restart hhd`** from sleep hook (rebind only) | **Fixed** |
| WiFi dead after sleep | BE200 `d3cold_allowed=0` (udev) + sleep hook | **Fixed** |
| WiFi exclamation / "no internet" after wake | `rp_filter=0` on wlan0 + `claw-wifi-post-resume.sh`; ZT starts **after** WiFi verified | **Fixed** |
| Battery "not charging" on AC (at limit or after Windows boot) | `claw-battery-charge-kick.sh` syncs HHD `p85` → sysfs; `--retry` on wake | **Fixed** |
| ZeroTier OFFLINE after boot | `zerotier-ensure-online.service` | **Fixed** |
| Sleep hook on power-button suspend | `systemd-suspend.service.d` drop-in | **Fixed** |
| Fan spinning during sleep | Shallow `s2idle`, no S0ix — **Windows same** | **Not fixed** |
| Wake → brief screen → sleep again | HHD **Gamescope DPMS** timeout on wake; disable in HHD to test | **Workaround** |
| Sleep battery drain (~2%/h) | Platform floor — **Windows same** | **Not fixed** — shutdown for 8h+ |
---
## Hardware (short)
- **Audio:** SOF `sof-hda-dsp`, PCI `8086:7e28` — **not** `snd_hda_intel`
- **WiFi:** BE200 `8086:272b` at `0000:2b:00.0`, drivers `iwlmld` + `iwlwifi` — **not** CNVi `8086:7e40`
- **Gamepad:** MSI USB `0db0:1902` at `usb 3-9` (built-in; not Bluetooth)
- **Sleep:** `s2idle` only — **`mem_sleep_default=deep` = cold reboot**
---
## 1. Audio after suspend
**Cause:** RTC in local TZ → clock jumps ~3h on wake while real sleep is ~0.1s → PipeWire/SOF timing breaks.
**Fix:**
```bash
sudo timedatectl set-local-rtc 0
sudo reboot
```
**Also installed:**
- `/etc/modprobe.d/50-msi-claw-sof.conf` — SOF quirks
- `/etc/udev/rules.d/99-msi-claw-audio-pm.rules` — audio PCI `power=on`
- `~/.config/wireplumber/wireplumber.conf.d/80-alsa-headroom.conf` — Bazzite profile typo workaround
**Don't:** `snd_hda_intel` modprobe, PCI unbind hooks, PipeWire restart mid-game (needs **game restart**).
---
## 2. WiFi after suspend
### 2a. WiFi dead (no association)
**Cause:** BE200 (`8086:272b`, `0000:2b:00.0`) enters D3cold on `s2idle` wake and can't return to D0 — WiFi dead until reboot.
**Fix:**
```bash
# /etc/udev/rules.d/99-be200-no-d3cold.rules
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x8086", ATTR{device}=="0x272b", ATTR{d3cold_allowed}="0"
```
Sleep hook (section 6) also sets `d3cold_allowed=0` before sleep.
**Removed:** `fix-wifi-sleep.service` — duplicate of the udev rule.
**Don't:** unload `iwlmld` over SSH — kills WiFi, may need reboot.
### 2b. WiFi connected but exclamation / "can't reach internet"
**Cause (observed in logs):** NM can show `CONNECTED_GLOBAL` while apps still fail (`http error 0` in Steam). Contributing factors:
1. **ZeroTier starting before WiFi** on wake → NM sits at `CONNECTED_LOCAL` (ZT only, no default route) → exclamation icon
2. **`rp_filter=2` on wlan0** — Fedora NM docs warn strict rp_filter breaks connectivity checks / reply packets after resume
3. **`systemd-resolved` cache flush** on clock jump (`Clock change detected. Flushing caches.`) right as WiFi comes up
4. LAN/SSH can work while hostname-based internet is still broken for seconds (or longer without recovery)
NM backend is **IWD** (`/etc/NetworkManager/conf.d/iwd.conf`).
**Fix (installed):**
```bash
# /etc/sysctl.d/99-msi-claw-wlan-rp-filter.conf
net.ipv4.conf.wlan0.rp_filter = 0
```
`/usr/local/bin/claw-wifi-post-resume.sh` — after wake: wait for wlan0 connected → flush DNS caches → `nmcli networking connectivity wait` → verify real HTTP (fedora hotspot + 1.1.1.1) → `nmcli device reapply wlan0` if still broken (up to 3 tries) → **then** start ZeroTier.
`/etc/NetworkManager/dispatcher.d/99-claw-wifi-post-resume` — same script on wlan0 `up` (manual radio toggle).
SELinux: `/var/lib/iwd/` relabeled `NetworkManager_var_lib_t` — gamescope WiFi toggle was hitting AVC denials on `wfn.psk`.
**Do not** in the sleep hook:
- `rfkill block wlan` — forces full reconnect on wake
- `nmcli device reapply` / `nmcli device connect` **in the hook itself** — fights NM sleep/wake (the background recovery script is OK — it waits for NM first)
**Don't:** manual WiFi off/on spam from gamescope — creates duplicate `wfn` connection profiles and IWD `InProgress` errors.
Brief exclamation (~1s) during `CONNECTED_SITE` → `CONNECTED_GLOBAL` can still happen — that's normal. Stuck exclamation with LAN working = run recovery manually:
```bash
sudo /usr/local/bin/claw-wifi-post-resume.sh
```
---
## 3. Controller after suspend
### 3a. Dead in Proton only (Steam UI OK)
**Cause:** HHD **DInput mode** — physical pad is DirectInput; Proton expects XInput.
**Fix:** DInput **off** in HHD → `sudo systemctl restart hhd` → **exit and relaunch game**.
### 3b. Sticks / dpad / buttons dead after sleep (Steam button still OK)
**Cause:** Built-in gamepad USB `3-9` (`0db0:1902`) hits `input irq status -75` storm after sleep. Sleep hook used to set **USB autosuspend** on `3-9` — restoring `power=on` wasn't enough. Steam button uses separate **MSI WMI hotkeys**, so it can still work.
**Fix (in sleep hook):** keep `3-9` **power=on** (no autosuspend); post-wake **unbind/rebind** `3-9` only. HHD recovers the pad on its own after rebind.
**Manual recovery (if pad still dead):**
```bash
sudo sh -c 'echo 3-9 > /sys/bus/usb/drivers/usb/unbind; sleep 2; echo 3-9 > /sys/bus/usb/drivers/usb/bind'
sudo systemctl restart hhd # only if rebind alone isn't enough
```
**Don't confuse with 3a** — DInput off won't fix USB `-75` irq storm.
### 3c. Pad sluggish for several seconds after wake (but eventually OK)
**Cause (logs):** Sleep hook did USB rebind → HHD launched emulated pad → hook then **`systemctl restart hhd`** → full HHD cold start (~15–18s: SDL mappings, DPMS handler, relaunch pad). HHD also resets TDP/GPU on wake (+4–5s).
**Fix:** removed HHD restart from sleep hook. Expect **~3–5s** before pad is fully responsive. A few seconds more from HHD TDP/GPU wake timers is normal.
**Optional HHD:** **Steam Powerbutton Handler** (`powerbuttond`) — fine to enable; unrelated to USB `-75`. If wake feels like it **immediately sleeps again**, see §7b (Gamescope DPMS).
---
## 4. ZeroTier after boot
**Fix:** `zerotier-ensure-online.service` + `/usr/local/bin/zerotier-ensure-online.sh` — polls for ONLINE, restarts `zerotier-one` if stuck.
On **resume**, hook stops ZT before sleep; `claw-wifi-post-resume.sh` starts it only after WiFi passes real connectivity checks (not on a fixed 5s timer).
---
## 5. Battery "not charging" on AC
**Cause:** EC/firmware charge path stuck after sleep (`Not charging`, 0A with AC on). Also: **Windows 80% charge limit** can persist into Linux (sysfs `charge_control_end_threshold=80` while HHD wants `p85`) — looks like "not charging" at 80%.
**Fix:**
- `/usr/local/bin/claw-battery-charge-kick.sh` — syncs limit from HHD `state.yml`, nudges EC via threshold 100→limit; `--retry` on wake
- `/etc/udev/rules.d/99-msi-claw-battery-charge-kick.rules` — delayed kick on AC plug-in
**Manual:**
```bash
sudo /usr/local/bin/claw-battery-charge-kick.sh --sync
sudo /usr/local/bin/claw-battery-charge-kick.sh
```
**Normal:** at **85%** with HHD `charge_limit: p85` — intentional hold, not a bug.
---
## 6. Sleep hook (power-button suspend)
Early on, hooks in `/etc/systemd/system-sleep/` didn't run on button suspend. Fixed:
```ini
# /etc/systemd/system/systemd-suspend.service.d/msi-claw-s2idle.conf
[Service]
ExecStartPre=-/etc/systemd/system-sleep/50-msi-claw-s2idle-power.sh pre suspend
ExecStartPost=-/etc/systemd/system-sleep/50-msi-claw-s2idle-power.sh post suspend
```
**Hook does:** rfkill **BT only** (not WiFi), BE200 d3cold, stop fprintd/zerotier, unbind Goodix USB `3-4`, **keep gamepad USB `3-9` power=on** (no autosuspend); post-wake: rebind Goodix, **rebind gamepad `3-9` only** (no HHD restart), battery charge kick (background `--retry`), launch **`claw-wifi-post-resume.sh`** (ZT starts from that script after WiFi verified). **NM handles WiFi reconnect** — no nmcli in hook.
**Hook does NOT:** fix S0ix / sleep drain / fan-off in sleep.
---
## 7. Sleep drain, fan, and wake quirks — NOT FIXED
### 7a. Battery drain (~2%/h)
S0ix never engages on Linux. **Windows 11 Modern Standby (Connected)** on same hardware: **DRIPS 0%**, **~2–2.6%/hr**, power LED stays on — comparable to Linux. Not a Linux-only regression; platform/firmware floor with connected standby.
Shutdown for long idle (8h+).
### 7b. Fan audible during "sleep"
**Observed:** Fan can run while device appears asleep (including long `s2idle` sessions). Logs show real `PM: suspend entry` / `suspend exit` — not a failed suspend, but **shallow sleep** with SoC still warm. Fan may also run during the **pre-suspend freeze** phase (seconds before hardware sleeps). **No software fan-off** — MSI EC/firmware; `fw-fanctrl-suspend` is a Framework script and fails here (ignore).
### 7c. Wake → screen flash → sleeps again
**Observed:** HHD enables **Gamescope DPMS** on sleep entry; on wake, **`DPMS timeout lapsed`** (~30 min timer, can coincide with wake) → logind **`The system will suspend now!`** again.
**Workaround:** In HHD, try disabling **Gamescope DPMS** (`gamemode.gamescope.dpms` / "Poweroff screen before sleep"). Unrelated to fan, but explains double-suspend feel on resume.
**Never do:** `mem_sleep_default=deep`, `modprobe -r intel_vpu`, PCI audio unbind hook, ROG Ally fingerprint rule, **USB autosuspend on gamepad `3-9`**.
---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment