aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-03-28 15:58:03 +0800
committerHarald Welte <laforge@gnumonks.org>2010-03-28 15:58:03 +0800
commitc0d83b0647cc77970fd072aa77225ac70374f786 (patch)
tree12303782dcb7afea38f116a8681e79601ce17f9c /openbsc
parent4563eab30ef10be8447c53301d96b949a5af3f5f (diff)
chan_alloc: Support allocating TCH/F of a dynamic TCH/F + PDCH
This code simply enables the channel allocator to understand the dynamic TCH/F / PDCH channel type as used by ip.access nanoBTS. It does not actually try to switch the dynamic mode, but instead sends signals to a (not yet present) dynamic switching algorithm.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/signal.h13
-rw-r--r--openbsc/src/chan_alloc.c22
2 files changed, 34 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h
index 0c22869f6..1b974e288 100644
--- a/openbsc/include/openbsc/signal.h
+++ b/openbsc/include/openbsc/signal.h
@@ -42,6 +42,7 @@ enum signal_subsystems {
SS_SUBSCR,
SS_SCALL,
SS_GLOBAL,
+ SS_CHALLOC,
};
/* SS_PAGING signals */
@@ -93,6 +94,12 @@ enum signal_lchan {
S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */
};
+/* SS_CHALLOC signals */
+enum signal_challoc {
+ S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */
+ S_CHALLOC_FREED, /* lchan has been successfully freed */
+};
+
/* SS_SUBSCR signals */
enum signal_subscr {
S_SUBSCR_ATTACHED,
@@ -130,4 +137,10 @@ struct ipacc_ack_signal_data {
u_int8_t msg_type;
};
+struct challoc_signal_data {
+ struct gsm_bts *bts;
+ struct gsm_lchan *lchan;
+ enum gsm_chan_t type;
+};
+
#endif
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index c8e358dc8..a986bb38e 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -152,6 +152,7 @@ static const u_int8_t subslots_per_pchan[] = {
[GSM_PCHAN_TCH_H] = 2,
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
/* FIXME: what about dynamic TCH_F_TCH_H ? */
+ [GSM_PCHAN_TCH_F_PDCH] = 1,
};
static struct gsm_lchan *
@@ -167,7 +168,14 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
ts = &trx->ts[j];
if (!ts_is_usable(ts))
continue;
- if (ts->pchan != pchan)
+ /* ip.access dynamic TCH/F + PDCH combination */
+ if (ts->pchan == GSM_PCHAN_TCH_F_PDCH &&
+ pchan == GSM_PCHAN_TCH_F) {
+ /* we can only consider such a dynamic channel
+ * if the PDCH is currently inactive */
+ if (ts->flags & TS_F_PDCH_MODE)
+ continue;
+ } else if (ts->pchan != pchan)
continue;
/* check if all sub-slots are allocated yet */
for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) {
@@ -177,6 +185,7 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
return lc;
}
}
+
return NULL;
}
@@ -269,6 +278,11 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
lchan->conn.release_timer.data = lchan;
bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
+ } else {
+ struct challoc_signal_data sig;
+ sig.bts = bts;
+ sig.type = type;
+ dispatch_signal(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig);
}
return lchan;
@@ -277,8 +291,10 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
/* Free a logical channel */
void lchan_free(struct gsm_lchan *lchan)
{
+ struct challoc_signal_data sig;
int i;
+ sig.type = lchan->type;
lchan->type = GSM_LCHAN_NONE;
if (lchan->conn.subscr) {
subscr_put(lchan->conn.subscr);
@@ -306,6 +322,10 @@ void lchan_free(struct gsm_lchan *lchan)
lchan->conn.silent_call = 0;
+ sig.lchan = lchan;
+ sig.bts = lchan->ts->trx->bts;
+ dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig);
+
/* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */
}