Sur ces machines, la ventilation est réalisée en 3 canaux séparés
- Canal 1 : CPU & RAM : 2 ventilateurs, 1 en façade et 1 à l’arrière en extraction, dont la vitesse est régulée en fonction de la température CPU
- Canal 2 : GPU et cartes d’extensions : 1 ventilateur en façade
- Canal 3 : Alimentation & lecteurs optiques.
Sur mon système, si les canaux 1 et 3 sont gérés correctement par le SMC ( le chip chargé de la gestion du système ), le ventilateur du canal 2 a sa vitesse fixe à 500 tr/min. J’imagine que la cause est à trouver dans mon utilisation peut habituelle de cette machine : un GPU non officiel (AMD R9 380) sous un OS non officiel (Linux).
Pour pallier à ce problème, et effectivement piloter ce ventilateur en fonction de la demande en refroidissement du GPU, j’ai écrit un script bash, qui contrôle ce ventilateur en fonction de la commande PWM du ventilateur du GPU ( attention, à ma connaissance cette information n’est disponible que sur le pilote graphique libre AMD ) :
$ cat /opt/IO_fan_control.sh
#!/bin/bash
BASE_FAN="/sys/devices/platform/applesmc.768/fan2"
GPU_PWM_FILE="/sys/class/drm/card0/device/hwmon/hwmon0/pwm1"
GPU_PWM_MIN=75
GPU_PWM_MAX=250
function setfancontrolmanual()
{
echo $1 > $BASE_FAN"_manual"
if (( $? == 0 ))
then
if (( $1 == 0 ))
then
echo "Returning fan control to SMC"
else
echo "Taking control of fan from SMC"
fi
else
if (( $1 == 0 ))
then
echo "Failed to return fan control to SMC"
exit 1
else
echo "Failed to take control of fan from SMC"
exit 1
fi
fi
}
function abort()
{
setfancontrolmanual 0
exit
}
function checkforroot()
{
if(( $(id -u) != 0 ));
then
echo "Need to be run as root";
exit
fi
}
checkforroot
if [ "$1" == "release" ]; then
setfancontrolmanual 0
exit
fi
trap abort SIGINT
setfancontrolmanual 1
while true
do
INPUT_RPM=$(<$BASE_FAN'_input')
MAX_RPM=$(<$BASE_FAN'_max')
MIN_RPM=$(<$BASE_FAN'_min')
GPU_PWM=$(<$GPU_PWM_FILE)
#compute MAC fan RPM from GPU fan PWM
if (( $GPU_PWM >= $GPU_PWM_MAX )); then
TARGET_RPM=$MAX_RPM
elif (( $GPU_PWM <= $GPU_PWM_MIN )); then
TARGET_RPM=$MIN_RPM
else
TARGET_RPM=$(( ($MAX_RPM - $MIN_RPM) * ( $GPU_PWM - $GPU_PWM_MIN ) / ($GPU_PWM_MAX - $GPU_PWM_MIN) + $MIN_RPM))
fi
#clamp value between MIN_RPM and MAX_RPM
if (( $TARGET_RPM < $MIN_RPM )); then
OUTPUT_RPM=$MIN_RPM
elif (( $TARGET_RPM > $MAX_RPM )); then
OUTPUT_RPM=$MAX_RPM
else
OUTPUT_RPM=$TARGET_RPM
fi
echo $OUTPUT_RPM > $BASE_FAN'_output'
echo 'INPUT_RPM: '$INPUT_RPM' MAX_RPM: '$MAX_RPM' MIN_RPM: '$MIN_RPM' GPU_PWM: '$GPU_PWM' TARGET_RPM: '$TARGET_RPM' OUTPUT_RPM: '$OUTPUT_RPM
sleep 2
done
Les variables GPU_PWM_MIN et GPU_PWM_MAX correspondent respectivement aux 2 valeur PWM à laquelle le ventilateur du canal 2 sera commandé à sa vitesse minimum, et celle où il sera commandé à sa vitesse maximum.
Ce script est exécuté automatiquement au démarrage grâce à systemd
$ cat /etc/systemd/system/system_mac-io-fan-control.service
[Unit]
Description=MacPro IO fan control from GPU temperature
After=systemd-udevd.service
[Service]
ExecStart=/opt/IO_fan_control.sh
Restart=always
StartLimitIntervalSec=10
ExecStopPost=/opt/IO_fan_control.sh release
[Install]
WantedBy=multi-user.target
Il ne reste plus qu’à activer l’unité systemd créé :
$ sudo systemctl enable system_mac-io-fan-control.service
$ sudo systemctl start system_mac-io-fan-control.service
La vitesse du ventilateur du canal 2 est maintenant asservie à celle du GPU, facilitant le refroidissement de ce dernier, et réduisant le niveau sonore de la machine.
Commentaires récents