- Shell 100%
| sleep | ||
| systemd | ||
| deploy.sh | ||
| legion-thermal-gov | ||
| README.md | ||
| thermal-cap-ac.yaml | ||
legion_thermals
Thermal management for the Lenovo Legion with AMD Ryzen 9 7945HX on Linux.
Targets sustained CPU temperatures at or below 85°C with fans capped at 3500 RPM, without relying on ryzenadj (which the Lenovo EC resets within seconds).
How it works
Two independent layers:
1. Thermal governor (legion-thermal-gov)
A daemon that polls k10temp Tctl every 500ms and walks scaling_max_freq up or
down proportionally. The Linux cpufreq layer enforces this limit — the firmware EC
has no mechanism to override it.
- Normal overshoot (>82°C): steps down 400 MHz × overshoot multiplier (up to 1.6 GHz/s)
- Emergency (>88°C): drops 1.2 GHz in a single step
- Recovery (<77°C): rises slowly at 100 MHz/tick so temps don't immediately spike again
- Also sets
energy_performance_preferencetobalance_poweron all cores at startup, which softens the initial all-core boost ramp before the governor can react
2. Fan curve (thermal-cap-ac.yaml)
Written directly to the EC via legion_cli. Hard-capped at 3500 RPM.
Uses 5°C hysteresis at every band transition and slow deceleration throughout
to prevent fan hunting.
Platform profile is set to balanced on boot, giving the EC a moderate TDP baseline
to work from.
Files
legion-thermal-gov Governor daemon → /usr/local/bin/
thermal-cap-ac.yaml Fan curve preset → /etc/legion_linux/
systemd/
legion-thermal-gov.service Runs the governor on boot
legion-fancurve.service Applies fan curve + platform profile on boot and resume
sleep/
legion-resume Re-applies fan curve after suspend → /lib/systemd/system-sleep/
deploy.sh Installs everything
External dependencies
1. lenovolegionlinux (DKMS + CLI)
Provides the legion_laptop kernel module and legion_cli tool.
The package is in Ubuntu 26.04 (Resolute). On Ubuntu 24.04 / Linux Mint 22.x,
install the .deb files directly from Launchpad:
https://launchpad.net/ubuntu/+source/lenovolegionlinux/0.0.20+ds-1.1
Download and install these three packages for amd64:
lenovolegionlinux-dkms_0.0.20+ds-1.1_amd64.deblegiond_0.0.20+ds-1.1_amd64.debpython3-legion-linux_0.0.20+ds-1.1_all.deb
sudo apt-get install -y dkms linux-headers-$(uname -r) python3-pyqt5 python3-yaml python3-argcomplete
sudo dpkg -i lenovolegionlinux-dkms_*.deb legiond_*.deb python3-legion-linux_*.deb
2. Kernel requirements
- Kernel 6.x recommended (6.17+ confirmed working)
amd_pstate=activemust be the active driver:
If it showscat /sys/devices/system/cpu/amd_pstate/status # should print "active"passiveorguided, addamd_pstate=activeto your kernel cmdline in/etc/default/gruband runsudo update-grub.
3. Required system packages
sudo apt-get install -y dkms linux-headers-$(uname -r)
Installation
git clone <this-repo> /home/user/Code/legion_thermals
cd /home/user/Code/legion_thermals
./deploy.sh
deploy.sh will re-invoke itself with sudo if not already root.
Monitoring
# Live governor log (freq adjustments)
journalctl -u legion-thermal-gov -f
# Live temp + freq cap
watch -n 0.5 "
echo CPU: \$(( \$(cat /sys/class/hwmon/hwmon4/temp1_input) / 1000 ))°C
echo Cap: \$(( \$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq) / 1000 ))MHz
echo Fan1: \$(cat /sys/class/hwmon/hwmon9/fan1_input) RPM
echo Fan2: \$(cat /sys/class/hwmon/hwmon9/fan2_input) RPM
"
Note:
hwmon4(k10temp) andhwmon9(legion_hwmon) indices may differ after a reboot. Rungrep -l k10temp /sys/class/hwmon/*/nameandgrep -l legion /sys/class/hwmon/*/nameto find the correct indices.
Tuning
All tuning knobs are variables at the top of legion-thermal-gov. Edit the file
then restart the service:
sudo nano /usr/local/bin/legion-thermal-gov
sudo systemctl restart legion-thermal-gov
| Variable | Default | Effect |
|---|---|---|
TARGET_TEMP |
82000 | Start throttling above this (millidegrees) |
RECOVER_TEMP |
77000 | Only recover freq below this |
CRITICAL_TEMP |
88000 | Emergency 1.2 GHz drop threshold |
FREQ_CEILING |
4500000 | Max allowed frequency in kHz |
FREQ_FLOOR |
1800000 | Min allowed frequency in kHz |
FREQ_STEP |
400000 | Normal step size per tick (kHz) |
FREQ_STEP_CRITICAL |
1200000 | Emergency step size (kHz) |
FREQ_RECOVER |
100000 | Recovery step size per tick (kHz) |
INTERVAL |
0.5 | Poll interval in seconds |
Fan curve is edited in thermal-cap-ac.yaml. After editing, redeploy it:
sudo cp thermal-cap-ac.yaml /etc/legion_linux/
sudo legion_cli fancurve-write-preset-to-hw thermal-cap-ac --preset-dir /etc/legion_linux
Uninstalling
sudo systemctl disable --now legion-thermal-gov.service legion-fancurve.service
sudo rm /usr/local/bin/legion-thermal-gov
sudo rm /etc/systemd/system/legion-thermal-gov.service
sudo rm /etc/systemd/system/legion-fancurve.service
sudo rm /lib/systemd/system-sleep/legion-resume
sudo rm /etc/legion_linux/thermal-cap-ac.yaml
sudo rm /etc/modules-load.d/legion.conf
sudo systemctl daemon-reload