THINKFAN.CONF.LEGACY(5)

πŸ“¦
version 2.0.0 Β· 3 versions
, in alpine 3.24, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu resolute, ubuntu stonking

✨ THINKFAN.CONF.LEGACY β€” bestie edition ✨

okay so this is the old-school, backwards-compatible config syntax for thinkfan β€” the one your grandma's ThinkPad config is written in πŸ’– (it's thinkfan(1) btw, go read that one too).


🌸 NAME 🌸

thinkfan.conf.legacy β€” the old, backwards-compatible config syntax for thinkfan thinkfan(1) πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

So here's the vibe. Your thinkfan config file tells the program three things:

  • one or more temperature inputs
  • exactly one fan to control
  • and the fan levels

A fan level is basically a situationship between a fan speed and a lower + upper temperature bound 🫢. Here's the tea: if the temperature hits the upper bound, we switch to the next fan level. If it drops below the lower bound, we switch back to the previous one. Slay.

Temperature bounds can be either:

  • a single temperature β†’ that's simple mode
  • multiple temperatures β†’ that's complex mode

In simple mode, only the highest of all known temperatures gets compared against the upper & lower bound. Like, that's it, that's the whole comparison.

Now β€” if you've got devices with very different temperature ratings (CPU vs. mechanical hard drives, the classic chaotic duo 😭), you should specify correction values to equalize their temperature ranges. Or better: use complex mode.

In complex mode, the upper and lower bounds of each fan level are specified for each sensor individually. Thinkfan then switches to the next fan level if one of the upper bounds is reached, and switches back to the previous fan level if all temperatures have dropped below their respective lower bounds. Different rules, iconic behaviour, no cap.


🌑️ THERMAL SENSORS 🌑️

You can combine multiple sensor keywords in one config file, but heads up bestie β€” the ordering is significant with respect to the upper and lower fan level bounds if you use complex mode. Like, literally: if /proc/acpi/ibm/thermal contains 16 temperatures and you specify an hwmon sensor after the tp_thermal statement, that hwmon sensor will be the 17th temperature. Position matters fr fr πŸ‘‘

After each sensor path, you can optionally drop a correction-value. This value (can be negative, drama allowed) is always added to the temperature reading from that sensor. Correction values should be specified if you use Simple Mode with components that have a different temperature rating, like hard disks and CPUs.

but ngl, Complex Mode is generally the better solution here β€” it gives you full control over fan levels and temperature ranges for each sensor, instead of just adding a fixed value to equalize temperature ranges. no notes πŸ’…

🧚 tp_thermal /proc/acpi/ibm/thermal [ (correction-value ...) ]

Use the thermal sensors provided by the thinkpad_acpi kernel module on older thinkpads. These normally reside in /proc/acpi/ibm/thermal, so this keyword will hardly be used with other paths.

This file usually contains 8-16 temperatures, some of which may be reserved for removable hardware or completely unused. Unused temperature slots always contain the value -128.

Since this file contains all temperatures the thinkpad_acpi module knows about, there cannot be more than one tp_thermal statement in a config file. one (1) only, bestie 🫢


πŸ“ hwmon sysfs-path [ (correction-value) ]

Use a standard hwmon temperature input that may be provided by all kinds of kernel drivers. sysfs-path is usually a file named temp*_input, somewhere under /sys, so you can search for them e.g. with:

find /sys -type f -name "temp*_input"

Each of these files contains one temperature, so you need to add a hwmon statement for each device whose temperature you wish to control. yes, individually. it's giving admin homework but we do it πŸ’…


πŸ’€ atasmart device-path [ (correction-value) ]

NOTE: only available if thinkfan was compiled with USE_ATASMART enabled.

Read the temperature directly from a hard disk using S.M.A.R.T. See also the -d option in thinkfan(1) that prevents thinkfan from waking up sleeping (mechanical) disks to read their temperature. let them nap 😴


🌈 nv_thermal pci-bus-id [ (correction-value) ]

NOTE: only available if thinkfan was compiled with USE_NVML enabled.

Read the temperature of an nVidia graphics card from the proprietary nVidia driver. This does not work with the open-source Nouveau driver β€” it depends specifically on libnvidia-ml.so that is usually installed with the binary nVidia driver.

The correct pci-bus-id can be retrieved using e.g. lspci with:

lspci | grep -i vga

Most open-source graphics drivers (radeon, nouveau, possibly others too) can instead be used with the hwmon keyword described above. options on options, we love to see it ✨


