aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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();