aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/lchan_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bsc/lchan_fsm.c')
-rw-r--r--src/osmo-bsc/lchan_fsm.c142
1 files changed, 72 insertions, 70 deletions
diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c
index 6a95d4c57..9181b322c 100644
--- a/src/osmo-bsc/lchan_fsm.c
+++ b/src/osmo-bsc/lchan_fsm.c
@@ -151,7 +151,7 @@ static void lchan_on_fully_established(struct gsm_lchan *lchan)
return;
lchan->activate.concluded = true;
- switch (lchan->activate.activ_for) {
+ switch (lchan->activate.info.activ_for) {
case FOR_MS_CHANNEL_REQUEST:
/* No signalling to do here, MS is free to use the channel, and should go on to connect
* to the MSC and establish a subscriber connection. */
@@ -201,7 +201,7 @@ static void lchan_on_fully_established(struct gsm_lchan *lchan)
default:
LOG_LCHAN(lchan, LOGL_NOTICE, "lchan %s fully established\n",
- lchan_activate_mode_name(lchan->activate.activ_for));
+ lchan_activate_mode_name(lchan->activate.info.activ_for));
break;
}
}
@@ -238,7 +238,7 @@ struct state_timeout lchan_fsm_timeouts[32] = {
lchan_set_last_error(_lchan, "lchan %s in state %s: " fmt, \
_lchan->activate.concluded ? "failure" : "allocation failed", \
osmo_fsm_state_name(fsm, state_was), ## args); \
- lchan_on_activation_failure(_lchan, _lchan->activate.activ_for, _lchan->conn); \
+ lchan_on_activation_failure(_lchan, _lchan->activate.info.activ_for, _lchan->conn); \
if (fi->state != state_chg) \
lchan_fsm_state_chg(state_chg); \
else \
@@ -495,8 +495,6 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat
{
struct lchan_activate_info *info = data;
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
- struct gsm_bts *bts = lchan->ts->trx->bts;
- struct gsm48_multi_rate_conf mr_conf;
switch (event) {
@@ -507,63 +505,8 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat
lchan_set_last_error(lchan, NULL);
lchan->release.requested = false;
- lchan->conn = info->for_conn;
- lchan->activate.activ_for = info->activ_for;
- lchan->activate.requires_voice_stream = info->requires_voice_stream;
- lchan->activate.wait_before_switching_rtp = info->wait_before_switching_rtp;
- lchan->activate.msc_assigned_cic = info->msc_assigned_cic;
+ lchan->activate.info = *info;
lchan->activate.concluded = false;
- lchan->activate.re_use_mgw_endpoint_from_lchan = info->old_lchan;
-
- if (info->old_lchan)
- lchan->encr = info->old_lchan->encr;
- else {
- lchan->encr = (struct gsm_encr){
- .alg_id = RSL_ENC_ALG_A5(0), /* no encryption */
- };
- }
-
- /* If there is a previous lchan, and the new lchan is on the same cell as previous one,
- * take over power and TA values. Otherwise, use max power and zero TA. */
- if (info->old_lchan && info->old_lchan->ts->trx->bts == bts) {
- lchan->ms_power = info->old_lchan->ms_power;
- lchan->bs_power = info->old_lchan->bs_power;
- lchan->rqd_ta = info->old_lchan->rqd_ta;
- } else {
- lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
- /* From lchan_reset():
- * - bs_power is still zero, 0dB reduction, output power = Pn.
- * - TA is still zero, to be determined by RACH. */
- }
-
- if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) {
- gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0);
- if (lchan_mr_config(lchan, &mr_conf) < 0) {
- lchan_fail("Can not generate multirate configuration IE\n");
- return;
- }
- }
-
- switch (info->chan_mode) {
-
- case GSM48_CMODE_SIGN:
- lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
- lchan->tch_mode = GSM48_CMODE_SIGN;
- break;
-
- case GSM48_CMODE_SPEECH_V1:
- case GSM48_CMODE_SPEECH_EFR:
- case GSM48_CMODE_SPEECH_AMR:
- lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
- lchan->tch_mode = info->chan_mode;
- break;
-
- default:
- lchan_fail("Not implemented: cannot activate for chan mode %s",
- gsm48_chan_mode_name(info->chan_mode));
- return;
- }
-
lchan_fsm_state_chg(LCHAN_ST_WAIT_TS_READY);
break;
@@ -575,18 +518,75 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat
static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
- struct mgwep_ci *use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);
+ struct gsm48_multi_rate_conf mr_conf;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct mgwep_ci *use_mgwep_ci;
+ struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;
+ struct lchan_activate_info *info = &lchan->activate.info;
if (lchan->release.requested) {
lchan_fail("Release requested while activating");
return;
}
+ lchan->conn = info->for_conn;
+
+ if (old_lchan)
+ lchan->encr = old_lchan->encr;
+ else {
+ lchan->encr = (struct gsm_encr){
+ .alg_id = RSL_ENC_ALG_A5(0), /* no encryption */
+ };
+ }
+
+ /* If there is a previous lchan, and the new lchan is on the same cell as previous one,
+ * take over power and TA values. Otherwise, use max power and zero TA. */
+ if (old_lchan && old_lchan->ts->trx->bts == bts) {
+ lchan->ms_power = old_lchan->ms_power;
+ lchan->bs_power = old_lchan->bs_power;
+ lchan->rqd_ta = old_lchan->rqd_ta;
+ } else {
+ lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
+ /* From lchan_reset():
+ * - bs_power is still zero, 0dB reduction, output power = Pn.
+ * - TA is still zero, to be determined by RACH. */
+ }
+
+ if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) {
+ gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0);
+ if (lchan_mr_config(lchan, &mr_conf) < 0) {
+ lchan_fail("Can not generate multirate configuration IE\n");
+ return;
+ }
+ }
+
+ switch (info->chan_mode) {
+
+ case GSM48_CMODE_SIGN:
+ lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
+ lchan->tch_mode = GSM48_CMODE_SIGN;
+ break;
+
+ case GSM48_CMODE_SPEECH_V1:
+ case GSM48_CMODE_SPEECH_EFR:
+ case GSM48_CMODE_SPEECH_AMR:
+ lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
+ lchan->tch_mode = info->chan_mode;
+ break;
+
+ default:
+ lchan_fail("Not implemented: cannot activate for chan mode %s",
+ gsm48_chan_mode_name(info->chan_mode));
+ return;
+ }
+
+ use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);
+
LOG_LCHAN(lchan, LOGL_INFO,
"Activation requested: %s voice=%s MGW-ci=%s type=%s tch-mode=%s\n",
- lchan_activate_mode_name(lchan->activate.activ_for),
- lchan->activate.requires_voice_stream ? "yes" : "no",
- lchan->activate.requires_voice_stream ?
+ lchan_activate_mode_name(lchan->activate.info.activ_for),
+ lchan->activate.info.requires_voice_stream ? "yes" : "no",
+ lchan->activate.info.requires_voice_stream ?
(use_mgwep_ci ? mgwep_ci_name(use_mgwep_ci) : "new")
: "none",
gsm_lchant_name(lchan->type),
@@ -597,7 +597,7 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p
osmo_fsm_inst_dispatch(lchan->ts->fi, TS_EV_LCHAN_REQUESTED, lchan);
/* Prepare an MGW endpoint CI if appropriate. */
- if (lchan->activate.requires_voice_stream)
+ if (lchan->activate.info.requires_voice_stream)
lchan_rtp_fsm_start(lchan);
}
@@ -641,7 +641,7 @@ static void lchan_fsm_wait_activ_ack_onenter(struct osmo_fsm_inst *fi, uint32_t
return;
}
- switch (lchan->activate.activ_for) {
+ switch (lchan->activate.info.activ_for) {
case FOR_MS_CHANNEL_REQUEST:
act_type = RSL_ACT_INTRA_IMM_ASS;
break;
@@ -723,7 +723,7 @@ static void lchan_fsm_post_activ_ack(struct osmo_fsm_inst *fi)
return;
}
- switch (lchan->activate.activ_for) {
+ switch (lchan->activate.info.activ_for) {
case FOR_MS_CHANNEL_REQUEST:
rc = rsl_tx_imm_assignment(lchan);
@@ -778,7 +778,7 @@ static void lchan_fsm_post_activ_ack(struct osmo_fsm_inst *fi)
default:
LOG_LCHAN(lchan, LOGL_NOTICE, "lchan %s is now active\n",
- lchan_activate_mode_name(lchan->activate.activ_for));
+ lchan_activate_mode_name(lchan->activate.info.activ_for));
break;
}
@@ -798,7 +798,7 @@ static void lchan_fsm_wait_rll_rtp_establish(struct osmo_fsm_inst *fi, uint32_t
switch (event) {
case LCHAN_EV_RLL_ESTABLISH_IND:
- if (!lchan->activate.requires_voice_stream
+ if (!lchan->activate.info.requires_voice_stream
|| lchan_rtp_established(lchan))
lchan_fsm_state_chg(LCHAN_ST_ESTABLISHED);
return;
@@ -1395,6 +1395,8 @@ void lchan_forget_conn(struct gsm_lchan *lchan)
if (!lchan)
return;
+ lchan->activate.info.for_conn = NULL;
+
conn = lchan->conn;
if (conn) {
/* Log for both lchan FSM and conn FSM to ease reading the log in case of problems */