aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2020-09-28 12:36:09 +0200
committerlaforge <laforge@osmocom.org>2020-10-20 13:45:57 +0000
commit22f59cd63ab7906684ba38e2f617497ec806cca2 (patch)
treefdf296613fcb97008f4bdd9ec03cfaf69b1419a3
parent7810a917331b33b6cfab5259b5fb2df73b27b230 (diff)
Introduce NM Channel FSM
-rw-r--r--include/osmo-bts/nm_common_fsm.h12
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/bts_trx.c13
-rw-r--r--src/common/nm_bb_transc_fsm.c24
-rw-r--r--src/common/nm_channel_fsm.c210
-rw-r--r--src/common/nm_common_fsm.c3
-rw-r--r--src/common/nm_radio_carrier_fsm.c9
-rw-r--r--src/osmo-bts-litecell15/l1_if.c3
-rw-r--r--src/osmo-bts-litecell15/oml.c55
-rw-r--r--src/osmo-bts-oc2g/l1_if.c3
-rw-r--r--src/osmo-bts-oc2g/oml.c53
-rw-r--r--src/osmo-bts-octphy/l1_if.c5
-rw-r--r--src/osmo-bts-octphy/l1_oml.c38
-rw-r--r--src/osmo-bts-omldummy/bts_model.c10
-rw-r--r--src/osmo-bts-sysmo/l1_if.c4
-rw-r--r--src/osmo-bts-sysmo/oml.c55
-rw-r--r--src/osmo-bts-trx/l1_if.c15
-rw-r--r--src/osmo-bts-virtual/bts_model.c10
18 files changed, 385 insertions, 138 deletions
diff --git a/include/osmo-bts/nm_common_fsm.h b/include/osmo-bts/nm_common_fsm.h
index 46717250..4a827577 100644
--- a/include/osmo-bts/nm_common_fsm.h
+++ b/include/osmo-bts/nm_common_fsm.h
@@ -36,6 +36,9 @@ enum nm_fsm_events {
NM_EV_PHYLINK_UP, /* RadioCarrier and BaseBand Transceiver only */
NM_EV_PHYLINK_DOWN, /* RadioCarrier and BaseBand Transceiver only */
NM_EV_DISABLE, /* RadioCarrier and BaseBand Transceiver only */
+ NM_EV_BBTRANSC_INSTALLED, /* Radio Channel only */
+ NM_EV_BBTRANSC_ENABLED, /* Radio Channel only */
+ NM_EV_BBTRANSC_DISABLED, /* Radio Channel only */
};
extern const struct value_string nm_fsm_event_names[];
@@ -72,3 +75,12 @@ enum nm_rcarrier_op_fsm_states {
NM_RCARRIER_ST_OP_ENABLED,
};
extern struct osmo_fsm nm_rcarrier_fsm;
+
+/* Radio channel */
+enum nm_chan_op_fsm_states {
+ NM_CHAN_ST_OP_DISABLED_NOTINSTALLED,
+ NM_CHAN_ST_OP_DISABLED_DEPENDENCY,
+ NM_CHAN_ST_OP_DISABLED_OFFLINE,
+ NM_CHAN_ST_OP_ENABLED,
+};
+extern struct osmo_fsm nm_chan_fsm;
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 71567857..d979bc0e 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -41,6 +41,7 @@ libbts_a_SOURCES = \
nm_bts_sm_fsm.c \
nm_bts_fsm.c \
nm_bb_transc_fsm.c \
+ nm_channel_fsm.c \
nm_radio_carrier_fsm.c \
$(NULL)
diff --git a/src/common/bts_trx.c b/src/common/bts_trx.c
index 04c21c34..6bb18a34 100644
--- a/src/common/bts_trx.c
+++ b/src/common/bts_trx.c
@@ -32,6 +32,8 @@
static int gsm_bts_trx_talloc_destructor(struct gsm_bts_trx *trx)
{
+ unsigned int i;
+
if (trx->bb_transc.mo.fi) {
osmo_fsm_inst_free(trx->bb_transc.mo.fi);
trx->bb_transc.mo.fi = NULL;
@@ -40,6 +42,13 @@ static int gsm_bts_trx_talloc_destructor(struct gsm_bts_trx *trx)
osmo_fsm_inst_free(trx->mo.fi);
trx->mo.fi = NULL;
}
+ for (i = 0; i < TRX_NR_TS; i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ if (ts->mo.fi) {
+ osmo_fsm_inst_free(ts->mo.fi);
+ ts->mo.fi = NULL;
+ }
+ }
return 0;
}
@@ -79,6 +88,10 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
ts->dyn.pchan_want = GSM_PCHAN_NONE;
ts->tsc = -1;
+ ts->mo.fi = osmo_fsm_inst_alloc(&nm_chan_fsm, trx, ts,
+ LOGL_INFO, NULL);
+ osmo_fsm_inst_update_id_f(ts->mo.fi, "bts%d-trx%d-ts%d",
+ bts->nr, trx->nr, ts->nr);
gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,
bts->nr, trx->nr, ts->nr);
diff --git a/src/common/nm_bb_transc_fsm.c b/src/common/nm_bb_transc_fsm.c
index b23ff531..936451ff 100644
--- a/src/common/nm_bb_transc_fsm.c
+++ b/src/common/nm_bb_transc_fsm.c
@@ -55,11 +55,17 @@ static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint3
static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct gsm_bts_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+ struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);
+ int i;
switch (event) {
case NM_EV_SW_ACT:
oml_mo_tx_sw_act_rep(&bb_transc->mo);
nm_bb_transc_fsm_state_chg(fi, NM_BBTRANSC_ST_OP_DISABLED_OFFLINE);
+ for (i = 0; i < TRX_NR_TS; i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_BBTRANSC_INSTALLED, NULL);
+ }
return;
case NM_EV_RSL_UP:
return;
@@ -79,8 +85,18 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
static void st_op_disabled_offline_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_bts_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+ struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);
+ int i;
+
bb_transc->mo.opstart_success = false;
oml_mo_state_chg(&bb_transc->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+
+ if (prev_state == NM_BBTRANSC_ST_OP_ENABLED) {
+ for (i = 0; i < TRX_NR_TS; i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_BBTRANSC_DISABLED, NULL);
+ }
+ }
}
static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -138,7 +154,15 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
static void st_op_enabled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_bts_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+ struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);
+ uint8_t tn;
+
oml_mo_state_chg(&bb_transc->mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
+ /* Mark Dependency TS as Offline (ready to be Opstarted) */
+ for (tn = 0; tn < TRX_NR_TS; tn++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[tn];
+ osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_BBTRANSC_ENABLED, NULL);
+ }
}
static void st_op_enabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
diff --git a/src/common/nm_channel_fsm.c b/src/common/nm_channel_fsm.c
new file mode 100644
index 00000000..263d2cc9
--- /dev/null
+++ b/src/common/nm_channel_fsm.c
@@ -0,0 +1,210 @@
+/* NM Radio Carrier FSM */
+
+/* (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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 <errno.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/tdef.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
+
+#include <osmo-bts/logging.h>
+#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/bts_model.h>
+#include <osmo-bts/bts.h>
+#include <osmo-bts/rsl.h>
+#include <osmo-bts/nm_common_fsm.h>
+
+#define X(s) (1 << (s))
+
+#define nm_chan_fsm_state_chg(fi, NEXT_STATE) \
+ osmo_fsm_inst_state_chg(fi, NEXT_STATE, 0, 0)
+
+//////////////////////////
+// FSM STATE ACTIONS
+//////////////////////////
+
+static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+ ts->mo.opstart_success = false;
+ oml_mo_state_chg(&ts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
+}
+
+static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+
+ switch (event) {
+ case NM_EV_BBTRANSC_INSTALLED:
+ oml_mo_tx_sw_act_rep(&ts->mo);
+ if (ts->trx->bb_transc.mo.nm_state.operational == NM_OPSTATE_ENABLED)
+ nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_DISABLED_OFFLINE);
+ else
+ nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_DISABLED_DEPENDENCY);
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_op_disabled_dependency_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+ ts->mo.opstart_success = false;
+ oml_mo_state_chg(&ts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
+}
+
+static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+
+ switch (event) {
+ case NM_EV_OPSTART_ACK:
+ LOGPFSML(fi, LOGL_NOTICE, "BSC trying to activate TS while still in avail=dependency. "
+ "Allowing it to stay backward-compatible with older osmo-bts versions, but BSC is wrong.\n");
+ ts->mo.opstart_success = true;
+ oml_mo_opstart_ack(&ts->mo);
+ nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_ENABLED);
+ return;
+ case NM_EV_OPSTART_NACK:
+ ts->mo.opstart_success = false;
+ oml_mo_opstart_nack(&ts->mo, (int)(intptr_t)data);
+ return;
+ case NM_EV_BBTRANSC_ENABLED:
+ oml_mo_state_chg(&ts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_op_disabled_offline_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+ ts->mo.opstart_success = false;
+ oml_mo_state_chg(&ts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+}
+
+static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+
+ switch (event) {
+ case NM_EV_OPSTART_ACK:
+ ts->mo.opstart_success = true;
+ oml_mo_opstart_ack(&ts->mo);
+ nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_ENABLED);
+ return;
+ case NM_EV_OPSTART_NACK:
+ ts->mo.opstart_success = false;
+ oml_mo_opstart_nack(&ts->mo, (int)(intptr_t)data);
+ return;
+ case NM_EV_BBTRANSC_DISABLED:
+ oml_mo_state_chg(&ts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_op_enabled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;
+ oml_mo_state_chg(&ts->mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
+}
+
+static void st_op_enabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case NM_EV_BBTRANSC_DISABLED:
+ nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_DISABLED_DEPENDENCY);
+ return;
+ case NM_EV_DISABLE:
+ nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_DISABLED_OFFLINE);
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static struct osmo_fsm_state nm_chan_fsm_states[] = {
+ [NM_CHAN_ST_OP_DISABLED_NOTINSTALLED] = {
+ .in_event_mask =
+ X(NM_EV_BBTRANSC_INSTALLED),
+ .out_state_mask =
+ X(NM_CHAN_ST_OP_DISABLED_OFFLINE) |
+ X(NM_CHAN_ST_OP_DISABLED_DEPENDENCY),
+ .name = "DISABLED_NOTINSTALLED",
+ .onenter = st_op_disabled_notinstalled_on_enter,
+ .action = st_op_disabled_notinstalled,
+ },
+ [NM_CHAN_ST_OP_DISABLED_DEPENDENCY] = {
+ .in_event_mask =
+ X(NM_EV_OPSTART_ACK) | /* backward compatibility, buggy BSC */
+ X(NM_EV_OPSTART_NACK) |
+ X(NM_EV_BBTRANSC_ENABLED),
+ .out_state_mask =
+ X(NM_CHAN_ST_OP_DISABLED_OFFLINE) |
+ X(NM_CHAN_ST_OP_ENABLED), /* backward compatibility, buggy BSC */
+ .name = "DISABLED_DEPENDENCY",
+ .onenter = st_op_disabled_dependency_on_enter,
+ .action = st_op_disabled_dependency,
+ },
+ [NM_CHAN_ST_OP_DISABLED_OFFLINE] = {
+ .in_event_mask =
+ X(NM_EV_OPSTART_ACK) |
+ X(NM_EV_OPSTART_NACK) |
+ X(NM_EV_BBTRANSC_DISABLED),
+ .out_state_mask =
+ X(NM_CHAN_ST_OP_ENABLED) |
+ X(NM_CHAN_ST_OP_DISABLED_DEPENDENCY),
+ .name = "DISABLED_OFFLINE",
+ .onenter = st_op_disabled_offline_on_enter,
+ .action = st_op_disabled_offline,
+ },
+ [NM_CHAN_ST_OP_ENABLED] = {
+ .in_event_mask =
+ X(NM_EV_BBTRANSC_DISABLED) |
+ X(NM_EV_DISABLE),
+ .out_state_mask =
+ X(NM_CHAN_ST_OP_DISABLED_OFFLINE) |
+ X(NM_CHAN_ST_OP_DISABLED_DEPENDENCY),
+ .name = "ENABLED",
+ .onenter = st_op_enabled_on_enter,
+ .action = st_op_enabled,
+ },
+};
+
+struct osmo_fsm nm_chan_fsm = {
+ .name = "NM_CHAN_OP",
+ .states = nm_chan_fsm_states,
+ .num_states = ARRAY_SIZE(nm_chan_fsm_states),
+ .event_names = nm_fsm_event_names,
+ .log_subsys = DOML,
+};
+
+static __attribute__((constructor)) void nm_chan_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&nm_chan_fsm) == 0);
+}
diff --git a/src/common/nm_common_fsm.c b/src/common/nm_common_fsm.c
index 88045699..b2fd4514 100644
--- a/src/common/nm_common_fsm.c
+++ b/src/common/nm_common_fsm.c
@@ -32,5 +32,8 @@ const struct value_string nm_fsm_event_names[] = {
{ NM_EV_PHYLINK_UP, "PHYLINK_UP" },
{ NM_EV_PHYLINK_DOWN, "PHYLINK_DOWN" },
{ NM_EV_DISABLE, "DISABLE" },
+ { NM_EV_BBTRANSC_INSTALLED, "BBTRANSC_INSTALLED" },
+ { NM_EV_BBTRANSC_ENABLED, "BBTRANSC_ENABLED" },
+ { NM_EV_BBTRANSC_DISABLED, "BBTRANSC_DISABLED" },
{ 0, NULL }
};
diff --git a/src/common/nm_radio_carrier_fsm.c b/src/common/nm_radio_carrier_fsm.c
index 01849d1e..d8291f8c 100644
--- a/src/common/nm_radio_carrier_fsm.c
+++ b/src/common/nm_radio_carrier_fsm.c
@@ -136,16 +136,7 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
static void st_op_enabled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_bts_trx *trx = (struct gsm_bts_trx *)fi->priv;
- uint8_t tn;
oml_mo_state_chg(&trx->mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
-
- /* Mark Dependency TS as Offline (ready to be Opstarted) */
- for (tn = 0; tn < TRX_NR_TS; tn++) {
- if (trx->ts[tn].mo.nm_state.operational == NM_OPSTATE_DISABLED &&
- trx->ts[tn].mo.nm_state.availability == NM_AVSTATE_DEPENDENCY) {
- oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
- }
- }
}
static void st_op_enabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c
index 94fd1653..b7c24c08 100644
--- a/src/osmo-bts-litecell15/l1_if.c
+++ b/src/osmo-bts-litecell15/l1_if.c
@@ -1273,9 +1273,6 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
/* signal availability */
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
-
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
- oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
} else {
if (bts_lc15->led_ctrl_mode == LC15_LED_CONTROL_BTS)
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
diff --git a/src/osmo-bts-litecell15/oml.c b/src/osmo-bts-litecell15/oml.c
index d8109877..1fe7205a 100644
--- a/src/osmo-bts-litecell15/oml.c
+++ b/src/osmo-bts-litecell15/oml.c
@@ -277,38 +277,41 @@ static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg)
get_value_string(lc15bts_l1prim_names, l1p->id),
get_value_string(lc15bts_l1status_names, status));
msgb_free(l1_msg);
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_NACK,
(void*)(intptr_t)NM_NACK_CANT_PERFORM);
- else
- return oml_mo_opstart_nack(mo, NM_NACK_CANT_PERFORM);
+ case NM_OC_CHANNEL:
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi, NM_EV_OPSTART_NACK,
+ (void*)(intptr_t)NM_NACK_CANT_PERFORM);
+ default:
+ OSMO_ASSERT(0);
+ }
}
msgb_free(l1_msg);
-
- /* We already have a FSM for Radio Carrier, handle it there */
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_ACK, NULL);
-
- /* Set to Operational State: Enabled */
- oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
-
- /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
- if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 &&
- mo->obj_inst.ts_nr == 0) {
- struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
- DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
- mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
- LCHAN_REL_ACT_OML;
- lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
- if (cbch) {
- cbch->rel_act_kind = LCHAN_REL_ACT_OML;
- lchan_activate(cbch);
+ case NM_OC_CHANNEL:
+ /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
+ if (mo->obj_inst.trx_nr == 0 &&
+ mo->obj_inst.ts_nr == 0) {
+ struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
+ DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
+ mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
+ LCHAN_REL_ACT_OML;
+ lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
+ if (cbch) {
+ cbch->rel_act_kind = LCHAN_REL_ACT_OML;
+ lchan_activate(cbch);
+ }
}
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi,
+ NM_EV_OPSTART_ACK, NULL);
+ default:
+ OSMO_ASSERT(0);
}
-
- /* Send OPSTART ack */
- return oml_mo_opstart_ack(mo);
}
static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
@@ -1886,6 +1889,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
{
struct gsm_bts_bb_trx *bb_transc;
struct gsm_bts_trx *trx;
+ struct gsm_bts_trx_ts *ts;
int rc;
switch (mo->obj_class) {
@@ -1904,7 +1908,8 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL);
break;
case NM_OC_CHANNEL:
- rc = ts_opstart(obj);
+ ts = (struct gsm_bts_trx_ts*) obj;
+ rc = ts_opstart(ts);
break;
case NM_OC_GPRS_NSE:
case NM_OC_GPRS_CELL:
diff --git a/src/osmo-bts-oc2g/l1_if.c b/src/osmo-bts-oc2g/l1_if.c
index 4044f43d..475edd21 100644
--- a/src/osmo-bts-oc2g/l1_if.c
+++ b/src/osmo-bts-oc2g/l1_if.c
@@ -1328,9 +1328,6 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
/* signal availability */
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
-
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
- oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
} else {
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_DISABLE, NULL);
diff --git a/src/osmo-bts-oc2g/oml.c b/src/osmo-bts-oc2g/oml.c
index 2efa577b..6403a22c 100644
--- a/src/osmo-bts-oc2g/oml.c
+++ b/src/osmo-bts-oc2g/oml.c
@@ -277,38 +277,41 @@ static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg)
get_value_string(oc2gbts_l1prim_names, l1p->id),
get_value_string(oc2gbts_l1status_names, status));
msgb_free(l1_msg);
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_NACK,
(void*)(intptr_t)NM_NACK_CANT_PERFORM);
- else
- return oml_mo_opstart_nack(mo, NM_NACK_CANT_PERFORM);
+ case NM_OC_CHANNEL:
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi, NM_EV_OPSTART_NACK,
+ (void*)(intptr_t)NM_NACK_CANT_PERFORM);
+ default:
+ OSMO_ASSERT(0);
+ }
}
msgb_free(l1_msg);
-
- /* We already have a FSM for Radio Carrier, handle it there */
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_ACK, NULL);
-
- /* Set to Operational State: Enabled */
- oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
-
- /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
- if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 &&
- mo->obj_inst.ts_nr == 0) {
- struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
- DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
- mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
- LCHAN_REL_ACT_OML;
- lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
- if (cbch) {
- cbch->rel_act_kind = LCHAN_REL_ACT_OML;
- lchan_activate(cbch);
+ case NM_OC_CHANNEL:
+ /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
+ if (mo->obj_inst.trx_nr == 0 &&
+ mo->obj_inst.ts_nr == 0) {
+ struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
+ DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
+ mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
+ LCHAN_REL_ACT_OML;
+ lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
+ if (cbch) {
+ cbch->rel_act_kind = LCHAN_REL_ACT_OML;
+ lchan_activate(cbch);
+ }
}
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi,
+ NM_EV_OPSTART_ACK, NULL);
+ default:
+ OSMO_ASSERT(0);
}
-
- /* Send OPSTART ack */
- return oml_mo_opstart_ack(mo);
}
static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
@@ -1894,6 +1897,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
{
struct gsm_bts_bb_trx *bb_transc;
struct gsm_bts_trx* trx;
+ struct gsm_bts_trx_ts *ts;
int rc;
switch (mo->obj_class) {
@@ -1916,6 +1920,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL);
break;
case NM_OC_CHANNEL:
+ ts = (struct gsm_bts_trx_ts*) obj;
rc = ts_opstart(obj);
break;
case NM_OC_GPRS_NSE:
diff --git a/src/osmo-bts-octphy/l1_if.c b/src/osmo-bts-octphy/l1_if.c
index c7e0b429..4dc399e2 100644
--- a/src/osmo-bts-octphy/l1_if.c
+++ b/src/osmo-bts-octphy/l1_if.c
@@ -310,15 +310,10 @@ int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
/* For OctPHY, this only about sending state changes to BSC */
int l1if_activate_rf(struct gsm_bts_trx *trx, int on)
{
- int i;
if (on) {
/* signal availability */
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
-
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
- oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED,
- NM_AVSTATE_DEPENDENCY);
} else {
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_DISABLE, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_DISABLE, NULL);
diff --git a/src/osmo-bts-octphy/l1_oml.c b/src/osmo-bts-octphy/l1_oml.c
index a72367c4..bf171254 100644
--- a/src/osmo-bts-octphy/l1_oml.c
+++ b/src/osmo-bts-octphy/l1_oml.c
@@ -190,28 +190,28 @@ static int opstart_compl(struct gsm_abis_mo *mo)
struct gsm_bts_trx *trx = gsm_bts_trx_num(mo->bts, mo->obj_inst.trx_nr);
/* TODO: Send NACK in case of error! */
- /* We already have a FSM for Radio Carrier, handle it there */
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_ACK, NULL);
-
- /* Set to Operational State: Enabled */
- oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
-
- /* hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
- if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 &&
- mo->obj_inst.ts_nr == 7) {
- struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
- mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
- LCHAN_REL_ACT_OML;
- lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
- if (cbch) {
- cbch->rel_act_kind = LCHAN_REL_ACT_OML;
- lchan_activate(cbch);
+ case NM_OC_CHANNEL:
+ /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
+ if (mo->obj_inst.trx_nr == 0 &&
+ mo->obj_inst.ts_nr == 0) {
+ struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
+ DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
+ mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
+ LCHAN_REL_ACT_OML;
+ lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
+ if (cbch) {
+ cbch->rel_act_kind = LCHAN_REL_ACT_OML;
+ lchan_activate(cbch);
+ }
}
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi,
+ NM_EV_OPSTART_ACK, NULL);
+ default:
+ OSMO_ASSERT(0);
}
-
- /* Send OPSTART ack */
- return oml_mo_opstart_ack(mo);
}
static
diff --git a/src/osmo-bts-omldummy/bts_model.c b/src/osmo-bts-omldummy/bts_model.c
index 06e13735..5624fc1a 100644
--- a/src/osmo-bts-omldummy/bts_model.c
+++ b/src/osmo-bts-omldummy/bts_model.c
@@ -73,13 +73,8 @@ int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
static uint8_t vbts_set_bts(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
- uint8_t tn;
llist_for_each_entry(trx, &bts->trx_list, list) {
-
- for (tn = 0; tn < TRX_NR_TS; tn++)
- oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
-
/* report availability of trx to the bts. this will trigger the rsl connection */
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
@@ -124,6 +119,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj)
int rc;
struct gsm_bts_bb_trx *bb_transc;
struct gsm_bts_trx* trx;
+ struct gsm_bts_trx_ts* ts;
switch (mo->obj_class) {
case NM_OC_SITE_MANAGER:
@@ -140,6 +136,10 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj)
bb_transc = (struct gsm_bts_bb_trx *) obj;
rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL);
break;
+ case NM_OC_CHANNEL:
+ ts = (struct gsm_bts_trx_ts *) obj;
+ rc = osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_OPSTART_ACK, NULL);
+ break;
case NM_OC_GPRS_NSE:
case NM_OC_GPRS_CELL:
case NM_OC_GPRS_NSVC:
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 4d228bb6..2e4765d9 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -1218,7 +1218,6 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
SuperFemto_Prim_t *sysp = msgb_sysprim(resp);
GsmL1_Status_t status;
int on = 0;
- unsigned int i;
if (sysp->id == SuperFemto_PrimId_ActivateRfCnf)
on = 1;
@@ -1243,9 +1242,6 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
/* signal availability */
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
-
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
- oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
} else {
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_DISABLE, NULL);
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index 9a82647e..e8bfb2da 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -276,38 +276,41 @@ static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg)
get_value_string(femtobts_l1prim_names, l1p->id),
get_value_string(femtobts_l1status_names, status));
msgb_free(l1_msg);
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_NACK,
(void*)(intptr_t)NM_NACK_CANT_PERFORM);
- else
- return oml_mo_opstart_nack(mo, NM_NACK_CANT_PERFORM);
+ case NM_OC_CHANNEL:
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi, NM_EV_OPSTART_NACK,
+ (void*)(intptr_t)NM_NACK_CANT_PERFORM);
+ default:
+ OSMO_ASSERT(0);
+ }
}
msgb_free(l1_msg);
-
- /* We already have a FSM for Radio Carrier, handle it there */
- if (mo->obj_class == NM_OC_RADIO_CARRIER)
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_ACK, NULL);
-
- /* Set to Operational State: Enabled */
- oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
-
- /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
- if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 &&
- mo->obj_inst.ts_nr == 0) {
- struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
- DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
- mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
- LCHAN_REL_ACT_OML;
- lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
- if (cbch) {
- cbch->rel_act_kind = LCHAN_REL_ACT_OML;
- lchan_activate(cbch);
+ case NM_OC_CHANNEL:
+ /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */
+ if (mo->obj_inst.trx_nr == 0 &&
+ mo->obj_inst.ts_nr == 0) {
+ struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts);
+ DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n");
+ mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind =
+ LCHAN_REL_ACT_OML;
+ lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]);
+ if (cbch) {
+ cbch->rel_act_kind = LCHAN_REL_ACT_OML;
+ lchan_activate(cbch);
+ }
}
+ return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi,
+ NM_EV_OPSTART_ACK, NULL);
+ default:
+ OSMO_ASSERT(0);
}
-
- /* Send OPSTART ack */
- return oml_mo_opstart_ack(mo);
}
static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
@@ -1772,6 +1775,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
{
struct gsm_bts_bb_trx *bb_transc;
struct gsm_bts_trx* trx;
+ struct gsm_bts_trx_ts *ts;
int rc;
switch (mo->obj_class) {
@@ -1794,7 +1798,8 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL);
break;
case NM_OC_CHANNEL:
- rc = ts_opstart(obj);
+ ts = (struct gsm_bts_trx_ts*) obj;
+ rc = ts_opstart(ts);
break;
case NM_OC_GPRS_NSE:
case NM_OC_GPRS_CELL:
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index 9c8069a3..fc8ef760 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -91,7 +91,6 @@ static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail)
{
struct phy_instance *pinst = l1h->phy_inst;
struct gsm_bts_trx *trx = pinst->trx;
- uint8_t tn;
/* HACK, we should change state when we receive first clock from
* transceiver */
@@ -102,19 +101,9 @@ static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail)
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
pinst->u.osmotrx.sw_act_reported = true;
}
-
- for (tn = 0; tn < TRX_NR_TS; tn++)
- oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED,
- (l1h->config.slotmask & (1 << tn)) ?
- NM_AVSTATE_DEPENDENCY :
- NM_AVSTATE_NOT_INSTALLED);
} else {
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_DISABLE, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_DISABLE, NULL);
-
- for (tn = 0; tn < TRX_NR_TS; tn++)
- oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED,
- NM_AVSTATE_OFF_LINE);
}
}
@@ -604,6 +593,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
{
struct gsm_bts_bb_trx *bb_transc;
struct gsm_bts_trx *trx;
+ struct gsm_bts_trx_ts *ts;
int rc;
switch (mo->obj_class) {
@@ -623,6 +613,9 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL);
break;
case NM_OC_CHANNEL:
+ ts = (struct gsm_bts_trx_ts *) obj;
+ rc = osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_OPSTART_ACK, NULL);
+ break;
case NM_OC_GPRS_NSE:
case NM_OC_GPRS_CELL:
case NM_OC_GPRS_NSVC:
diff --git a/src/osmo-bts-virtual/bts_model.c b/src/osmo-bts-virtual/bts_model.c
index c3a75f4c..e7b0f81b 100644
--- a/src/osmo-bts-virtual/bts_model.c
+++ b/src/osmo-bts-virtual/bts_model.c
@@ -83,13 +83,8 @@ int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
static uint8_t vbts_set_bts(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
- uint8_t tn;
llist_for_each_entry(trx, &bts->trx_list, list) {
-
- for (tn = 0; tn < TRX_NR_TS; tn++)
- oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
-
/* report availability of trx to the bts. this will trigger the rsl connection */
osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL);
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL);
@@ -141,6 +136,7 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj)
int rc;
struct gsm_bts_bb_trx *bb_transc;
struct gsm_bts_trx* trx;
+ struct gsm_bts_trx_ts *ts;
switch (mo->obj_class) {
case NM_OC_SITE_MANAGER:
@@ -157,6 +153,10 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj)
bb_transc = (struct gsm_bts_bb_trx *) obj;
rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL);
break;
+ case NM_OC_CHANNEL:
+ ts = (struct gsm_bts_trx_ts *) obj;
+ rc = osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_OPSTART_ACK, NULL);
+ break;
case NM_OC_GPRS_NSE:
case NM_OC_GPRS_CELL:
case NM_OC_GPRS_NSVC: