Skip to content

Releases

Thinkfan-Ex v1.4

Choose a tag to compare

@VexFlint VexFlint released this 08 Sep 17:30

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 reboot

Fixed

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 one echo away in think-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 row real or aborted, because a failed suspend fires suspend.target too 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

Choose a tag to compare

@VexFlint VexFlint released this 04 Sep 23:05

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 disengaged had no deadband, so a temperature resting on
    CRITICAL_TEMP toggled it every few seconds. It now uses the same HYSTERESIS
    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 full HYSTERESIS deadband 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
    leading v is 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 at VexFlint/Thinkfan-Ex directly.

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 reboot

Re-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

Choose a tag to compare

@VexFlint VexFlint released this 04 Sep 23:02

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. Some hwmon nodes
    return nothing while cat still exits 0, so the || echo 0 fallback never fired.
  • Reading /sys/module/thinkpad_acpi/parameters/fan_control aborted the installer
    when thinkpad_acpi is built into the kernel rather than loaded as a module.
  • The default fan command was auto, which /proc/acpi/ibm/fan rejects. The valid
    command is level auto.
  • A grep miss while reading the current level aborted the loop under set -e.
  • local error_code=$? always captured 0, because local resets $?.
  • systemctl enable --now will 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_CONFIRM requires 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.sh

Note 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.