diff options
Diffstat (limited to 'openbsc/src/libbsc/abis_rsl.c')
-rw-r--r-- | openbsc/src/libbsc/abis_rsl.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 04d5c61b3..6e1ce7852 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -46,6 +46,11 @@ #define RSL_ALLOC_SIZE 1024 #define RSL_ALLOC_HEADROOM 128 +enum sacch_deact { + SACCH_NONE, + SACCH_DEACTIVATE, +}; + static int rsl_send_imm_assignment(struct gsm_lchan *lchan); static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan, @@ -644,12 +649,16 @@ static void error_timeout_cb(void *data) static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan); /* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */ -static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) +static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error, + enum sacch_deact deact_sacch) { struct abis_rsl_dchan_hdr *dh; struct msgb *msg; int rc; + /* Stop timers that should lead to a channel release */ + osmo_timer_del(&lchan->T3109); + if (lchan->state == LCHAN_S_REL_ERR) { LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n", gsm_lchan_name(lchan)); @@ -688,7 +697,8 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) /* * sacch de-activate and "local end release" */ - rsl_deact_sacch(lchan); + if (deact_sacch == SACCH_DEACTIVATE) + rsl_deact_sacch(lchan); rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END); /* @@ -939,7 +949,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN); else - rsl_rf_chan_release(msg->lchan, 1); + rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE); } else rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN); @@ -969,7 +979,7 @@ static int rsl_rx_conn_fail(struct msgb *msg) LOGPC(DRSL, LOGL_NOTICE, "\n"); /* FIXME: only free it after channel release ACK */ osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail); - return rsl_rf_chan_release(msg->lchan, 1); + return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE); } static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru, @@ -1250,7 +1260,7 @@ static void t3101_expired(void *data) { struct gsm_lchan *lchan = data; - rsl_rf_chan_release(lchan, 1); + rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE); } /* If T3111 expires, we will send the RF Channel Request */ @@ -1258,7 +1268,17 @@ static void t3111_expired(void *data) { struct gsm_lchan *lchan = data; - rsl_rf_chan_release(lchan, 0); + rsl_rf_chan_release(lchan, 0, SACCH_NONE); +} + +/* If T3109 expires the MS has not send a UA/UM do the error release */ +static void t3109_expired(void *data) +{ + struct gsm_lchan *lchan = data; + + LOGP(DRSL, LOGL_ERROR, + "%s SACCH deactivation timeout.\n", gsm_lchan_name(lchan)); + rsl_rf_chan_release(lchan, 1, SACCH_NONE); } #define GSM48_LEN2PLEN(a) (((a) << 2) | 1) @@ -1516,7 +1536,7 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) { osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err); - return rsl_rf_chan_release(msg->lchan, 1); + return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE); } return 0; @@ -1544,8 +1564,8 @@ static void rsl_handle_release(struct gsm_lchan *lchan) } - - /* wait a bit to send the RF Channel Release */ + /* Stop T3109 and wait for T3111 before re-using the channel */ + osmo_timer_del(&lchan->T3109); lchan->T3111.cb = t3111_expired; lchan->T3111.data = lchan; bts = lchan->ts->trx->bts; @@ -2107,3 +2127,17 @@ int rsl_release_sapis_from(struct gsm_lchan *lchan, int start, return no_sapi; } + +int rsl_start_t3109(struct gsm_lchan *lchan) +{ + struct gsm_bts *bts = lchan->ts->trx->bts; + + /* Disabled, mostly legacy code */ + if (bts->network->T3109 == 0) + return -1; + + lchan->T3109.cb = t3109_expired; + lchan->T3109.data = lchan; + osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0); + return 0; +} |