README.md (3322B)
1 # fan/ — the throttle fix, as captured and as declared 2 3 **Slot:** `hosts/laptop/fan-throttle-guard.nix` (import it from `hosts/laptop/default.nix`). 4 5 ## What is in here 6 7 | File | Origin on the Arch install | Role | 8 |---|---|---| 9 | `fan-throttle-guard.nix` | written this pass | the whole fix as one NixOS module | 10 | `fanfix` | `~/.local/bin/fanfix` | CLI + fan-curve daemon (bash, 372 lines) | 11 | `stability_guard.py` | `/usr/local/lib/motherboardctl/stability_guard.py` | staged ceiling 3200/2400/1800 MHz | 12 | `99-cpu-freq-cap.conf` | `/etc/tmpfiles.d/` | the static floor as it is today | 13 | `fanfix.conf` | `/etc/fanfix.conf` | `CURVE="0:60 100:60"` | 14 | `fanfix-fan.service`, `motherboard-stability.service` | `/etc/systemd/system/` | the two units, verbatim | 15 | `modules-load.conf`, `uniwill-laptop.conf` | `/etc/modules-load.d/`, `/etc/modprobe.d/` | module load + `force=1` | 16 | `fan-ctl`, `fan-state` | bar plugin `daemon-sec.fans/bin/` | pkexec dispatcher and the read-only poller the widget uses | 17 18 ## Measured state at capture (2026-10-07 15:21 BST, idle, mains) 19 20 ``` 21 scaling_max_freq 3200000 scaling_min 1121095 cpuinfo_max 5169491 boost 1 22 governor performance driver amd-pstate-epp (status active) profile performance 23 k10temp Tctl 38 °C · uniwill fan1 4347 rpm pwm1 255 · fan2 0 rpm pwm2 255 · board temp2 37 °C 24 amdgpu package 7 W · RTX 3070 Ti 37 °C, 20 W, 16 % util (nvidia-smi fan [N/A]) 25 motherboard-stability: active (limit 3200, stage 0, "mains power; normal temperatures") 26 fanfix-fan.service: enabled but stopped at 15:08 today; EC commanding both fans 100 % 27 ``` 28 29 ## Things that change on NixOS (read before enabling) 30 31 - [ ] `fanfix install` / `uninstall` and `fan-ctl cap` / `uncap` **write `/etc/tmpfiles.d` imperatively**. On NixOS the floor is the `systemd.tmpfiles.rules` line in the module; treat `install`/`cap` as a no-op and change `capKhz` instead. `uncap` still works at runtime but the guard re-applies 3200 MHz within a second, so stop `motherboard-stability.service` first if an uncapped run is wanted. 32 - [ ] `fanfix fan setup` has an **Arch-only package-install branch**. Dead code on NixOS; the module supplies `linuxPackages.acpi_call`. Do not run `fan setup`. 33 - [ ] `fanfix` elevates with `sudo` inside `need_root`; `fan-ctl` expects to be launched by **pkexec** from a bar widget. Both need a polkit agent in the session. Which shell provides it is an open question in the capture note. 34 - [ ] `stability_guard.py` hard-fails unless **exactly 16 cpufreq policies** exist and `/sys/class/power_supply/AC0/online` is the mains sensor. Same hardware, so fine, but check the power-supply name on the NixOS kernel. 35 - [ ] `fanfix status` **false-negatives on the latched low-temperature clamp** (its detector is temperature-gated). Trust `/proc/cpuinfo` "cpu MHz" vs `scaling_min_freq`: cores below the kernel floor = EC clamp. 36 - [ ] Never set the global cpufreq `boost` to 0 (see module header). 37 38 ## First-boot verification 39 40 ```sh 41 fanfix status # cap 3200 MHz · boost 1 · profile performance · fan line present 42 sudo fanfix fan status # fan-abnormal=1 is expected; universal-fan-ctrl / custom-tables show which EC path is live 43 fanfix test 30 # all-core stress: expect 0 throttle events, peak < 75 °C 44 systemctl status motherboard-stability fanfix-fan 45 ```