aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libbsc/abis_rsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/libbsc/abis_rsl.c')
-rw-r--r--openbsc/src/libbsc/abis_rsl.c52
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;
+}