Merge pull request #495 from jostar-yang/as7726_1128

Add as7726-32x thermal policy
This commit is contained in:
Jeffrey Townsend
2018-12-26 09:08:13 -08:00
committed by GitHub
3 changed files with 224 additions and 341 deletions

View File

@@ -53,7 +53,6 @@ static struct accton_as7726_32x_led_data *ledctl = NULL;
#define LED_TYPE_DIAG_REG_MASK (0x3)
#define LED_MODE_DIAG_GREEN_VALUE (0x02)
#define LED_MODE_DIAG_RED_VALUE (0x01)
#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/
#define LED_MODE_DIAG_OFF_VALUE (0x03)
@@ -102,11 +101,11 @@ struct led_type_mode {
static struct led_type_mode led_type_mode_data[] = {
{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ON_VALUE},
{LED_TYPE_LOC, LED_MODE_BLUE, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ON_VALUE},
{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
{LED_TYPE_DIAG, LED_MODE_RED, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_RED_VALUE},
{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE},
};
@@ -428,6 +427,6 @@ static void __exit accton_as7726_32x_led_exit(void)
module_init(accton_as7726_32x_led_init);
module_exit(accton_as7726_32x_led_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_AUTHOR("Jostar Yang <jostar_yang@accton.com.tw>");
MODULE_DESCRIPTION("accton_as7726_32x_led driver");
MODULE_LICENSE("GPL");

View File

@@ -77,7 +77,6 @@ typedef struct led_light_mode_map {
led_light_mode_map_t led_map[] = {
{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE},
{LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED},
{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_LOC, LED_MODE_BLUE, ONLP_LED_MODE_BLUE},
@@ -105,7 +104,7 @@ static onlp_led_info_t linfo[] =
{
{ ONLP_LED_ID_CREATE(LED_DIAG), "LED 1 (DIAG LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED,
},
{
{ ONLP_LED_ID_CREATE(LED_LOC), "LED 2 (LOC LED)", 0 },

View File

@@ -36,22 +36,12 @@
#include "x86_64_accton_as7726_32x_int.h"
#include "x86_64_accton_as7726_32x_log.h"
#define NUM_OF_FAN_ON_MAIN_BROAD 6
#define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/"
#define NUM_OF_CPLD 3
#define FAN_DUTY_CYCLE_MAX (100)
#define FAN_DUTY_CYCLE_DEFAULT (32)
#define FAN_DUTY_PLUS_FOR_DIR (13)
/* Note, all chassis fans share 1 single duty setting.
* Here use fan 1 to represent global fan duty value.*/
#define FAN_ID_FOR_SET_FAN_DUTY (1)
#define CELSIUS_RECORD_NUMBER (2) /*Must >= 2*/
#define FAN_DUTY_CYCLE_DEFAULT (38)
typedef struct fan_ctrl_policy {
int duty_cycle; /* In percetage */
int step_up_thermal; /* In mini-Celsius */
int step_dn_thermal; /* In mini-Celsius */
} fan_ctrl_policy_t;
static char arr_cplddev_name[NUM_OF_CPLD][10] =
{
@@ -136,351 +126,244 @@ onlp_sysi_platform_info_free(onlp_platform_info_t* pi)
aim_free(pi->cpld_versions);
}
/* Thermal plan:
* $TMP = (CPU_core + LM75_1+ LM75_2 + LM75_3 + LM75_4)/5
* 1. If any FAN failed, set all the other fans as full speed, 100%.
* 2. If any sensor is high than 45 degrees, set fan speed to duty 62.5%.
* 3. If any sensor is high than 50 degrees, set fan speed to duty 100%.
* 4. When $TMP >= 40 C, set fan speed to duty 62.5%.
* 5. When $TMP >= 45 C, set fan speed to duty 100%.
* 6. When $TMP < 35 C, set fan speed to duty 31.25%.
* 7. Direction factor, when B2F, duty + 12.5%.
*
* Note, all chassis fans share 1 single duty setting.
/*
* Air Flow Front to Back :
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08)
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E)
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system
* One Fan fail : Change Fan speed to 100%(0x0E)
* Air Flow Back to Front :
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08)
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E)
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message
* (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system
* One Fan fail: Change Fan speed to 100%(0x0E)
*/
fan_ctrl_policy_t fan_ctrl_policy_avg[] = {
{FAN_DUTY_CYCLE_MAX , 45000, INT_MIN},
{63 , 40000, INT_MIN},
{32 , INT_MAX, 35000},
};
fan_ctrl_policy_t fan_ctrl_policy_single[] = {
{FAN_DUTY_CYCLE_MAX , 50000, INT_MIN},
{63 , 45000, INT_MIN},
};
struct fan_control_data_s {
typedef struct fan_ctrl_policy {
int duty_cycle;
int dir_plus;
int mc_avg_pre[CELSIUS_RECORD_NUMBER];
int mc_high_pre[CELSIUS_RECORD_NUMBER];
int pwm;
int temp_down; /* The boundary temperature to down adjust fan speed */
int temp_up; /* The boundary temperature to up adjust fan speed */
int state;
} fan_ctrl_policy_t;
} fan_control_data_pre =
enum
{
.duty_cycle = FAN_DUTY_CYCLE_DEFAULT,
.dir_plus = 0,
.mc_avg_pre = {INT_MIN+1, INT_MIN}, /*init as thermal rising to avoid full speed.*/
.mc_high_pre = {INT_MIN+1, INT_MIN}, /*init as thermal rising to avoid full speed.*/
LEVEL_FAN_DEF=0,
LEVEL_FAN_MID,
LEVEL_FAN_MAX,
LEVEL_TEMP_HIGH,
LEVEL_TEMP_CRITICAL
};
static int
sysi_check_fan(uint32_t *fan_dir){
int i, present;
fan_ctrl_policy_t fan_thermal_policy_f2b[] = {
{38, 0x4, 0, 38000, LEVEL_FAN_DEF},
{63, 0x8, 38000, 46000, LEVEL_FAN_MID},
{100, 0xE, 46000, 58000, LEVEL_FAN_MAX},
{100, 0xE, 58000, 66000, LEVEL_TEMP_HIGH},
{100, 0xE, 66000, 200000, LEVEL_TEMP_CRITICAL}
};
for (i = 1; i <= CHASSIS_FAN_COUNT; i++)
fan_ctrl_policy_t fan_thermal_policy_b2f[] = {
{38, 0x4, 0, 34000, LEVEL_FAN_DEF},
{63, 0x8, 34000, 44000, LEVEL_FAN_MID},
{100, 0xE, 44000, 59000, LEVEL_FAN_MAX},
{100, 0xE, 59000, 67000, LEVEL_TEMP_HIGH},
{100, 0xE, 67000, 200000, LEVEL_TEMP_CRITICAL}
};
#define FAN_SPEED_CTRL_PATH "/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage"
#define FAN_DIRECTION_PATH "/sys/bus/i2c/devices/54-0066/fan1_direction"
static int fan_state=LEVEL_FAN_DEF;
static int alarm_state = 0; /* 0->default or clear, 1-->alarm detect */
static int fan_fail = 0;
int onlp_sysi_platform_manage_fans(void)
{
int i=0, ori_state=LEVEL_FAN_DEF, current_state=LEVEL_FAN_DEF;
int fd, len, value=1;
int cur_duty_cycle, new_duty_cycle, temp=0;
onlp_thermal_info_t thermal_4, thermal_5;
char buf[10] = {0};
fan_ctrl_policy_t *fan_thermal_policy;
/* Get fan direction
*/
if (onlp_file_read_int(&value, FAN_DIRECTION_PATH) < 0) {
AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", FAN_DIRECTION_PATH);
}
if(value==1)
fan_thermal_policy=fan_thermal_policy_f2b;
else
fan_thermal_policy=fan_thermal_policy_b2f;
/* Get current temperature
*/
if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(4), &thermal_4) != ONLP_STATUS_OK )
{
AIM_LOG_ERROR("Unable to read thermal status, set fans to 75% speed");
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fan_thermal_policy[LEVEL_FAN_MID].duty_cycle);
return ONLP_STATUS_E_INTERNAL;
}
if(onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(5), &thermal_5) != ONLP_STATUS_OK)
{
AIM_LOG_ERROR("Unable to read thermal status, set fans to 75% speed");
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fan_thermal_policy[LEVEL_FAN_MID].duty_cycle);
return ONLP_STATUS_E_INTERNAL;
}
temp = (thermal_4.mcelsius + thermal_5.mcelsius)/2;
/* Get current fan pwm percent
*/
fd = open(FAN_SPEED_CTRL_PATH, O_RDONLY);
if (fd == -1){
AIM_LOG_ERROR("Unable to open fan speed control node (%s)", FAN_SPEED_CTRL_PATH);
return ONLP_STATUS_E_INTERNAL;
}
len = read(fd, buf, sizeof(buf));
close(fd);
if (len <= 0) {
AIM_LOG_ERROR("Unable to read fan speed from (%s)", FAN_SPEED_CTRL_PATH);
return ONLP_STATUS_E_INTERNAL;
}
cur_duty_cycle = atoi(buf);
ori_state=fan_state;
/* Inpunt temp to get theraml_polyc state and new pwm percent. */
for(i=0; i < sizeof(fan_thermal_policy_f2b)/sizeof(fan_ctrl_policy_t); i++)
{
if (temp > fan_thermal_policy[i].temp_down)
{
if (temp <= fan_thermal_policy[i].temp_up)
{
current_state =i;
}
}
}
if(current_state > LEVEL_TEMP_CRITICAL || current_state < LEVEL_FAN_DEF)
{
AIM_LOG_ERROR("onlp_sysi_platform_manage_fans get error current_state\n");
return 0;
}
/* Decision 3: Decide new fan pwm percent.
*/
if (fan_fail==0 &&cur_duty_cycle!=fan_thermal_policy[current_state].duty_cycle)
{
new_duty_cycle = fan_thermal_policy[current_state].duty_cycle;
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), new_duty_cycle);
}
/* Get each fan status
*/
for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++)
{
onlp_fan_info_t fan_info;
if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i);
return ONLP_STATUS_E_INTERNAL;
AIM_LOG_ERROR("Unable to get fan(%d) status, try to set the other fans as full speed\r\n", i);
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX);
fan_fail=1;
break;
}
present = fan_info.status & ONLP_FAN_STATUS_PRESENT;
if ((fan_info.status & ONLP_FAN_STATUS_FAILED) || !present) {
AIM_LOG_WARN("Fan(%d) is not working, set the other fans as full speed\r\n", i);
int ret = onlp_fani_percentage_set(
ONLP_FAN_ID_CREATE(FAN_ID_FOR_SET_FAN_DUTY), FAN_DUTY_CYCLE_MAX);
if (ret != ONLP_STATUS_OK)
return ret;
else
return ONLP_STATUS_E_MISSING;
}
/* Get fan direction (Only get the first one since all fan direction are the same)
/* Decision 1: Set fan as full speed if any fan is failed.
*/
if (i == 1) {
*fan_dir = fan_info.status & (ONLP_FAN_STATUS_F2B|ONLP_FAN_STATUS_B2F);
}
}
return ONLP_STATUS_OK;
}
static int
sysi_get_fan_duty(int *cur_duty_cycle){
int fd, len;
char buf[10] = {0};
char *node = FAN_NODE(fan_duty_cycle_percentage);
/* Get current fan duty*/
fd = open(node, O_RDONLY);
if (fd == -1){
AIM_LOG_ERROR("Unable to open fan speed control node (%s)", node);
return ONLP_STATUS_E_INTERNAL;
}
len = read(fd, buf, sizeof(buf));
close(fd);
if (len <= 0) {
AIM_LOG_ERROR("Unable to read fan speed from (%s)", node);
return ONLP_STATUS_E_INTERNAL;
}
*cur_duty_cycle = atoi(buf);
return ONLP_STATUS_OK;
}
static int
sysi_get_thermal_sum(int *mcelsius){
onlp_thermal_info_t thermal_info;
int i;
*mcelsius = 0;
for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) {
if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal_info)
!= ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read thermal status");
return ONLP_STATUS_E_INTERNAL;
if (fan_info.status & ONLP_FAN_STATUS_FAILED || !(fan_info.status & ONLP_FAN_STATUS_PRESENT)) {
AIM_LOG_ERROR("Fan(%d) is not working, set the other fans as full speed\r\n", i);
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX);
fan_fail=1;
break;
}
*mcelsius += thermal_info.mcelsius;
}
DEBUG_PRINT("Thermal %d: %d \n ", i, thermal_info.mcelsius);
if(current_state!=ori_state)
{
fan_state=current_state;
switch (ori_state)
{
case LEVEL_FAN_DEF:
if(current_state==LEVEL_TEMP_HIGH)
{
if(alarm_state==0)
{
AIM_SYSLOG_WARN("Temperature high", "Temperature high","Alarm for temperature high is detected");
alarm_state=1;
}
}
if(current_state==LEVEL_TEMP_CRITICAL)
{
AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical", "Alarm for temperature critical is detected, reboot DUT");
system("sync;sync;sync");
system("reboot");
}
break;
case LEVEL_FAN_MID:
if(current_state==LEVEL_TEMP_HIGH)
{
if(alarm_state==0)
{
AIM_SYSLOG_WARN("Temperature high", "Temperature high","Alarm for temperature high is detected");
alarm_state=1;
}
}
if(current_state==LEVEL_TEMP_CRITICAL)
{
AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical", "Alarm for temperature critical is detected, reboot DUT");
system("sync;sync;sync");
system("reboot");
}
break;
case LEVEL_FAN_MAX:
if(current_state==LEVEL_TEMP_HIGH)
{
if(alarm_state==0)
{
AIM_SYSLOG_WARN("Temperature high", "Temperature high","Alarm for temperature high is detected");
alarm_state=1;
}
}
if(current_state==LEVEL_TEMP_CRITICAL)
{
AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical ", "Alarm for temperature critical is detected, reboot DUT");
system("sync;sync;sync");
system("reboot");
}
break;
case LEVEL_TEMP_HIGH:
if(current_state==LEVEL_TEMP_CRITICAL)
{
AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical ", "Alarm for temperature critical is detected, reboot DUT");
system("sync;sync;sync");
system("reboot");
}
break;
case LEVEL_TEMP_CRITICAL:
break;
default:
AIM_SYSLOG_WARN("onlp_sysi_platform_manage_fans abnormal state", "onlp_sysi_platform_manage_fans abnormal state", "onlp_sysi_platform_manage_fans at abnormal state\n");
break;
}
}
return ONLP_STATUS_OK;
}
static int
sysi_get_highest_thermal(int *mcelsius){
onlp_thermal_info_t thermal_info;
int i, highest;
highest = 0;
for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) {
if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal_info)
!= ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read thermal status");
return ONLP_STATUS_E_INTERNAL;
}
highest = (thermal_info.mcelsius > highest)?
thermal_info.mcelsius : highest;
}
*mcelsius = highest;
return ONLP_STATUS_OK;
}
/* Anaylze thermal changing history to judge if the change is a stable trend. */
static int _is_thermal_a_trend(int *mc_history){
int i, trend, trended;
if (mc_history == NULL) {
AIM_LOG_ERROR("Unable to get history of thermal\n");
return 0;
}
/* Get heat up/down trend. */
trend = 0;
for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) {
if (( mc_history[i+1] < mc_history[i])){
trend++;
}else if (( mc_history[i+1] > mc_history[i])){
trend--;
}
}
trended = (abs(trend) >= ((CELSIUS_RECORD_NUMBER+1)/2))? 1:0;
#if (DEBUG_MODE == 1)
DEBUG_PRINT("[INFO]%s#%d, trended: %d, UP/DW: %d mcelsius:",
__func__, __LINE__, trended, trend );
for (i = 0; i <= CELSIUS_RECORD_NUMBER; i++) {
DEBUG_PRINT(" %d =>", mc_history[i]);
}
DEBUG_PRINT("%c\n", ' ');
#endif
/*For more than half changes are same direction, it's a firm trend.*/
return trended;
}
/* Decide duty by highest value of thermal sensors.*/
static int
sysi_get_duty_by_highest(int *duty_cycle){
int i, ret, maxtrix_len;
int new_duty_cycle = 0 ;
int mc_history[CELSIUS_RECORD_NUMBER+1] = {0};
int *mcelsius_pre_p = &mc_history[1];
int *mcelsius_now_p = &mc_history[0];
/* Fill up mcelsius array,
* [0] is current temperature, others are history.
*/
ret = sysi_get_highest_thermal(mcelsius_now_p);
if(ONLP_STATUS_OK != ret){
return ret;
}
memcpy (mcelsius_pre_p, fan_control_data_pre.mc_high_pre,
sizeof(fan_control_data_pre.mc_high_pre));
DEBUG_PRINT("[INFO]%s#%d, highest mcelsius:%d!\n",
__func__, __LINE__, *mcelsius_now_p);
/* Shift records to the right */
for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) {
fan_control_data_pre.mc_high_pre[i] = mc_history[i];
}
/* Only change duty on consecutive heat rising or falling.*/
maxtrix_len = AIM_ARRAYSIZE(fan_ctrl_policy_single);
/* Only change duty when the thermal changing are firm. */
if (_is_thermal_a_trend(mc_history))
if(alarm_state==1 && current_state < LEVEL_TEMP_HIGH)
{
int matched = 0;
for (i = 0; i < maxtrix_len; i++) {
if ((*mcelsius_now_p > fan_ctrl_policy_single[i].step_up_thermal)) {
new_duty_cycle = fan_ctrl_policy_single[i].duty_cycle;
matched = !matched;
break;
}
}
/* if (!matched) {
DEBUG_PRINT("%s#%d, celsius(%d) falls into undefined range!!\n",
__func__, __LINE__, *mcelsius_now_p);
} */
}
*duty_cycle = new_duty_cycle;
return ONLP_STATUS_OK;
}
/* Decide duty by average value of thermal sensors.*/
static int
sysi_get_duty_by_average(int *duty_cycle){
int i, mcelsius_avg, ret, maxtrix_len;
int new_duty_cycle=0;
int mc_history[CELSIUS_RECORD_NUMBER+1] = {0};
int *mcelsius_pre_p = &mc_history[1];
int *mcelsius_now_p = &mc_history[0];
/* Fill up mcelsius array,
* [0] is current temperature, others are history.
*/
*mcelsius_now_p = 0;
ret = sysi_get_thermal_sum(mcelsius_now_p);
if(ONLP_STATUS_OK != ret){
return ret;
}
mcelsius_avg = (*mcelsius_now_p)/CHASSIS_THERMAL_COUNT;
memcpy (mcelsius_pre_p, fan_control_data_pre.mc_avg_pre,
sizeof(fan_control_data_pre.mc_avg_pre));
DEBUG_PRINT("[INFO]%s#%d, mcelsius:%d!\n", __func__, __LINE__, mcelsius_avg);
/* Shift records to the right */
for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) {
fan_control_data_pre.mc_avg_pre[i] = mc_history[i];
}
/* Only change duty on consecutive heat rising or falling.*/
maxtrix_len = AIM_ARRAYSIZE(fan_ctrl_policy_avg);
/* Only change duty when the thermal changing are firm. */
if (_is_thermal_a_trend(mc_history))
{
int matched = 0;
for (i = 0; i < maxtrix_len; i++) {
if ((mcelsius_avg >= fan_ctrl_policy_avg[i].step_up_thermal)) {
new_duty_cycle = fan_ctrl_policy_avg[i].duty_cycle;
matched = !matched;
break;
}
}
for (i = maxtrix_len-1; i>=0; i--) {
if ((mcelsius_avg < fan_ctrl_policy_avg[i].step_dn_thermal)) {
new_duty_cycle = fan_ctrl_policy_avg[i].duty_cycle;
matched = !matched;
break;
}
}
/*if (!matched) {
DEBUG_PRINT("%s#%d, celsius(%d) falls into undefined range!!\n",
__func__, __LINE__, mcelsius_avg);
} */
if (temp < (fan_thermal_policy[LEVEL_TEMP_HIGH].temp_down - 5000)) /*below 58 C, clear alarm*/
{
AIM_SYSLOG_INFO("Temperature high is clean", "Temperature high is clear", "Alarm for temperature high is cleared");
alarm_state=0;
}
}
*duty_cycle = new_duty_cycle;
return ONLP_STATUS_OK;
}
int
onlp_sysi_platform_manage_fans(void)
{
uint32_t fan_dir;
int ret;
int cur_duty_cycle, new_duty_cycle, tmp;
int direct_addon = 0;
onlp_oid_t fan_duty_oid = ONLP_FAN_ID_CREATE(FAN_ID_FOR_SET_FAN_DUTY);
/**********************************************************
* Decision 1: Set fan as full speed if any fan is failed.
**********************************************************/
ret = sysi_check_fan(&fan_dir);
if(ONLP_STATUS_OK != ret){
return ret;
}
if (fan_dir & ONLP_FAN_STATUS_B2F) {
direct_addon = FAN_DUTY_PLUS_FOR_DIR;
}
/**********************************************************
* Decision 2: If no matched fan speed is found from the policy,
* use FAN_DUTY_CYCLE_MIN as default speed
**********************************************************/
ret = sysi_get_fan_duty(&cur_duty_cycle);
if(ONLP_STATUS_OK != ret){
return ret;
}
/**********************************************************
* Decision 3: Decide new fan speed depend on fan direction and temperature
**********************************************************/
ret = sysi_get_duty_by_average(&new_duty_cycle);
if (ONLP_STATUS_OK != ret){
return ret;
}
ret = sysi_get_duty_by_highest(&tmp);
if (ONLP_STATUS_OK != ret){
return ret;
}
new_duty_cycle = (tmp > new_duty_cycle)? tmp : new_duty_cycle;
if (new_duty_cycle == 0)
{
new_duty_cycle = fan_control_data_pre.duty_cycle;
} else {
fan_control_data_pre.duty_cycle = new_duty_cycle;
}
fan_control_data_pre.dir_plus = direct_addon;
DEBUG_PRINT("[INFO]%s#%d, new duty: %d = %d + %d (%d)!\n", __func__, __LINE__,
new_duty_cycle + direct_addon, new_duty_cycle, direct_addon, cur_duty_cycle);
new_duty_cycle += direct_addon;
new_duty_cycle = (new_duty_cycle > FAN_DUTY_CYCLE_MAX)?
FAN_DUTY_CYCLE_MAX : new_duty_cycle;
if (new_duty_cycle == cur_duty_cycle) {
/* Duty cycle does not change, just return */
return ONLP_STATUS_OK;
}
return onlp_fani_percentage_set(fan_duty_oid, new_duty_cycle);
}
return 0;
}
int
onlp_sysi_platform_manage_leds(void)
@@ -488,3 +371,5 @@ onlp_sysi_platform_manage_leds(void)
return ONLP_STATUS_E_UNSUPPORTED;
}