aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-21 22:52:50 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-21 23:55:27 +0200
commitb0674e9636a5010b1d9a17496afa1f6ffc1fc79b (patch)
treef1c93387fd754052d2edb5c03cd76481cf0eaaf6
parentd036cce744b4c0da6b147fe94d7f8ce723f8bb30 (diff)
sysmobts: Implement a small state machine for temp control
Check the temperature and move between "NORMAL", "WARNING" and "CRITICAL" state. We will only return from CRITICAL to WARNING when the temperature has significantly changed, and when being in state "WARNING" we enter an intermediate state to allow an easy hysteris.
-rw-r--r--src/osmo-bts-sysmo/Makefile.am3
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr.c3
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr.h6
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c8
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c191
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_misc.h2
6 files changed, 206 insertions, 7 deletions
diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am
index dc753f5..cc66933 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 496efd8..919bc52 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 deddaad..17a81cc 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 90890e6..cdb7832 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 0000000..217928a
--- /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 bddb1c2..28b6e62 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();