aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2020-09-25 18:55:55 +0200
committerlaforge <laforge@osmocom.org>2020-10-20 13:45:57 +0000
commit7810a917331b33b6cfab5259b5fb2df73b27b230 (patch)
treea463fa051fd97170f80f2aa4acf8d5c4ce61e56a /src/common
parentae6e3e8f8b2bd7b8235035fb324c373d61648cb5 (diff)
Introduce NM Radio Carrier and Baseband Transceiver FSMs
All the Operative State logic to manage a RadioCarrier//BBTransc NM objects is centralized in these FSM, where other parts of the code simply send events to it. This allows keeping state consistent and offloading logic from each bts backend, since they are only required to submit events now. The idea in the long run is to also replace other NM objects with similar FSMs. This improved logic fixes bug where PHY + RSL link became available before OPSTART and hence op state changed to Enabled before receiving any OPSTART message. Change-Id: Ifb249a821c4270918699b6375a72b3a618e8cfbe
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/bts_trx.c42
-rw-r--r--src/common/nm_bb_transc_fsm.c211
-rw-r--r--src/common/nm_common_fsm.c5
-rw-r--r--src/common/nm_radio_carrier_fsm.c218
-rw-r--r--src/common/phy_link.c11
6 files changed, 471 insertions, 18 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 463797ef..71567857 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -40,6 +40,8 @@ libbts_a_SOURCES = \
nm_common_fsm.c \
nm_bts_sm_fsm.c \
nm_bts_fsm.c \
+ nm_bb_transc_fsm.c \
+ nm_radio_carrier_fsm.c \
$(NULL)
libl1sched_a_SOURCES = scheduler.c
diff --git a/src/common/bts_trx.c b/src/common/bts_trx.c
index 93e15c32..04c21c34 100644
--- a/src/common/bts_trx.c
+++ b/src/common/bts_trx.c
@@ -17,6 +17,8 @@
*
*/
+#include <osmocom/core/fsm.h>
+
#include <osmocom/gsm/abis_nm.h>
#include <osmo-bts/logging.h>
@@ -26,6 +28,20 @@
#include <osmo-bts/bts_model.h>
#include <osmo-bts/rsl.h>
#include <osmo-bts/phy_link.h>
+#include <osmo-bts/nm_common_fsm.h>
+
+static int gsm_bts_trx_talloc_destructor(struct gsm_bts_trx *trx)
+{
+ if (trx->bb_transc.mo.fi) {
+ osmo_fsm_inst_free(trx->bb_transc.mo.fi);
+ trx->bb_transc.mo.fi = NULL;
+ }
+ if (trx->mo.fi) {
+ osmo_fsm_inst_free(trx->mo.fi);
+ trx->mo.fi = NULL;
+ }
+ return 0;
+}
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
{
@@ -35,12 +51,20 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
if (!trx)
return NULL;
+ talloc_set_destructor(trx, gsm_bts_trx_talloc_destructor);
+
trx->bts = bts;
trx->nr = bts->num_trx++;
+ trx->mo.fi = osmo_fsm_inst_alloc(&nm_rcarrier_fsm, trx, trx,
+ LOGL_INFO, NULL);
+ osmo_fsm_inst_update_id_f(trx->mo.fi, "bts%d-trx%d", bts->nr, trx->nr);
gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,
bts->nr, trx->nr, 0xff);
+ trx->bb_transc.mo.fi = osmo_fsm_inst_alloc(&nm_bb_transc_fsm, trx, &trx->bb_transc,
+ LOGL_INFO, NULL);
+ osmo_fsm_inst_update_id_f(trx->bb_transc.mo.fi, "bts%d-trx%d", bts->nr, trx->nr);
gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
bts->nr, trx->nr, 0xff);
@@ -161,7 +185,7 @@ int trx_link_estab(struct gsm_bts_trx *trx)
LOGPTRX(trx, DSUM, LOGL_INFO, "RSL link %s\n",
link ? "up" : "down");
- trx_operability_update(trx);
+ osmo_fsm_inst_dispatch(trx->mo.fi, link ? NM_EV_RSL_UP : NM_EV_RSL_DOWN, NULL);
if (link)
rc = rsl_tx_rf_res(trx);
@@ -177,22 +201,6 @@ int trx_link_estab(struct gsm_bts_trx *trx)
return 0;
}
-/* set the availability of the TRX based on internal state (RSL + phy link) */
-void trx_operability_update(struct gsm_bts_trx *trx)
-{
- enum abis_nm_op_state op_st;
- enum abis_nm_avail_state avail_st;
- struct phy_instance *pinst = trx_phy_instance(trx);
-
- op_st = (trx->rsl_link && phy_link_state_get(pinst->phy_link) == PHY_LINK_CONNECTED) ?
- NM_OPSTATE_ENABLED : NM_OPSTATE_DISABLED;
- avail_st = (op_st == NM_OPSTATE_ENABLED) ? NM_AVSTATE_OK : NM_AVSTATE_NOT_INSTALLED;
-
- LOGPTRX(trx, DSUM, LOGL_INFO, "Setting operative = %s\n", abis_nm_opstate_name(op_st));
- oml_mo_state_chg(&trx->mo, op_st, avail_st);
- oml_mo_state_chg(&trx->bb_transc.mo, -1, avail_st);
-}
-
bool trx_ms_pwr_ctrl_is_osmo(const struct gsm_bts_trx *trx)
{
diff --git a/src/common/nm_bb_transc_fsm.c b/src/common/nm_bb_transc_fsm.c
new file mode 100644
index 00000000..b23ff531
--- /dev/null
+++ b/src/common/nm_bb_transc_fsm.c
@@ -0,0 +1,211 @@
+/* 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>
+#include <osmo-bts/phy_link.h>
+
+#define X(s) (1 << (s))
+
+#define nm_bb_transc_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_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+ bb_transc->mo.opstart_success = false;
+ oml_mo_state_chg(&bb_transc->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_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+
+ 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);
+ return;
+ case NM_EV_RSL_UP:
+ return;
+ case NM_EV_RSL_DOWN:
+ return;
+ case NM_EV_PHYLINK_UP:
+ return;
+ case NM_EV_PHYLINK_DOWN:
+ return;
+ case NM_EV_DISABLE:
+ 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_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+ bb_transc->mo.opstart_success = false;
+ oml_mo_state_chg(&bb_transc->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_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;
+ struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);
+ bool phy_state_connected;
+ bool rsl_link_connected;
+
+ switch (event) {
+ case NM_EV_OPSTART_ACK:
+ bb_transc->mo.opstart_success = true;
+ oml_mo_opstart_ack(&bb_transc->mo);
+ break; /* check statechg below */
+ case NM_EV_OPSTART_NACK:
+ bb_transc->mo.opstart_success = false;
+ oml_mo_opstart_nack(&bb_transc->mo, (int)(intptr_t)data);
+ return;
+ case NM_EV_RSL_UP:
+ break; /* check statechg below */
+ case NM_EV_RSL_DOWN:
+ return;
+ case NM_EV_PHYLINK_UP:
+ break; /* check statechg below */
+ case NM_EV_PHYLINK_DOWN:
+ return;
+ case NM_EV_DISABLE:
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+
+ if (trx->bts->variant != BTS_OSMO_OMLDUMMY) { /* In OMLDUMMY, phy=NULL */
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ phy_state_connected = phy_link_state_get(pinst->phy_link) == PHY_LINK_CONNECTED;
+ rsl_link_connected = !!trx->rsl_link;
+ } else {
+ phy_state_connected = true;
+ rsl_link_connected = true;
+ }
+
+ if (rsl_link_connected && phy_state_connected &&
+ bb_transc->mo.opstart_success) {
+ nm_bb_transc_fsm_state_chg(fi, NM_BBTRANSC_ST_OP_ENABLED);
+ } else {
+ LOGPFSML(fi, LOGL_INFO, "Delay switch to operative state Enabled, wait for:%s%s%s\n",
+ rsl_link_connected ? "": " rsl",
+ phy_state_connected ? "": " phy",
+ bb_transc->mo.opstart_success ? "": " opstart");
+
+ }
+}
+
+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;
+ oml_mo_state_chg(&bb_transc->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_RSL_DOWN:
+ break;
+ case NM_EV_PHYLINK_DOWN:
+ break;
+ case NM_EV_DISABLE:
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+ nm_bb_transc_fsm_state_chg(fi, NM_BBTRANSC_ST_OP_DISABLED_OFFLINE);
+}
+
+static struct osmo_fsm_state nm_bb_transc_fsm_states[] = {
+ [NM_BBTRANSC_ST_OP_DISABLED_NOTINSTALLED] = {
+ .in_event_mask =
+ X(NM_EV_SW_ACT) |
+ X(NM_EV_RSL_UP) |
+ X(NM_EV_RSL_DOWN) |
+ X(NM_EV_PHYLINK_UP) |
+ X(NM_EV_PHYLINK_DOWN),
+ .out_state_mask =
+ X(NM_BBTRANSC_ST_OP_DISABLED_OFFLINE),
+ .name = "DISABLED_NOTINSTALLED",
+ .onenter = st_op_disabled_notinstalled_on_enter,
+ .action = st_op_disabled_notinstalled,
+ },
+ [NM_BBTRANSC_ST_OP_DISABLED_OFFLINE] = {
+ .in_event_mask =
+ X(NM_EV_OPSTART_ACK) |
+ X(NM_EV_OPSTART_NACK) |
+ X(NM_EV_RSL_UP) |
+ X(NM_EV_RSL_DOWN) |
+ X(NM_EV_PHYLINK_UP) |
+ X(NM_EV_PHYLINK_DOWN),
+ .out_state_mask =
+ X(NM_BBTRANSC_ST_OP_ENABLED),
+ .name = "DISABLED_OFFLINE",
+ .onenter = st_op_disabled_offline_on_enter,
+ .action = st_op_disabled_offline,
+ },
+ [NM_BBTRANSC_ST_OP_ENABLED] = {
+ .in_event_mask =
+ X(NM_EV_RSL_DOWN) |
+ X(NM_EV_PHYLINK_DOWN),
+ .out_state_mask =
+ X(NM_BBTRANSC_ST_OP_DISABLED_OFFLINE),
+ .name = "ENABLED",
+ .onenter = st_op_enabled_on_enter,
+ .action = st_op_enabled,
+ },
+};
+
+struct osmo_fsm nm_bb_transc_fsm = {
+ .name = "NM_BBTRANSC_OP",
+ .states = nm_bb_transc_fsm_states,
+ .num_states = ARRAY_SIZE(nm_bb_transc_fsm_states),
+ .event_names = nm_fsm_event_names,
+ .log_subsys = DOML,
+};
+
+static __attribute__((constructor)) void nm_bb_transc_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&nm_bb_transc_fsm) == 0);
+}
diff --git a/src/common/nm_common_fsm.c b/src/common/nm_common_fsm.c
index 662a7602..88045699 100644
--- a/src/common/nm_common_fsm.c
+++ b/src/common/nm_common_fsm.c
@@ -27,5 +27,10 @@ const struct value_string nm_fsm_event_names[] = {
{ NM_EV_SW_ACT, "SW_ACT" },
{ NM_EV_OPSTART_ACK, "OPSTART_ACK" },
{ NM_EV_OPSTART_NACK, "OPSTART_NACK" },
+ { NM_EV_RSL_UP, "RSL_UP" },
+ { NM_EV_RSL_DOWN, "RSL_DOWN" },
+ { NM_EV_PHYLINK_UP, "PHYLINK_UP" },
+ { NM_EV_PHYLINK_DOWN, "PHYLINK_DOWN" },
+ { NM_EV_DISABLE, "DISABLE" },
{ 0, NULL }
};
diff --git a/src/common/nm_radio_carrier_fsm.c b/src/common/nm_radio_carrier_fsm.c
new file mode 100644
index 00000000..01849d1e
--- /dev/null
+++ b/src/common/nm_radio_carrier_fsm.c
@@ -0,0 +1,218 @@
+/* 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>
+#include <osmo-bts/phy_link.h>
+
+#define X(s) (1 << (s))
+
+#define nm_rcarrier_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 *trx = (struct gsm_bts_trx *)fi->priv;
+ trx->mo.opstart_success = false;
+ oml_mo_state_chg(&trx->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 *trx = (struct gsm_bts_trx *)fi->priv;
+
+ switch (event) {
+ case NM_EV_SW_ACT:
+ oml_mo_tx_sw_act_rep(&trx->mo);
+ nm_rcarrier_fsm_state_chg(fi, NM_RCARRIER_ST_OP_DISABLED_OFFLINE);
+ return;
+ case NM_EV_RSL_UP:
+ return;
+ case NM_EV_RSL_DOWN:
+ return;
+ case NM_EV_PHYLINK_UP:
+ return;
+ case NM_EV_PHYLINK_DOWN:
+ return;
+ case NM_EV_DISABLE:
+ 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 *trx = (struct gsm_bts_trx *)fi->priv;
+ trx->mo.opstart_success = false;
+ oml_mo_state_chg(&trx->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 *trx = (struct gsm_bts_trx *)fi->priv;
+ bool phy_state_connected;
+ bool rsl_link_connected;
+
+ switch (event) {
+ case NM_EV_OPSTART_ACK:
+ trx->mo.opstart_success = true;
+ oml_mo_opstart_ack(&trx->mo);
+ break; /* check statechg below */
+ case NM_EV_OPSTART_NACK:
+ trx->mo.opstart_success = false;
+ oml_mo_opstart_nack(&trx->mo, (int)(intptr_t)data);
+ return;
+ case NM_EV_RSL_UP:
+ break; /* check statechg below */
+ case NM_EV_RSL_DOWN:
+ return;
+ case NM_EV_PHYLINK_UP:
+ break; /* check statechg below */
+ case NM_EV_PHYLINK_DOWN:
+ return;
+ case NM_EV_DISABLE:
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+ if (trx->bts->variant != BTS_OSMO_OMLDUMMY) { /* In OMLDUMMY, phy=NULL */
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ phy_state_connected = phy_link_state_get(pinst->phy_link) == PHY_LINK_CONNECTED;
+ rsl_link_connected = !!trx->rsl_link;
+ } else {
+ phy_state_connected = true;
+ rsl_link_connected = true;
+ }
+
+ if (rsl_link_connected && phy_state_connected &&
+ trx->mo.opstart_success) {
+ nm_rcarrier_fsm_state_chg(fi, NM_RCARRIER_ST_OP_ENABLED);
+ } else {
+ LOGPFSML(fi, LOGL_INFO, "Delay switch to operative state Enabled, wait for:%s%s%s\n",
+ rsl_link_connected ? "": " rsl",
+ phy_state_connected ? "": " phy",
+ trx->mo.opstart_success ? "": " opstart");
+
+ }
+}
+
+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)
+{
+ switch (event) {
+ case NM_EV_RSL_DOWN:
+ break;
+ case NM_EV_PHYLINK_DOWN:
+ break;
+ case NM_EV_DISABLE:
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+ nm_rcarrier_fsm_state_chg(fi, NM_RCARRIER_ST_OP_DISABLED_OFFLINE);
+}
+
+static struct osmo_fsm_state nm_rcarrier_fsm_states[] = {
+ [NM_RCARRIER_ST_OP_DISABLED_NOTINSTALLED] = {
+ .in_event_mask =
+ X(NM_EV_SW_ACT) |
+ X(NM_EV_RSL_UP) |
+ X(NM_EV_RSL_DOWN) |
+ X(NM_EV_PHYLINK_UP) |
+ X(NM_EV_PHYLINK_DOWN),
+ .out_state_mask =
+ X(NM_RCARRIER_ST_OP_DISABLED_OFFLINE),
+ .name = "DISABLED_NOTINSTALLED",
+ .onenter = st_op_disabled_notinstalled_on_enter,
+ .action = st_op_disabled_notinstalled,
+ },
+ [NM_RCARRIER_ST_OP_DISABLED_OFFLINE] = {
+ .in_event_mask =
+ X(NM_EV_OPSTART_ACK) |
+ X(NM_EV_OPSTART_NACK) |
+ X(NM_EV_RSL_UP) |
+ X(NM_EV_RSL_DOWN) |
+ X(NM_EV_PHYLINK_UP) |
+ X(NM_EV_PHYLINK_DOWN),
+ .out_state_mask =
+ X(NM_RCARRIER_ST_OP_ENABLED),
+ .name = "DISABLED_OFFLINE",
+ .onenter = st_op_disabled_offline_on_enter,
+ .action = st_op_disabled_offline,
+ },
+ [NM_RCARRIER_ST_OP_ENABLED] = {
+ .in_event_mask =
+ X(NM_EV_RSL_DOWN) |
+ X(NM_EV_PHYLINK_DOWN),
+ .out_state_mask =
+ X(NM_RCARRIER_ST_OP_DISABLED_OFFLINE),
+ .name = "ENABLED",
+ .onenter = st_op_enabled_on_enter,
+ .action = st_op_enabled,
+ },
+};
+
+struct osmo_fsm nm_rcarrier_fsm = {
+ .name = "NM_RCARRIER_OP",
+ .states = nm_rcarrier_fsm_states,
+ .num_states = ARRAY_SIZE(nm_rcarrier_fsm_states),
+ .event_names = nm_fsm_event_names,
+ .log_subsys = DOML,
+};
+
+static __attribute__((constructor)) void nm_rcarrier_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&nm_rcarrier_fsm) == 0);
+}
diff --git a/src/common/phy_link.c b/src/common/phy_link.c
index 48ba283e..77d7aa62 100644
--- a/src/common/phy_link.c
+++ b/src/common/phy_link.c
@@ -2,6 +2,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
+#include <osmocom/core/fsm.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/gsm_data.h>
@@ -9,6 +10,7 @@
#include <osmo-bts/oml.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/bts_model.h>
+#include <osmo-bts/nm_common_fsm.h>
static LLIST_HEAD(g_phy_links);
@@ -65,7 +67,14 @@ void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
if (!trx)
continue;
- trx_operability_update(trx);
+ osmo_fsm_inst_dispatch(trx->mo.fi,
+ state == PHY_LINK_CONNECTED ? NM_EV_PHYLINK_UP :
+ NM_EV_PHYLINK_DOWN,
+ NULL);
+ osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi,
+ state == PHY_LINK_CONNECTED ? NM_EV_PHYLINK_UP :
+ NM_EV_PHYLINK_DOWN,
+ NULL);
}
}