Feature: Fan Control
Purpose
This feature provides automatic fan control for AMD MI25 GPUs on Linux. It controls every MI25 found, not just one.
The MI25 is a datacenter GPU that ships without a fan. Its BIOS cannot control a fan. Without runtime fan control, the MI25 overheats and shuts down the server. The service reads GPU temperatures from hwmon and writes PWM values to control a blower fan. The service runs continuously as a systemd unit named amd-mi25-fanctl.service. The target use is LLM inference on the GPU in a desktop case. The service minimizes noise and power when the GPU is idle. The service maximizes performance when the GPU is busy.
Requirements
- The service enumerates all AMD GPUs under
/sys/class/drm/card*/device/and identifies which are controllable MI25 cards. - A controllable MI25 matches vendor
0x1002and device0x6860, is bound to the amdgpu driver, and has a hwmon directory exposingpwm1_enable. - The service controls every controllable MI25 found, not just the first.
- The service reports which AMD GPUs it found and which it can control, so an unexpected card is visible.
- The service retries discovery until at least one controllable hwmon directory appears, because at boot the amdgpu driver may not have created it yet.
- The service writes
1topwm1_enableat startup to take manual fan control. - The service never writes
2topwm1_enable; the MI25 firmware fan control does not work. - The service writes
manualtopower_dpm_force_performance_leveland5(COMPUTE) topp_power_profile_modeat startup, so the SMU boosts clocks eagerly under compute load and idles low. - The service never writes
hightopower_dpm_force_performance_level; forced-high clocks conflict with the COMPUTE profile and waste idle power. - The service reads
temp1_input(edge),temp2_input(junction), andtemp3_input(mem) from the hwmon directory. - The service controls the fan from the higher of the junction and mem temperatures.
- The service probes the discovered interface at startup and adapts to driver changes instead of assuming a fixed interface.
- The service records the amdgpu driver version and kernel release at startup; an empty driver version is expected for in-tree drivers.
- The service treats debugfs as optional diagnostics and never depends on it.
- The service maps temperature to a PWM target using fixed stage tables and linear interpolation between stages.
- The service ramps the PWM value smoothly: it rises fast and falls slowly, to avoid oscillation.
- The service writes the computed PWM value to
pwm1. - The service treats its last written PWM value as the source of truth, because the value read back from
pwm1is unreliable. - The service reports edge, junction, and mem temperatures plus PWM state to standard output at a bounded rate.
- The service supports a
SYSFS_ROOTenvironment-variable override so tests can run against a fixture instead of/sys. - The service does not restore automatic control on shutdown.
- The service runs as root.
- The service retries on transient sysfs failures instead of exiting, because the kernel returns
-EBUSYduring GPU reset, suspend, or before full initialization. - The service exits nonzero when the device is removed, because the kernel returns
-ENODEVafter removal and retrying cannot recover. - The service re-asserts
pwm1_enable = 1and retries when apwm1write fails with-EINVAL, because the driver rejects manual PWM writes unless manual mode is active. - The service keeps its last good PWM value during a transient failure and keeps retrying, so fan control is never dropped silently.
- The service treats a
pwm1write that succeeds without effect as a control failure, because the driver’sbNoFanpath silently no-ops.
Behavior
- On startup, the service locates every MI25 hwmon directory, enables manual PWM on each, and sets each fan to the minimum stage.
- The service samples temperatures on every MI25 about once per second.
- The service adjusts the PWM target when the controlling temperature changes by the defined delta.
- The service keeps the mem (memory) temperature below 90 °C under sustained compute load with the reference duct and blower fan.
- The service restarts under systemd whenever it exits.
Dependencies
None.
Open Questions
None remaining; the research spike is complete. See documents/07-failure-behavior.md for the kernel failure taxonomy and the service failure policy.