diff options
-rw-r--r-- | src/osmo-bts-sysmo/Makefile.am | 3 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 3 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 6 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c | 8 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c | 191 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/misc/sysmobts_misc.h | 2 |
6 files changed, 206 insertions, 7 deletions
diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index dc753f50..cc669339 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -25,7 +25,8 @@ sysmobts_mgr_SOURCES = \ misc/sysmobts_par.c misc/sysmobts_nl.c \ misc/sysmobts_mgr_2050.c \ misc/sysmobts_mgr_vty.c \ - misc/sysmobts_mgr_nl.c + misc/sysmobts_mgr_nl.c \ + misc/sysmobts_mgr_temp.c sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 496efd89..919bc520 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -288,6 +288,9 @@ int main(int argc, char **argv) if (sysmobts_mgr_nl_init() != 0) exit(3); + /* Initialize the temperature control */ + sysmobts_mgr_temp_init(&manager); + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index deddaadb..17a81ccb 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -18,8 +18,9 @@ enum { TEMP_ACT_PA_OFF = 0x8, }; -enum { +enum sysmobts_temp_state { STATE_NORMAL, /* Everything is fine */ + STATE_WARNING_HYST, /* Go back to normal next? */ STATE_WARNING, /* We are above the warning threshold */ STATE_CRITICAL, /* We have an issue. Wait for below warning */ }; @@ -58,11 +59,12 @@ struct sysmobts_mgr_instance { int action_warn; int action_crit; - int state; + enum sysmobts_temp_state state; }; int sysmobts_mgr_vty_init(void); int sysmobts_mgr_parse_config(struct sysmobts_mgr_instance *mgr); int sysmobts_mgr_nl_init(void); +int sysmobts_mgr_temp_init(struct sysmobts_mgr_instance *mgr); #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c index 90890e69..cdb78323 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c @@ -278,7 +278,7 @@ void sbts2050_uc_set_power(int pmaster, int pslave, int ppa) /********************************************************************** * Uc temperature handling *********************************************************************/ -void sbts2050_uc_check_temp(int *temp_pa, int *temp_board) +int sbts2050_uc_check_temp(int *temp_pa, int *temp_board) { rsppkt_t *response; struct msgb *msg; @@ -290,7 +290,7 @@ void sbts2050_uc_check_temp(int *temp_pa, int *temp_board) if (msg == NULL) { LOGP(DTEMP, LOGL_ERROR, "Error reading temperature\n"); - return; + return -1; } response = (rsppkt_t *)msg->data; @@ -303,6 +303,7 @@ void sbts2050_uc_check_temp(int *temp_pa, int *temp_board) response->rsp.tempGet.i8BrdTemp, response->rsp.tempGet.i8PaTemp); msgb_free(msg); + return 0; } void sbts2050_uc_initialize(void) @@ -323,10 +324,11 @@ void sbts2050_uc_initialize(void) LOGP(DTEMP, LOGL_NOTICE, "sysmoBTS2050 was not enabled at compile time.\n"); } -void sbts2050_uc_check_temp(int *temp_pa, int *temp_board) +int sbts2050_uc_check_temp(int *temp_pa, int *temp_board) { LOGP(DTEMP, LOGL_ERROR, "sysmoBTS2050 compiled without temp support.\n"); *temp_pa = *temp_board = 99999; + return -1; } int sbts2050_uc_get_status(struct sbts2050_power_status *status) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c new file mode 100644 index 00000000..217928a3 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c @@ -0,0 +1,191 @@ +/* Temperature control for SysmoBTS management daemon */ + +/* + * (C) 2014 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "misc/sysmobts_mgr.h" +#include "misc/sysmobts_misc.h" + +#include <osmo-bts/logging.h> + +#include <osmocom/core/timer.h> + +static struct sysmobts_mgr_instance *s_mgr; +static struct osmo_timer_list temp_ctrl_timer; + +static int next_state(enum sysmobts_temp_state current_state, int critical, int warning) +{ + int next_state = -1; + switch (current_state) { + case STATE_NORMAL: + if (critical) + next_state = STATE_CRITICAL; + else if (warning) + next_state = STATE_WARNING; + break; + case STATE_WARNING_HYST: + if (critical) + next_state = STATE_CRITICAL; + else if (warning) + next_state = STATE_WARNING; + else + next_state = STATE_NORMAL; + break; + case STATE_WARNING: + if (critical) + next_state = STATE_CRITICAL; + else if (!warning) + next_state = STATE_WARNING_HYST; + break; + case STATE_CRITICAL: + if (!critical && !warning) + next_state = STATE_WARNING; + break; + }; + + return next_state; +} + +/** + * Go back to normal! Undo everything we did in the other states. For + * reducint the transmit power, the question is if we should slowly set + * it back to normal, let the BTS slowly increase it.. or handle it here + * as well? + */ +static void execute_normal_act(struct sysmobts_mgr_instance *manager) +{ + LOGP(DTEMP, LOGL_NOTICE, "System is back to normal temperature.\n"); +} + +static void execute_warning_act(struct sysmobts_mgr_instance *manager) +{ + LOGP(DTEMP, LOGL_NOTICE, "System has reached temperature warning.\n"); +} + +static void execute_critical_act(struct sysmobts_mgr_instance *manager) +{ + LOGP(DTEMP, LOGL_NOTICE, "System has reached critical warning.\n"); +} + +static void sysmobts_mgr_temp_handle(struct sysmobts_mgr_instance *manager, + int critical, int warning) +{ + int new_state = next_state(manager->state, critical, warning); + + /* Nothing changed */ + if (new_state < 0) + return; + + manager->state = new_state; + switch (manager->state) { + case STATE_NORMAL: + execute_normal_act(manager); + break; + case STATE_WARNING_HYST: + /* do nothing? Maybe start to increase transmit power? */ + break; + case STATE_WARNING: + execute_warning_act(manager); + break; + case STATE_CRITICAL: + execute_critical_act(manager); + break; + }; +} + +static void temp_ctrl_check() +{ + int rc; + int warn_thresh_passed = 0; + int crit_thresh_passed = 0; + + LOGP(DTEMP, LOGL_DEBUG, "Going to check the temperature.\n"); + + /* Read the current digital temperature */ + rc = sysmobts_temp_get(SYSMOBTS_TEMP_DIGITAL, SYSMOBTS_TEMP_INPUT); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, + "Failed to read the digital temperature. rc=%d\n", rc); + warn_thresh_passed = crit_thresh_passed = 1; + } else { + int temp = rc / 1000; + if (temp > s_mgr->digital_limit.thresh_warn) + warn_thresh_passed = 1; + if (temp > s_mgr->digital_limit.thresh_crit) + crit_thresh_passed = 1; + LOGP(DTEMP, LOGL_DEBUG, "Digital temperature is: %d\n", temp); + } + + /* Read the current RF temperature */ + rc = sysmobts_temp_get(SYSMOBTS_TEMP_RF, SYSMOBTS_TEMP_INPUT); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, + "Failed to read the RF temperature. rc=%d\n", rc); + warn_thresh_passed = crit_thresh_passed = 1; + } else { + int temp = rc / 1000; + if (temp > s_mgr->rf_limit.thresh_warn) + warn_thresh_passed = 1; + if (temp > s_mgr->rf_limit.thresh_crit) + crit_thresh_passed = 1; + LOGP(DTEMP, LOGL_DEBUG, "RF temperature is: %d\n", temp); + } + + if (is_sbts2050_master()) { + int temp_pa, temp_board; + + rc = sbts2050_uc_check_temp(&temp_pa, &temp_board); + if (rc != 0) { + /* XXX what do here? */ + LOGP(DTEMP, LOGL_ERROR, + "Failed to read the temperature! Reboot?!\n"); + warn_thresh_passed = 1; + crit_thresh_passed = 1; + } else { + LOGP(DTEMP, LOGL_DEBUG, "SBTS2050 board(%d) PA(%d)\n", + temp_board, temp_pa); + if (temp_pa > s_mgr->pa_limit.thresh_warn) + warn_thresh_passed = 1; + if (temp_pa > s_mgr->pa_limit.thresh_crit) + crit_thresh_passed = 1; + if (temp_board > s_mgr->board_limit.thresh_warn) + warn_thresh_passed = 1; + if (temp_board > s_mgr->board_limit.thresh_crit) + crit_thresh_passed = 1; + } + } + + sysmobts_mgr_temp_handle(s_mgr, crit_thresh_passed, warn_thresh_passed); +} + +static void temp_ctrl_check_cb(void *unused) +{ + temp_ctrl_check(); + /* Check every two minutes? XXX make it configurable! */ + osmo_timer_schedule(&temp_ctrl_timer, 2 * 60, 0); +} + +int sysmobts_mgr_temp_init(struct sysmobts_mgr_instance *mgr) +{ + s_mgr = mgr; + temp_ctrl_timer.cb = temp_ctrl_check_cb; + temp_ctrl_check_cb(NULL); + return 0; +} diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index bddb1c20..28b6e628 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -55,7 +55,7 @@ struct sbts2050_power_status { float pa_bias_voltage; }; -void sbts2050_uc_check_temp(int *temp_pa, int *temp_board); +int sbts2050_uc_check_temp(int *temp_pa, int *temp_board); void sbts2050_uc_set_power(int pmaster, int pslave, int ppa); int sbts2050_uc_get_status(struct sbts2050_power_status *status); void sbts2050_uc_initialize(); |