πŸŽ€ FANS πŸŽ€

Currently, thinkfan can control only one fan at a time. In theory, you can run multiple instances of the program simultaneously (with multiple config files) to control multiple fans β€” but that requires enabling DANGEROUS mode and will likely break most init scripts. so like, theoretically possible, practically chaos 😭

It is an error to have more than one fan statement per config file. periodt.

πŸ‘‘ tp_fan /proc/acpi/ibm/fan

Use the fan control provided by the thinkpad_acpi kernel module, which needs to be loaded with the option fan_control=1. The path is defined by the thinkpad_acpi kernel module and will hardly change.

Besides the fan levels ranging from 0 to 7, it also supports the disengaged and auto modes:

  • The auto mode should delegate fan control to the firmware, so it can be regarded as a 'default' mode that does not change the fan behavior. This is useful for example if you only want to change the fan behavior at high and/or low temperatures. lowkey the polite option 🫢
  • The disengaged or full-speed mode effectively disables the fan RPM limiter. Fan speed will slowly ramp up until the fan uses the maximum electrical power available from the embedded controller.
⚠️ Use disengaged/full-speed only to prevent potentially destructive overheating, since it runs the fan outside of specifications and wears its bearings down quickly. like, it will cook itself to save you. dramatic but effective πŸ’€

🧊 pwm_fan sysfs-path

Control a sysfs PWM fan. Many hwmon drivers that provide a temp*_input file also allow fan control, although there may also be drivers that are specific to either temperature reading or fan control. You can search for a PWM control file e.g. with:

find /sys -type f -name "pwm?"

Note that with PWM, fan levels usually range from 0 to 255, although besides a file like pwm1 there may also be pwm1_min and pwm1_max that specify different (soft or recommended?) limits for a particular fan. the question mark in that sentence is doing so much work 😭


πŸ”₯ FAN LEVELS πŸ”₯

Defining the fan levels is the meat of the config file. Here you make use of your previously defined temperature inputs to set the lower and upper bounds for the fan speeds.

🚨 You cannot mix simple fan levels with complex fan levels. pick a lane bestie, both are valid, mixing is not.

The general syntax of a simple fan level is:

( fan-level [,] lower-bound [,] upper-bound )

The fan-level is either:

  • a numeric value (0-7 or 0-255, depending on whether a tp_fan or a pwm_fan is used), or
  • a string enclosed in double quotes.

When a tp_fan is used, specifying 0 has the same effect as specifying "level 0". In addition to the numeric fan levels, tp_fan also supports "level auto" and "level disengaged" or "level full-speed". See above for an explanation of what these mean πŸ‘†

The format of lower-bound and upper-bound depends on whether you want to use Simple Mode or Complex Mode.


🌼 Simple Mode

In simple mode, the lower-bound and upper-bound of a fan level are each specified as a single temperature value. Both are compared only to the highest temperature found in all of the configured thermal sensors.

Using this mode of operation makes sense e.g. if all temperature readings come from the on-DIE thermal sensors of a multicore processor. The fan speed will affect all of these temperatures in the same way because they share a single thermal connection to the heatsink, so it makes sense to ignore all but the highest of these temperatures. cute and efficient ✨

Rule of thumb: if your thermal sensors cover multiple devices you should use Complex Mode, or at least specify correction values to account for different temperature ratings.

πŸ¦„ Complex Mode

In complex mode, both the lower-bound and upper-bound are lists of temperatures, the length of which must match the number of temperature readings thinkfan knows about. Each bound must be enclosed in braces, with individual values separated by commas or spaces.

So the specific syntax of a complex mode fan level is:

{ fan-level
    ( lower-1 [lower-2 ...] )
    ( upper-1 [upper-2 ...] )
}

The optional commas have been omitted here for readability, and the curly braces are interchangeable with round braces. Note that it is not possible to mix simple fan levels with complex fan levels. (saying it twice because it matters πŸ’…)

Complex mode is generally the preferred mode of operation since it allows you to specify precisely what the fan should do to keep each component within its specified temperature range. main character energy, honestly πŸ‘‘


πŸ’– SEE ALSO πŸ’–


okay that's the whole page bestie, go forth and cool your ThinkPad responsibly πŸ¦‹βœ¨

this lil manual moment was brought to you by thinkfan 2.0.0, dated 2020-04-09 β€” vintage but still serving πŸ’…πŸŽ€