@ -94,7 +94,7 @@ static inline void unlock_adl(void)
@@ -94,7 +94,7 @@ static inline void unlock_adl(void)
void init_adl ( int nDevs )
{
int i , j , devices = 0 , last_adapter = - 1 , gpu = 0 , dummy = 0 ;
int i , j , devices = 0 , last_adapter = - 1 , gpu = 0 , dummy = 0 , prev_id = - 1 , prev_gpu = - 1 ;
# if defined (LINUX)
hDLL = dlopen ( " libatiadlxx.so " , RTLD_LAZY | RTLD_GLOBAL ) ;
@ -230,9 +230,11 @@ void init_adl(int nDevs)
@@ -230,9 +230,11 @@ void init_adl(int nDevs)
/* From here on we know this device is a discrete device and
* should support ADL */
ga = & gpus [ gpu ] . adl ;
ga - > gpu = gpu ;
ga - > iAdapterIndex = iAdapterIndex ;
ga - > lpAdapterID = lpAdapterID ;
ga - > DefPerfLev = NULL ;
ga - > twin = NULL ;
ga - > lpThermalControllerInfo . iSize = sizeof ( ADLThermalControllerInfo ) ;
if ( ADL_Overdrive5_ThermalDevices_Enum ( iAdapterIndex , 0 , & ga - > lpThermalControllerInfo ) ! = ADL_OK )
@ -306,8 +308,21 @@ void init_adl(int nDevs)
@@ -306,8 +308,21 @@ void init_adl(int nDevs)
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 " ) ;
/* This is our opportunity to detect the 2nd GPU in a
* dual GPU device with a fan controller only on the
* first */
if ( prev_id > = 0 & &
! strcmp ( lpInfo [ i ] . strAdapterName , lpInfo [ prev_id ] . strAdapterName ) & &
lpInfo [ i ] . iBusNumber = = lpInfo [ prev_id ] . iBusNumber + 1 & &
gpus [ prev_gpu ] . adl . has_fanspeed ) {
applog ( LOG_INFO , " 2nd GPU of dual card device detected " ) ;
ga - > twin = & gpus [ prev_gpu ] . adl ;
gpus [ prev_gpu ] . adl . twin = ga ;
}
} else
ga - > has_fanspeed = true ;
/* Save the fanspeed values as defaults in case we reset later */
ADL_Overdrive5_FanSpeed_Get ( ga - > iAdapterIndex , 0 , & ga - > DefFanSpeedValue ) ;
@ -343,6 +358,9 @@ void init_adl(int nDevs)
@@ -343,6 +358,9 @@ void init_adl(int nDevs)
ga - > managed = true ;
}
ga - > lasttemp = __gpu_temp ( ga ) ;
prev_id = i ;
prev_gpu = gpu ;
}
}
@ -465,6 +483,9 @@ int gpu_activity(int gpu)
@@ -465,6 +483,9 @@ int gpu_activity(int gpu)
static inline int __gpu_fanspeed ( struct gpu_adl * ga )
{
if ( ! ga - > has_fanspeed & & ga - > twin )
return __gpu_fanspeed ( ga - > twin ) ;
if ( ! ( ga - > lpFanSpeedInfo . iFlags & ADL_DL_FANCTRL_SUPPORTS_RPM_READ ) )
return - 1 ;
ga - > lpFanSpeedValue . iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_RPM ;
@ -488,8 +509,11 @@ int gpu_fanspeed(int gpu)
@@ -488,8 +509,11 @@ int gpu_fanspeed(int gpu)
return ret ;
}
static inline int __gpu_fanpercent ( struct gpu_adl * ga )
static int __gpu_fanpercent ( struct gpu_adl * ga )
{
if ( ! ga - > has_fanspeed & & ga - > twin )
return __gpu_fanpercent ( ga - > twin ) ;
if ( ! ( ga - > lpFanSpeedInfo . iFlags & ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ ) )
return - 1 ;
ga - > lpFanSpeedValue . iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT ;
@ -819,9 +843,48 @@ static int set_powertune(int gpu, int iPercentage)
@@ -819,9 +843,48 @@ static int set_powertune(int gpu, int iPercentage)
return ret ;
}
static void fan_autotune ( int gpu , int temp , int fanpercent , bool * fan_optimal )
{
struct cgpu_info * cgpu = & gpus [ gpu ] ;
struct gpu_adl * ga = & cgpu - > adl ;
int top = gpus [ gpu ] . gpu_fan ;
int bot = gpus [ gpu ] . min_fan ;
int newpercent = fanpercent ;
int iMin = 0 , iMax = 100 ;
get_fanrange ( gpu , & iMin , & iMax ) ;
if ( temp > ga - > overtemp & & fanpercent < iMax ) {
applog ( LOG_WARNING , " Overheat detected on GPU %d, increasing fan to 100% " , gpu ) ;
newpercent = iMax ;
} else if ( temp > ga - > targettemp & & fanpercent < top & & temp > = ga - > lasttemp ) {
if ( opt_debug )
applog ( LOG_DEBUG , " Temperature over target, increasing fanspeed " ) ;
if ( temp > ga - > targettemp + opt_hysteresis )
newpercent = ga - > targetfan + 10 ;
else
newpercent = ga - > targetfan + 5 ;
if ( newpercent > top )
newpercent = top ;
} else if ( fanpercent > bot & & temp < ga - > targettemp - opt_hysteresis & & temp < = ga - > lasttemp ) {
if ( opt_debug )
applog ( LOG_DEBUG , " Temperature %d degrees below target, decreasing fanspeed " , opt_hysteresis ) ;
newpercent = ga - > targetfan - 1 ;
}
if ( newpercent > iMax )
newpercent = iMax ;
else if ( newpercent < iMin )
newpercent = iMin ;
if ( newpercent ! = fanpercent ) {
fan_optimal = false ;
applog ( LOG_INFO , " Setting GPU %d fan percentage to %d " , gpu , newpercent ) ;
set_fanspeed ( gpu , newpercent ) ;
}
}
void gpu_autotune ( int gpu , bool * enable )
{
int temp , fanpercent , engine , newpercent , newengine ;
int temp , fanpercent , engine , newengine , twintemp ;
bool fan_optimal = true ;
struct cgpu_info * cgpu ;
struct gpu_adl * ga ;
@ -832,43 +895,28 @@ void gpu_autotune(int gpu, bool *enable)
@@ -832,43 +895,28 @@ void gpu_autotune(int gpu, bool *enable)
lock_adl ( ) ;
ADL_Overdrive5_CurrentActivity_Get ( ga - > iAdapterIndex , & ga - > lpActivity ) ;
temp = __gpu_temp ( ga ) ;
newpercent = fanpercent = __gpu_fanpercent ( ga ) ;
if ( ga - > twin )
twintemp = __gpu_temp ( ga - > twin ) ;
fanpercent = __gpu_fanpercent ( ga ) ;
unlock_adl ( ) ;
newengine = engine = gpu_engineclock ( gpu ) * 100 ;
if ( temp & & fanpercent > = 0 & & ga - > autofan ) {
int top = gpus [ gpu ] . gpu_fan ;
int bot = gpus [ gpu ] . min_fan ;
int iMin = 0 , iMax = 100 ;
get_fanrange ( gpu , & iMin , & iMax ) ;
if ( temp > ga - > overtemp & & fanpercent < iMax ) {
applog ( LOG_WARNING , " Overheat detected on GPU %d, increasing fan to 100% " , gpu ) ;
newpercent = iMax ;
} else if ( temp > ga - > targettemp & & fanpercent < top & & temp > = ga - > lasttemp ) {
if ( opt_debug )
applog ( LOG_DEBUG , " Temperature over target, increasing fanspeed " ) ;
if ( temp > ga - > targettemp + opt_hysteresis )
newpercent = ga - > targetfan + 10 ;
else
newpercent = ga - > targetfan + 5 ;
if ( newpercent > top )
newpercent = top ;
} else if ( fanpercent > bot & & temp < ga - > targettemp - opt_hysteresis & & temp < = ga - > lasttemp ) {
if ( opt_debug )
applog ( LOG_DEBUG , " Temperature %d degrees below target, decreasing fanspeed " , opt_hysteresis ) ;
newpercent = ga - > targetfan - 1 ;
}
if ( ! ga - > twin )
fan_autotune ( gpu , temp , fanpercent , & fan_optimal ) ;
else {
int hightemp , fan_gpu ;
if ( newpercent > iMax )
newpercent = iMax ;
else if ( newpercent < iMin )
newpercent = iMin ;
if ( newpercent ! = fanpercent ) {
fan_optimal = false ;
applog ( LOG_INFO , " Setting GPU %d fan percentage to %d " , gpu , newpercent ) ;
set_fanspeed ( gpu , newpercent ) ;
if ( twintemp > temp )
hightemp = twintemp ;
else
hightemp = temp ;
if ( ga - > has_fanspeed )
fan_gpu = gpu ;
else
fan_gpu = ga - > twin - > gpu ;
fan_autotune ( fan_gpu , hightemp , fanpercent , & fan_optimal ) ;
}
}