latest changes
This commit is contained in:
parent
808c898192
commit
f8437d26ea
126
fancontrol.pl
126
fancontrol.pl
@ -3,25 +3,9 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
use List::Util qw[min max];
|
use List::Util qw[min max];
|
||||||
|
|
||||||
# This script controls SuperMicro server fan speeds via IPMI in response to CPU and SYS temperatures.
|
my $min_temp_change = 3; # °C minimum change to actually cause a fan speed update
|
||||||
# A fork of https://github.com/missmah/ipmi_tools by Layla Mah <layla@insightfulvr.com>
|
my $min_power_change = 30; # W, minimum change to do something
|
||||||
|
my $seconds_to_sleep = 4; # Number of seconds to sleep between update loops
|
||||||
# Sensor treshold reset to allow slower fans
|
|
||||||
|
|
||||||
`ipmitool sensor thresh FANA lower 0 100 200`;
|
|
||||||
`ipmitool sensor thresh FANB lower 0 100 200`;
|
|
||||||
`ipmitool sensor thresh FAN1 lower 0 100 200`;
|
|
||||||
`ipmitool sensor thresh FAN2 lower 0 100 200`;
|
|
||||||
`ipmitool sensor thresh FAN3 lower 0 100 200`;
|
|
||||||
`ipmitool sensor thresh FAN4 lower 0 100 200`;
|
|
||||||
`ipmitool sensor thresh FAN5 lower 0 100 200`;
|
|
||||||
|
|
||||||
# cache SDR data for faster access
|
|
||||||
`rm /opt/ipmi-cache.sdr`;
|
|
||||||
`while ipmitool sdr dump /opt/ipmi-cache.sdr; [ $? != 0 ]; do sleep 2; done`;
|
|
||||||
|
|
||||||
my $min_temp_change = 2; # °C minimum change to actually cause a fan speed update
|
|
||||||
my $seconds_to_sleep = 2; # Number of seconds to sleep between update loops
|
|
||||||
|
|
||||||
# 0x64 = 100, 0x00 = 0.
|
# 0x64 = 100, 0x00 = 0.
|
||||||
# CPU Temp -> Fan Speed Mappings
|
# CPU Temp -> Fan Speed Mappings
|
||||||
@ -31,58 +15,51 @@ my %cpu_temp_to_fan_speed;
|
|||||||
$cpu_temp_to_fan_speed{70} = 0x56;
|
$cpu_temp_to_fan_speed{70} = 0x56;
|
||||||
$cpu_temp_to_fan_speed{65} = 0x52;
|
$cpu_temp_to_fan_speed{65} = 0x52;
|
||||||
$cpu_temp_to_fan_speed{60} = 0x48;
|
$cpu_temp_to_fan_speed{60} = 0x48;
|
||||||
$cpu_temp_to_fan_speed{55} = 0x46;
|
$cpu_temp_to_fan_speed{55} = 0x44;
|
||||||
$cpu_temp_to_fan_speed{50} = 0x42;
|
$cpu_temp_to_fan_speed{50} = 0x40;
|
||||||
$cpu_temp_to_fan_speed{45} = 0x40;
|
$cpu_temp_to_fan_speed{45} = 0x36;
|
||||||
$cpu_temp_to_fan_speed{40} = 0x36;
|
$cpu_temp_to_fan_speed{40} = 0x32;
|
||||||
$cpu_temp_to_fan_speed{35} = 0x34;
|
$cpu_temp_to_fan_speed{35} = 0x30;
|
||||||
$cpu_temp_to_fan_speed{30} = 0x32;
|
$cpu_temp_to_fan_speed{30} = 0x28;
|
||||||
|
|
||||||
# SYS Temp -> Fan Speed Mappings
|
# SYS Power -> Fan Speed Mappings
|
||||||
my %sys_temp_to_fan_speed;
|
my %sys_power_to_fan_speed;
|
||||||
$sys_temp_to_fan_speed{66} = 0x64;
|
$sys_power_to_fan_speed{650} = 0x64;
|
||||||
$sys_temp_to_fan_speed{60} = 0x60;
|
$sys_power_to_fan_speed{575} = 0x60;
|
||||||
$sys_temp_to_fan_speed{57} = 0x42;
|
$sys_power_to_fan_speed{525} = 0x56;
|
||||||
$sys_temp_to_fan_speed{55} = 0x40;
|
$sys_power_to_fan_speed{500} = 0x54;
|
||||||
$sys_temp_to_fan_speed{52} = 0x36;
|
$sys_power_to_fan_speed{475} = 0x52;
|
||||||
$sys_temp_to_fan_speed{50} = 0x34;
|
$sys_power_to_fan_speed{450} = 0x50;
|
||||||
$sys_temp_to_fan_speed{47} = 0x32;
|
$sys_power_to_fan_speed{425} = 0x48;
|
||||||
$sys_temp_to_fan_speed{45} = 0x30;
|
$sys_power_to_fan_speed{400} = 0x46;
|
||||||
$sys_temp_to_fan_speed{30} = 0x28;
|
$sys_power_to_fan_speed{375} = 0x44;
|
||||||
|
$sys_power_to_fan_speed{350} = 0x42;
|
||||||
|
$sys_power_to_fan_speed{325} = 0x40;
|
||||||
|
$sys_power_to_fan_speed{300} = 0x36;
|
||||||
|
$sys_power_to_fan_speed{275} = 0x34;
|
||||||
|
$sys_power_to_fan_speed{250} = 0x32;
|
||||||
|
$sys_power_to_fan_speed{225} = 0x30;
|
||||||
|
$sys_power_to_fan_speed{200} = 0x28;
|
||||||
|
$sys_power_to_fan_speed{175} = 0x26;
|
||||||
|
$sys_power_to_fan_speed{150} = 0x24;
|
||||||
|
$sys_power_to_fan_speed{125} = 0x22;
|
||||||
|
$sys_power_to_fan_speed{100} = 0x20;
|
||||||
|
|
||||||
my $g_current_sys_fan_duty_cycle = 0;
|
my $g_current_sys_fan_duty_cycle = 0;
|
||||||
my $g_current_cpu_fan_duty_cycle = 0;
|
my $g_current_cpu_fan_duty_cycle = 0;
|
||||||
my $g_current_sys_temp = 0;
|
|
||||||
my $g_current_cpu_temp = 0;
|
my $g_current_cpu_temp = 0;
|
||||||
|
my $g_current_sys_power = 0;
|
||||||
my $g_last_set_cpu_temp = 0;
|
my $g_last_set_cpu_temp = 0;
|
||||||
my $g_last_set_sys_temp = 0;
|
my $g_last_set_sys_power = 0;
|
||||||
|
|
||||||
sub UpdateFanSpeed {
|
sub UpdateFanSpeed {
|
||||||
# Gather statistics for fan speed and CPU Temp
|
my $current_cpu_temp = `sensors \$(sensors | grep k10temp) | grep 'Tctl:' | cut -c 16-17 | tr -d '\n'`;
|
||||||
my $ipmi_output = `ipmitool sdr list full -S /opt/ipmi-cache.sdr`;
|
my $current_sys_power = `sensors \$(sensors | grep corsairpsu) | grep 'power total:' | cut -c 14-16 | tr -d '\n'`;
|
||||||
my @vals = split( "\n", $ipmi_output );
|
|
||||||
|
|
||||||
my $current_cpu_temp = 0;
|
|
||||||
my $current_sys_temp = 0;
|
|
||||||
my $cpu_temp_difference = 0;
|
my $cpu_temp_difference = 0;
|
||||||
my $sys_temp_difference = 0;
|
my $sys_power_difference = 0;
|
||||||
|
|
||||||
foreach my $value (@vals) {
|
|
||||||
|
|
||||||
if( $value =~ /^(CPU\sTemp).*\s(\d+)\s.*degrees\sC.*/gi ) {
|
|
||||||
my $cpu_temp = $2;
|
|
||||||
$current_cpu_temp = max( $cpu_temp, $current_cpu_temp );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( $value =~ /^(System\sTemp).*\s(\d+)\s.*degrees\sC.*/gi ) {
|
|
||||||
my $sys_temp = $2;
|
|
||||||
$current_sys_temp = max( $sys_temp, $current_sys_temp );
|
|
||||||
}
|
|
||||||
|
|
||||||
} # foreach my $value (@vals)
|
|
||||||
|
|
||||||
$g_current_cpu_temp = $current_cpu_temp;
|
$g_current_cpu_temp = $current_cpu_temp;
|
||||||
$g_current_sys_temp = $current_sys_temp;
|
$g_current_sys_power = $current_sys_power;
|
||||||
|
|
||||||
my $desired_cpu_fan_speed = 0x0;
|
my $desired_cpu_fan_speed = 0x0;
|
||||||
my $desired_sys_fan_speed = 0x0;
|
my $desired_sys_fan_speed = 0x0;
|
||||||
@ -90,20 +67,15 @@ sub UpdateFanSpeed {
|
|||||||
my @cpu_temps = keys %cpu_temp_to_fan_speed;
|
my @cpu_temps = keys %cpu_temp_to_fan_speed;
|
||||||
for my $cpu_temp (@cpu_temps) {
|
for my $cpu_temp (@cpu_temps) {
|
||||||
if( $current_cpu_temp >= $cpu_temp ) {
|
if( $current_cpu_temp >= $cpu_temp ) {
|
||||||
# If the current CPU temperature is higher than the temperature enumerated by this hash lookup,
|
|
||||||
# Then set the desired fan speed (if our value is larger than the existing value)
|
|
||||||
$desired_cpu_fan_speed = max( $cpu_temp_to_fan_speed{ $cpu_temp }, $desired_cpu_fan_speed );
|
$desired_cpu_fan_speed = max( $cpu_temp_to_fan_speed{ $cpu_temp }, $desired_cpu_fan_speed );
|
||||||
# print "The fan speed setting for CPU Temp $cpu_temp *C is $cpu_temp_to_fan_speed{$cpu_temp} % duty cycle\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my @sys_temps = keys %sys_temp_to_fan_speed;
|
my @sys_powers = keys %sys_power_to_fan_speed;
|
||||||
for my $sys_temp (@sys_temps) {
|
for my $sys_power (@sys_powers) {
|
||||||
if( $current_sys_temp >= $sys_temp ) {
|
#for my $sys_temp (@sys_temps) {
|
||||||
# If the current gPU temperature is higher than the temperature enumerated by this hash lookup,
|
if( $current_sys_power >= $sys_power ) {
|
||||||
# Then set the desired fan speed (if our value is larger than the existing value)
|
$desired_sys_fan_speed = max( $sys_power_to_fan_speed{ $sys_power }, $desired_sys_fan_speed );
|
||||||
$desired_sys_fan_speed = max( $sys_temp_to_fan_speed{ $sys_temp }, $desired_sys_fan_speed );
|
|
||||||
# print "The fan speed setting for GPU Temp $sys_temp *C is $sys_temp_to_fan_speed{$sys_temp} % duty cycle\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,15 +90,15 @@ sub UpdateFanSpeed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$cpu_temp_difference = $g_current_cpu_temp - $g_last_set_cpu_temp;
|
$cpu_temp_difference = $g_current_cpu_temp - $g_last_set_cpu_temp;
|
||||||
$sys_temp_difference = $g_current_sys_temp - $g_last_set_sys_temp;
|
$sys_power_difference = $g_current_sys_power - $g_last_set_sys_power;
|
||||||
|
|
||||||
if( (abs $sys_temp_difference) > $min_temp_change ) {
|
if( (abs $sys_power_difference) > $min_power_change ) {
|
||||||
print "(SYS) Temp change of $sys_temp_difference °C, current $g_current_sys_temp °C, fan speed set to $desired_sys_fan_speed %\n";
|
print "(SYS) Power change of $sys_power_difference W, current $g_current_sys_power W, fan speed set to $desired_sys_fan_speed %\n";
|
||||||
|
|
||||||
$g_last_set_sys_temp = $g_current_sys_temp;
|
$g_last_set_sys_power = $g_current_sys_power;
|
||||||
$g_current_sys_fan_duty_cycle = $desired_sys_fan_speed;
|
$g_current_sys_fan_duty_cycle = $desired_sys_fan_speed;
|
||||||
|
|
||||||
`ipmitool raw 0x30 0x70 0x66 0x01 0x01 $desired_sys_fan_speed`;
|
`ipmitool raw 0x30 0x70 0x66 0x01 0x00 $desired_sys_fan_speed`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (abs $cpu_temp_difference) > $min_temp_change ) {
|
if( (abs $cpu_temp_difference) > $min_temp_change ) {
|
||||||
@ -135,7 +107,7 @@ sub UpdateFanSpeed {
|
|||||||
$g_last_set_cpu_temp = $g_current_cpu_temp;
|
$g_last_set_cpu_temp = $g_current_cpu_temp;
|
||||||
$g_current_cpu_fan_duty_cycle = $desired_cpu_fan_speed;
|
$g_current_cpu_fan_duty_cycle = $desired_cpu_fan_speed;
|
||||||
|
|
||||||
`ipmitool raw 0x30 0x70 0x66 0x01 0x00 $desired_cpu_fan_speed`;
|
`ipmitool raw 0x30 0x70 0x66 0x01 0x01 $desired_cpu_fan_speed`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -144,8 +116,6 @@ print "Setting Fan mode to FULL SPEED.\n";
|
|||||||
`ipmitool raw 0x30 0x45 0x01 0x01`;
|
`ipmitool raw 0x30 0x45 0x01 0x01`;
|
||||||
|
|
||||||
while( 1 ) {
|
while( 1 ) {
|
||||||
#print "Calling UpdateFanSpeed()...\n";
|
|
||||||
UpdateFanSpeed();
|
UpdateFanSpeed();
|
||||||
#print "Update Complete - going to sleep for $seconds_to_sleep seconds...\n";
|
|
||||||
sleep $seconds_to_sleep;
|
sleep $seconds_to_sleep;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user