From b50041c88089ae19b6d1834bc9e7bd45a7b469f9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 8 Sep 2011 13:29:13 +1000 Subject: [PATCH] Allow per-device fan ranges to be set and use them in auto-fan mode. --- README | 7 ++++--- adl.c | 29 +++++++++++++++-------------- main.c | 29 +++++++++++++++++++---------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/README b/README index fe801a8f..65dee2f5 100644 --- a/README +++ b/README @@ -117,7 +117,7 @@ Options for both config file and command line: --failover-only Don't leak work to backup pools when primary pool is lagging --gpu-threads|-g Number of threads per GPU (1 - 10) (default: 2) --gpu-engine GPU engine (over)clock range in Mhz - one value, range and/or comma separated list (e.g. 850-900,900,750-850) ---gpu-fan Set the GPU fan percentage - one value for all or separate by commas for per card. +--gpu-fan GPU fan percentage range - one value, range and/or comma separated list (e.g. 25-85,85,65) --gpu-memclock Set the GPU memory (over)clock in Mhz - one value for all or separate by commas for per card. --gpu-powertune Set the GPU powertune percentage - one value for all or separate by commas for per card. --gpu-vddc Set the GPU voltage in Volts - one value for all or separate by commas for per card. @@ -358,8 +358,9 @@ temperature. By default this is set to 75 degrees C but can be changed with: --temp-target AUTO FAN: -i.e. ---auto-fan +e.g. +--auto-fan (implies 85% upper limit) +--gpu-fan 25-85,65 --auto-fan Fan control in auto fan works off the theory that the minimum possible fan required to maintain an optimal temperature will use less power, make less diff --git a/adl.c b/adl.c index 51be7df6..0dfbde8b 100644 --- a/adl.c +++ b/adl.c @@ -264,6 +264,7 @@ void init_adl(int nDevs) ga->maxspeed = setengine; if (gpus[gpu].min_engine) ga->minspeed = gpus[gpu].min_engine * 100; + ga->managed = true; } if (gpus[gpu].gpu_memclock) { int setmem = gpus[gpu].gpu_memclock * 100; @@ -275,6 +276,7 @@ void init_adl(int nDevs) lpOdPerformanceLevels->aLevels[lev].iMemoryClock = setmem; applog(LOG_INFO, "Setting GPU %d memory clock to %d", gpu, gpus[gpu].gpu_memclock); ADL_Overdrive5_ODPerformanceLevels_Set(iAdapterIndex, lpOdPerformanceLevels); + ga->managed = true; } if (gpus[gpu].gpu_vddc) { int setv = gpus[gpu].gpu_vddc * 1000; @@ -286,16 +288,15 @@ void init_adl(int nDevs) lpOdPerformanceLevels->aLevels[lev].iVddc = setv; applog(LOG_INFO, "Setting GPU %d voltage to %.3f", gpu, gpus[gpu].gpu_vddc); ADL_Overdrive5_ODPerformanceLevels_Set(iAdapterIndex, lpOdPerformanceLevels); + ga->managed = true; } ADL_Overdrive5_ODPerformanceLevels_Get(iAdapterIndex, 0, lpOdPerformanceLevels); ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock; ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock; ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc; - if (ADL_Overdrive5_FanSpeedInfo_Get(iAdapterIndex, 0, &ga->lpFanSpeedInfo) != ADL_OK) { + if (ADL_Overdrive5_FanSpeedInfo_Get(iAdapterIndex, 0, &ga->lpFanSpeedInfo) != ADL_OK) applog(LOG_INFO, "Failed to ADL_Overdrive5_FanSpeedInfo_Get"); - continue; - } /* Save the fanspeed values as defaults in case we reset later */ ADL_Overdrive5_FanSpeed_Get(ga->iAdapterIndex, 0, &ga->DefFanSpeedValue); @@ -306,7 +307,9 @@ void init_adl(int nDevs) ga->lpFanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; applog(LOG_INFO, "Setting GPU %d fan speed to %d%%", gpu, gpus[gpu].gpu_fan); ADL_Overdrive5_FanSpeed_Set(ga->iAdapterIndex, 0, &ga->lpFanSpeedValue); - } + ga->managed = true; + } else + gpus[gpu].gpu_fan = 85; /* Set a nominal upper limit of 85% */ /* Not fatal if powercontrol get fails */ if (ADL_Overdrive5_PowerControl_Get(ga->iAdapterIndex, &ga->iPercentage, &dummy) != ADL_OK) @@ -315,13 +318,8 @@ void init_adl(int nDevs) if (gpus[gpu].gpu_powertune) { ADL_Overdrive5_PowerControl_Set(ga->iAdapterIndex, gpus[gpu].gpu_powertune); ADL_Overdrive5_PowerControl_Get(ga->iAdapterIndex, &ga->iPercentage, &dummy); - } - - /* Flag if the values of this GPU were ever modified to tell us - * we need to reset the values upon exiting */ - if (gpus[gpu].gpu_engine || gpus[gpu].gpu_memclock || gpus[gpu].gpu_vddc || - gpus[gpu].gpu_fan || gpus[gpu].gpu_powertune) ga->managed = true; + } /* Set some default temperatures for autotune when enabled */ ga->targettemp = opt_targettemp; @@ -856,19 +854,22 @@ void gpu_autotune(int gpu, bool *enable) newengine = engine = gpu_engineclock(gpu) * 100; if (temp && fanpercent >= 0 && ga->autofan) { + int top = gpus[gpu].gpu_fan; + int bot = gpus[gpu].min_fan; + if (temp > ga->overtemp && fanpercent < 100) { applog(LOG_WARNING, "Overheat detected, increasing fan to 100%"); newpercent = 100; - } else if (temp > ga->targettemp && fanpercent < 85) { + } else if (temp > ga->targettemp && fanpercent < top) { if (opt_debug) applog(LOG_DEBUG, "Temperature over target, increasing fanspeed"); if (temp > ga->targettemp + opt_hysteresis) newpercent = fanpercent + 10; else newpercent = fanpercent + 5; - if (newpercent > 85) - newpercent = 85; - } else if (fanpercent && temp < ga->targettemp - opt_hysteresis) { + if (newpercent > top) + newpercent = top; + } else if (fanpercent > bot && temp < ga->targettemp - opt_hysteresis) { if (opt_debug) applog(LOG_DEBUG, "Temperature %d degrees below target, decreasing fanspeed", opt_hysteresis); newpercent = fanpercent - 1; diff --git a/main.c b/main.c index ddccb3cf..0ec711ba 100644 --- a/main.c +++ b/main.c @@ -1162,27 +1162,36 @@ static char *set_gpu_engine(char *arg) static char *set_gpu_fan(char *arg) { - int i, val = 0, device = 0; + int i, val1 = 0, val2 = 0, device = 0; char *nextptr; nextptr = strtok(arg, ","); if (nextptr == NULL) return "Invalid parameters for set gpu fan"; - val = atoi(nextptr); - if (val < 0 || val > 100) + get_intrange(nextptr, &val1, &val2); + if (val1 < 0 || val1 > 100 || val2 < 0 || val2 > 100) return "Invalid value passed to set_gpu_fan"; - gpus[device++].gpu_fan = val; + gpus[device].min_fan = val1; + gpus[device].gpu_fan = val2; + device++; while ((nextptr = strtok(NULL, ",")) != NULL) { - val = atoi(nextptr); - if (val < 0 || val > 100) + get_intrange(nextptr, &val1, &val2); + if (val1 < 0 || val1 > 100 || val2 < 0 || val2 > 100) return "Invalid value passed to set_gpu_fan"; - gpus[device++].gpu_fan = val; + gpus[device].min_fan = val1; + gpus[device].gpu_fan = val2; + device++; + } + + if (device == 1) { + for (i = 1; i < 16; i++) { + gpus[i].min_fan = gpus[0].min_fan; + gpus[i].gpu_fan = gpus[0].gpu_fan; + } } - for (i = device; i < 16; i++) - gpus[i].gpu_fan = val; return NULL; } @@ -1337,7 +1346,7 @@ static struct opt_table opt_config_table[] = { "GPU engine (over)clock range in Mhz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"), OPT_WITH_ARG("--gpu-fan", set_gpu_fan, NULL, NULL, - "Set the GPU fan percentage - one value for all or separate by commas for per card."), + "GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"), OPT_WITH_ARG("--gpu-memclock", set_gpu_memclock, NULL, NULL, "Set the GPU memory (over)clock in Mhz - one value for all or separate by commas for per card."),