summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2018-01-04 01:26:34 +0100
committerVadim Yanitskiy <axilirator@gmail.com>2018-01-05 14:35:29 +0700
commit5c70e48077352d35b86aec733dda59d05aab1e01 (patch)
tree5196621d4007dd1ac953242e4709a423a174056c
parent96da00d45766d43c919d059fb94e9106cff33f2b (diff)
trxcon/scheduler: reset lchan state after deactivation
Let's assume that a logical channel, which was already in use, is activated again for a new connection. As we don't reset the state variables, such as burst masks or ciphering data, it may cause an unexpected behaviour. In order to avoid this, let's always reset the logical channel state after deactivation. Change-Id: I91e736a97cb05b167614cb488a00d847a9a859e0
-rw-r--r--src/host/trxcon/sched_trx.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c
index 120098b..2142119 100644
--- a/src/host/trxcon/sched_trx.c
+++ b/src/host/trxcon/sched_trx.c
@@ -406,6 +406,42 @@ int sched_trx_activate_lchan(struct trx_ts *ts, enum trx_lchan_type chan)
return 0;
}
+static void sched_trx_reset_lchan(struct trx_lchan_state *lchan)
+{
+ /* Prevent NULL-pointer deference */
+ OSMO_ASSERT(lchan != NULL);
+
+ /* Reset internal state variables */
+ lchan->rx_burst_mask = 0x00;
+ lchan->tx_burst_mask = 0x00;
+ lchan->rx_first_fn = 0;
+
+ /* Free burst memory */
+ talloc_free(lchan->rx_bursts);
+ talloc_free(lchan->tx_bursts);
+
+ lchan->rx_bursts = NULL;
+ lchan->tx_bursts = NULL;
+
+ /* Forget the current prim */
+ sched_prim_drop(lchan);
+
+ /* TCH specific variables */
+ if (CHAN_IS_TCH(lchan->type)) {
+ lchan->dl_ongoing_facch = 0;
+ lchan->ul_ongoing_facch = 0;
+
+ lchan->rsl_cmode = 0x00;
+ lchan->tch_mode = 0x00;
+
+ /* Reset AMR state */
+ memset(&lchan->amr, 0x00, sizeof(lchan->amr));
+ }
+
+ /* Reset ciphering state */
+ memset(&lchan->a5, 0x00, sizeof(lchan->a5));
+}
+
int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan)
{
struct trx_lchan_state *lchan;
@@ -424,16 +460,10 @@ int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan)
LOGP(DSCH, LOGL_DEBUG, "Deactivating lchan=%s "
"on ts=%d\n", trx_lchan_desc[chan].name, ts->index);
- /* Free memory */
- talloc_free(lchan->rx_bursts);
- talloc_free(lchan->tx_bursts);
-
- /* Reset ciphering state */
- memset(&lchan->a5, 0x00, sizeof(lchan->a5));
-
- /* Forget the current prim */
- sched_prim_drop(lchan);
+ /* Reset internal state, free memory */
+ sched_trx_reset_lchan(lchan);
+ /* Update activation flag */
lchan->active = 0;
return 0;
@@ -451,12 +481,14 @@ void sched_trx_deactivate_all_lchans(struct trx_ts *ts)
for (i = 0; i < len; i++) {
lchan = ts->lchans + i;
- talloc_free(lchan->rx_bursts);
- talloc_free(lchan->tx_bursts);
+ /* Omit inactive channels */
+ if (!lchan->active)
+ continue;
- /* Forget the current prim */
- sched_prim_drop(lchan);
+ /* Reset internal state, free memory */
+ sched_trx_reset_lchan(lchan);
+ /* Update activation flag */
lchan->active = 0;
}
}