aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2018-07-11 19:54:57 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2018-07-16 16:24:26 +0200
commitfbb1ab909fced736141c250669eda8f23b117583 (patch)
treebb58d37f6e8f1653ba33373bc3b3616b83b5b8c4
parentac39b3eb0a58531facb8552cfa6f7fcb2355ba7b (diff)
timeslot FSM: fix ts_fsm_in_use_onenter() for TCH/F_TCH/H_PDCH
-rw-r--r--include/osmocom/bsc/timeslot_fsm.h1
-rw-r--r--src/osmo-bsc/gsm_data.c73
-rw-r--r--src/osmo-bsc/timeslot_fsm.c67
3 files changed, 134 insertions, 7 deletions
diff --git a/include/osmocom/bsc/timeslot_fsm.h b/include/osmocom/bsc/timeslot_fsm.h
index f6082600a..d02e156df 100644
--- a/include/osmocom/bsc/timeslot_fsm.h
+++ b/include/osmocom/bsc/timeslot_fsm.h
@@ -47,6 +47,7 @@ void ts_fsm_init();
void ts_fsm_alloc(struct gsm_bts_trx_ts *ts);
bool ts_is_capable_of_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pchan);
+bool ts_is_capable_of_lchant(struct gsm_bts_trx_ts *ts, enum gsm_chan_t type);
bool ts_is_lchan_waiting_for_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config *target_pchan);
bool ts_is_pchan_switching(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config *target_pchan);
bool ts_usable_as_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan);
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c
index 35971bbe7..1afd16f8c 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -1440,6 +1440,79 @@ bool ts_is_capable_of_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config
}
}
+bool ts_is_capable_of_lchant(struct gsm_bts_trx_ts *ts, enum gsm_chan_t type)
+{
+ switch (ts->pchan_on_init) {
+
+ case GSM_PCHAN_TCH_F:
+ switch (type) {
+ case GSM_LCHAN_TCH_F:
+ return true;
+ default:
+ return false;
+ }
+
+ case GSM_PCHAN_TCH_H:
+ switch (type) {
+ case GSM_LCHAN_TCH_H:
+ return true;
+ default:
+ return false;
+ }
+
+ case GSM_PCHAN_TCH_F_PDCH:
+ switch (type) {
+ case GSM_LCHAN_TCH_F:
+ case GSM_LCHAN_PDTCH:
+ return true;
+ default:
+ return false;
+ }
+
+ case GSM_PCHAN_TCH_F_TCH_H_PDCH:
+ switch (type) {
+ case GSM_LCHAN_TCH_F:
+ case GSM_LCHAN_TCH_H:
+ case GSM_LCHAN_PDTCH:
+ return true;
+ default:
+ return false;
+ }
+
+ case GSM_PCHAN_PDCH:
+ switch (type) {
+ case GSM_LCHAN_PDTCH:
+ return true;
+ default:
+ return false;
+ }
+
+ case GSM_PCHAN_CCCH:
+ switch (type) {
+ case GSM_LCHAN_CCCH:
+ return true;
+ default:
+ return false;
+ }
+ break;
+
+ case GSM_PCHAN_CCCH_SDCCH4_CBCH:
+ case GSM_PCHAN_CCCH_SDCCH4:
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
+ switch (type) {
+ case GSM_LCHAN_CCCH:
+ case GSM_LCHAN_SDCCH:
+ return true;
+ default:
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
{
struct gsm_bts_trx_ts *ts;
diff --git a/src/osmo-bsc/timeslot_fsm.c b/src/osmo-bsc/timeslot_fsm.c
index 812560e13..1e5def4a5 100644
--- a/src/osmo-bsc/timeslot_fsm.c
+++ b/src/osmo-bsc/timeslot_fsm.c
@@ -530,25 +530,78 @@ static void ts_fsm_wait_pdch_deact(struct osmo_fsm_inst *fi, uint32_t event, voi
static void ts_fsm_in_use_onenter(struct osmo_fsm_inst *fi, uint32_t prev_event)
{
- int in_use;
+ bool ok;
struct gsm_lchan *lchan;
struct gsm_bts_trx_ts *ts = ts_fi_ts(fi);
+ enum gsm_chan_t activating_type = GSM_LCHAN_NONE;
/* After being in use, allow PDCH act again, if appropriate. */
ts->pdch_act_allowed = true;
- ts_lchans_dispatch(ts, LCHAN_ST_WAIT_TS_READY, LCHAN_EV_TS_READY);
-
- in_use = 0;
- ts_for_each_lchan(lchan, ts) {
+ /* For static TS, check validity. For dyn TS, figure out which PCHAN this should become. */
+ ts_as_pchan_for_each_lchan(lchan, ts, ts->pchan_on_init) {
if (lchan_state_is(lchan, LCHAN_ST_UNUSED))
continue;
- in_use ++;
+
+ switch (lchan->type) {
+ case GSM_LCHAN_TCH_H:
+ case GSM_LCHAN_TCH_F:
+ case GSM_LCHAN_SDCCH:
+ ok = ts_is_capable_of_lchant(ts, lchan->type);
+ break;
+ default:
+ ok = false;
+ break;
+ }
+
+ if (!ok && lchan_state_is(lchan, LCHAN_ST_WAIT_TS_READY)) {
+ LOG_TS(ts, LOGL_ERROR, "lchan activation of %s is not permitted for %s (%s)\n",
+ gsm_lchant_name(lchan->type), gsm_pchan_name(ts->pchan_on_init),
+ gsm_lchan_name(lchan));
+ lchan_dispatch(lchan, LCHAN_EV_TS_ERROR);
+ }
+
+ if (!ok)
+ continue;
+
+ if (activating_type == GSM_LCHAN_NONE)
+ activating_type = lchan->type;
+ else if (activating_type != lchan->type) {
+ LOG_TS(ts, LOGL_ERROR, "lchan type %s mismatches %s (%s)\n",
+ gsm_lchant_name(lchan->type), gsm_lchant_name(activating_type),
+ gsm_lchan_name(lchan));
+ lchan_dispatch(lchan, LCHAN_EV_TS_ERROR);
+ }
}
- if (!in_use) {
+
+ ok = false;
+ switch (activating_type) {
+ case GSM_LCHAN_SDCCH:
+ case GSM_LCHAN_TCH_F:
+ case GSM_LCHAN_TCH_H:
+ ok = ts_is_capable_of_lchant(ts, activating_type);
+ break;
+
+ case GSM_LCHAN_NONE:
LOG_TS(ts, LOGL_DEBUG, "Entered IN_USE state but no lchans are actually in use now.");
+ break;
+
+ default:
+ LOG_TS(ts, LOGL_ERROR, "cannot use timeslot as %s\n", gsm_lchant_name(activating_type));
+ ts_lchans_dispatch(ts, LCHAN_ST_WAIT_TS_READY, LCHAN_EV_TS_ERROR);
+ break;
+ }
+
+ if (!ok) {
osmo_fsm_inst_state_chg(fi, TS_ST_UNUSED, 0, 0);
+ return;
}
+
+ /* Make sure dyn TS pchan_is is updated. For TCH/F_PDCH, there are only PDCH or TCH/F modes, but
+ * for Osmocom style TCH/F_TCH/H_PDCH the pchan_is == NONE until an lchan is activated. */
+ if (ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH)
+ ts->pchan_is = gsm_pchan_by_lchan_type(activating_type);
+ ts_lchans_dispatch(ts, LCHAN_ST_WAIT_TS_READY, LCHAN_EV_TS_READY);
}
static void ts_fsm_in_use(struct osmo_fsm_inst *fi, uint32_t event, void *data)