Task: Implement the Fan Control Service
TASK-DESCRIPTION
Implement the fan-control service in C++ on this skeleton base, per prompts/features/02-fan-control.md, documents/06-fan-control-service-plan.md, and documents/07-failure-behavior.md.
Create sources/gpu_interface.h and sources/gpu_interface.cpp. The gpu interface module discovers the MI25 card and provides reads and writes of the hwmon and power attributes.
Create sources/fan_curve.h and sources/fan_curve.cpp. The fan curve module maps temperature to a PWM target with stage tables and interpolation, and ramps the PWM smoothly.
Create sources/mi25_fan_control.cpp. The main module implements the startup sequence, the control loop, reporting, and the failure policy.
Create CMakeLists.txt and .clang-format. The CMake build compiles the three source modules into the amd-mi25-fanctl binary.
Create scripts/install.sh and scripts/amd-mi25-fanctl.service. The install script installs the binary and the systemd unit.
Modify Makefile to build the C++ binary and run the fan-control test. Modify tests/ with a fixture-based test tests/02-fan-control.sh.
Behavior requirements:
- Discover the MI25 by matching vendor
0x1002and device0x6860under/sys/class/drm/card*/device/, bound to the amdgpu driver, with a hwmon directory exposingpwm1_enable. - Support a
SYSFS_ROOTenvironment-variable override for tests. - At startup, record the kernel release and driver version, then discover the card, retrying while the hwmon node appears.
- Write
1topwm1_enable, thenmanualtopower_dpm_force_performance_level, then5topp_power_profile_mode, then the minimum PWM topwm1. - Loop once per second: read
temp2_input(junction) andtemp3_input(mem), control from the higher value, map to a PWM target via the stage tables and interpolation, ramp up by 10 and down by 6 per second, write the ramp value topwm1, and track the last written value. - Report edge, junction, and mem temperatures plus PWM state every 100 seconds when stable and on every change otherwise.
- On
-EBUSY, keep the last good PWM and retry on the next loop. - On
-ENODEV, exit nonzero. - On
-EINVALfor apwm1write, re-assertpwm1_enable = 1and retry. - Treat a silent no-op write as a control failure by checking read-back.
- Exit nonzero after a discovery timeout at startup.
Support --help, --version, and --check command-line options. The --check option verifies the interface and exits without starting the loop.
TASK-OUTPUT
Implement the files in this order: the gpu interface module, the fan curve module, the main module, the build files, the install script and unit, the Makefile changes, and the test. Run make build and make test and report the results. Update TODO.md and commit the completed work.
TASK-CONTEXT
The reference shell service is at ~/work/amd-mi25-control/mi25-fan-control-actor6.sh. The failed C++ attempt is at ~/work/mi25-fan-service.old/sources/mi25_fan_control.cpp. The plan and failure policy are in documents/06-fan-control-service-plan.md and documents/07-failure-behavior.md. The interface map is in documents/05-mi25-driver-interfaces.md. The old CMakeLists.txt and tests provide a starting point for the build and test structure.
TASK-FILES
sources/gpu_interface.h— newsources/gpu_interface.cpp— newsources/fan_curve.h— newsources/fan_curve.cpp— newsources/mi25_fan_control.cpp— newCMakeLists.txt— new.clang-format— newscripts/install.sh— newscripts/amd-mi25-fanctl.service— newMakefile— modifytests/02-fan-control.sh— newTODO.md— modify