Repository navigation
Releases
Thinkfan-Ex v1.4
Fixes a release that installed wrong, ships the resume probe, and stops shipping 94 MB of Lenovo binaries.
Install
curl -LO https://github.com/VexFlint/Thinkfan-Ex/archive/refs/tags/v1.4.tar.gz
tar xf v1.4.tar.gz && cd Thinkfan-Ex-1.4
chmod +x *.sh
sudo ./thinkfan-extreme.sh
sudo rebootFixed
v1.3.1 installed wrong. Its source tarball was missing power-unlock.sh, so the installer hit its own Skipping power-unlock.sh: not found next to this installer path and silently produced a fan-daemon-only install with no thinkpad-power-unlock. This tarball was extracted and checked before tagging — not checking is how the last one shipped broken.
firmwares/ is no longer tracked. 94 MB of Lenovo BIOS packages and dock updater binaries had been committed, against the policy FIRMWARES/.gitignore already stated for the same class of file. It also meant FIRMWARES/ and firmwares/ differed only in case, so the repo could not be checked out on macOS or Windows at all. Nothing committed depended on them; .gitignore carries the download URLs.
History was then rewritten to purge them from all 99 commits, so a fresh clone is 424 KB rather than 83 MB. Commit hashes before this release changed; the file tree at each tag did not.
Added
Everything from the firmware investigation, previously unreleased:
MACHINE.md— every fact read off the test machine with the command beside it. Opens with the settings that can destroy the board (one of them is oneechoaway inthink-lmi) and closes with a table of this repo's own confident wrong answers.FIRMWARE.md— the undervolt and power-limit investigation. Core and cache share a rail; −100 mV bought +10.2 % all-core clock on AC and −15.4 % whole-machine power on battery; −140 mV hung the machine; the −120 mV display artifact never reproduced.BIOS-MOD.md— the firmware's hidden Intel Advanced Menu: 2,809 settings, 124 forms, 2,123 suppressed. Research, not a procedure — the conclusion is that nothing this repo wants is behind a door whose write route cannot be undone.uvsoak.sh— a soak harness that verifies answers, not uptime. Four concurrent known-answer workloads, references computed at 0 mV before and after, every line fsynced.uv-resume-probe— measures what suspend does to the voltage mailbox, ordered ahead of the re-apply so survived S3 and was restored for us can be told apart. Tags each rowrealoraborted, because a failed suspend firessuspend.targettoo and otherwise writes a row that reads exactly like the offset surviving.
Note
The undervolt is opt-in and not installed by the installer, by design. See Undervolting — and read the caution first; no number in it transfers to another laptop.
Thinkfan-Ex v1.3.1
The companion tools now live on PATH, and the curve no longer takes orders from
your Wi-Fi chip.
Neither 1.2.1 nor 1.3 was left standing as its own release, so everything below is
what has landed since v1.2.
Added — 1.3
The companion tools install to /usr/local/bin. Previously only the
thinkfan-ex daemon went on PATH, so the four tools ran solely as ./name.sh
from inside the clone — which the README's command tables never said, making
sudo ./powerwatch.sh from anywhere else fail with command not found. They are
now installed alongside the daemon:
| Tool | Installed as |
|---|---|
powerwatch.sh |
powerwatch |
sensors.sh |
thermalsensors |
fanbench.sh |
fanbench |
chargewatch.sh |
chargewatch |
sensors.sh becomes thermalsensors, not sensors: /usr/local/bin precedes
/usr/bin on PATH, so a binary called sensors there would shadow lm_sensors.
thinkfan-ex -uninstall removes all four, so nothing is orphaned. The tools stay
standalone — the daemon never calls them, and they still run straight from the
clone if you would rather install nothing.
Added — 1.2.1
SENSOR_PATTERNS, honoured by both the control loop and-probe. The curve
was driven by the hottest reading across every hwmon in the system, so an
unrelated device — Wi-Fi, NVMe, PCH — could command a CPU fan. The default is now
the CPU package and cores only.
Fixed — 1.2.1
- Entering and leaving
disengagedhad no deadband, so a temperature resting on
CRITICAL_TEMPtoggled it every few seconds. It now uses the sameHYSTERESIS
as every other level.
Changed — 1.2.1
- Default thresholds re-spaced so the fan starts at 51 °C and stops at 45 °C,
keeping a fullHYSTERESISdeadband at the bottom of the ladder.
Documentation — 1.3.1
- Installation covers installing from a release as well as from a clone, including
the tarball URL and the directory name GitHub produces (Thinkfan-Ex-1.3.1— the
leadingvis stripped). - The clone URL and
chargewatch.sh's header comment pointed at
BrunoGrande/Thinkfan-Ex, which resolves only through GitHub's rename redirect.
Both now point atVexFlint/Thinkfan-Exdirectly.
Upgrading
curl -LO https://github.com/VexFlint/Thinkfan-Ex/archive/refs/tags/v1.3.1.tar.gz
tar xf v1.3.1.tar.gz
cd Thinkfan-Ex-1.3.1
chmod +x *.sh
sudo ./thinkfan-extreme.sh
sudo rebootRe-running the installer is safe: it detects the modprobe.d line and boot
parameter already being present, and restarts the service rather than leaving an
old daemon running from memory. No reboot needed if you rebooted for 1.2.
Note
The thinkfan-extreme.sh attached below is handy for reading the installer before
you trust it with your fan, but running that file alone installs the daemon
only. It copies the companion tools just if they sit beside it, so a single-file
download logs Skipping powerwatch.sh: not found next to this installer four
times and leaves nothing on PATH but thinkfan-ex. Take the tarball or the
clone if you want powerwatch, thermalsensors, fanbench and chargewatch.
Thinkfan-Ex v1.2
Fan control rebuilt around measured hardware behaviour rather than assumed
behaviour, plus two new tools for measuring your own machine.
Highlights
Defaults derived from measurement. Fan speeds were benched on a repasted
ThinkPad T480 and the level ladder pruned to the speeds that actually differ.
Levels 4 and 7 measured identical to 3 and 6, and level 0 stops the fan entirely,
so all three are now unused. CRITICAL_TEMP is 88000 and HYSTERESIS 6000 to suit
the wider bands that pruning produces.
thinkfan-ex -check reports whether a machine supports fan control at all:
driver, fan interface, manual control state, which of level / auto /
disengaged / full-speed the firmware accepts, watchdog availability and sensor
count. Never touches the fan.
thinkfan-ex -probe measures real RPM at every level, waiting for the
tachometer to go steady rather than using a fixed dwell.
fanbench.sh is an interactive bench: live RPM, change level by keypress, and a
min/max/last table per level as you work through them.
EC watchdog armed automatically. If the daemon is killed without running its
cleanup trap, firmware reclaims the fan after WATCHDOG_TIMEOUT seconds.
Fixed
- An empty sensor read aborted the control loop under
set -e. Somehwmonnodes
return nothing whilecatstill exits 0, so the|| echo 0fallback never fired. - Reading
/sys/module/thinkpad_acpi/parameters/fan_controlaborted the installer
whenthinkpad_acpiis built into the kernel rather than loaded as a module. - The default fan command was
auto, which/proc/acpi/ibm/fanrejects. The valid
command islevel auto. - A
grepmiss while reading the current level aborted the loop underset -e. local error_code=$?always captured 0, becauselocalresets$?.systemctl enable --nowwill not restart an already-running service, so
reinstalling over a live install left the old daemon running the old code.- Hysteresis was applied as an offset to every level below the current one, which
shifts the whole ladder down while leaving the bands exactly as narrow as before.
It is now a deadband around the level actually held. - A single-sample temperature spike raised the level while the smoothed temperature
still permitted an immediate drop, so the fan reversed itself one poll later.
UP_CONFIRMrequires consecutive readings to agree before raising. - The configuration used when the config file fails its syntax check no longer
diverges from the shipped defaults.
Added
HYSTERESIS,SMOOTH_SAMPLES,UP_CONFIRM,WATCHDOG_TIMEOUT-check,-probe,fanbench.sh- Startup logging of the configuration source and every resolved value
Upgrading
The installer does not overwrite an existing configuration, so a v1.1 config will
survive and silently keep the old curve. To take the new defaults:
sudo thinkfan-ex -uninstall
echo "level auto" | sudo tee /proc/acpi/ibm/fan
sudo rm -f /etc/thinkfan-extreme.conf
chmod +x thinkfan-extreme.sh
sudo ./thinkfan-extreme.shNote on the defaults
These thresholds were measured on one machine with healthy thermals. A laptop with
degraded paste will sit at the top of this curve constantly. Run -check, then
fanbench.sh, and set your thresholds against what your own fan does.