aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/chan_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/chan_alloc.c')
-rw-r--r--openbsc/src/chan_alloc.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 27d582931..b5497bcb8 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -33,6 +33,29 @@
#include <openbsc/debug.h>
#include <openbsc/signal.h>
+static int ts_is_usable(struct gsm_bts_trx_ts *ts)
+{
+ /* FIXME: How does this behave for BS-11 ? */
+ if (is_ipaccess_bts(ts->trx->bts)) {
+ if (!nm_is_running(&ts->nm_state))
+ return 0;
+ }
+
+ return 1;
+}
+
+int trx_is_usable(struct gsm_bts_trx *trx)
+{
+ /* FIXME: How does this behave for BS-11 ? */
+ if (is_ipaccess_bts(trx->bts)) {
+ if (!nm_is_running(&trx->nm_state) ||
+ !nm_is_running(&trx->bb_transc.nm_state))
+ return 0;
+ }
+
+ return 1;
+}
+
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
enum gsm_phys_chan_config pchan)
{
@@ -61,6 +84,9 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
llist_for_each_entry(trx, &bts->trx_list, list) {
int from, to;
+ if (!trx_is_usable(trx))
+ continue;
+
/* the following constraints are pure policy,
* no requirement to put this restriction in place */
if (trx == bts->c0) {
@@ -95,6 +121,10 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
for (j = from; j <= to; j++) {
struct gsm_bts_trx_ts *ts = &trx->ts[j];
+
+ if (!ts_is_usable(ts))
+ continue;
+
if (ts->pchan == GSM_PCHAN_NONE) {
ts->pchan = pchan;
/* set channel attribute on OML */
@@ -119,6 +149,7 @@ static const u_int8_t subslots_per_pchan[] = {
[GSM_PCHAN_TCH_F] = 1,
[GSM_PCHAN_TCH_H] = 2,
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
+ /* FIXME: what about dynamic TCH_F_TCH_H ? */
};
static struct gsm_lchan *
@@ -127,14 +158,20 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
struct gsm_bts_trx_ts *ts;
int j, ss;
+ if (!trx_is_usable(trx))
+ return NULL;
+
for (j = 0; j < 8; j++) {
ts = &trx->ts[j];
+ if (!ts_is_usable(ts))
+ continue;
if (ts->pchan != pchan)
continue;
/* check if all sub-slots are allocated yet */
for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) {
struct gsm_lchan *lc = &ts->lchan[ss];
- if (lc->type == GSM_LCHAN_NONE)
+ if (lc->type == GSM_LCHAN_NONE &&
+ lc->state == LCHAN_S_NONE)
return lc;
}
}
@@ -256,6 +293,8 @@ void lchan_free(struct gsm_lchan *lchan)
}
for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
lchan->neigh_meas[i].arfcn = 0;
+ lchan->silent_call = 0;
+
/* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */
}
@@ -280,7 +319,7 @@ int _lchan_release(struct gsm_lchan *lchan)
LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n",
lchan->use_count);
- DEBUGP(DRLL, "Recycling the channel with: %d (%x)\n", lchan->nr, lchan->nr);
+ DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
rsl_release_request(lchan, 0);
return 1;
}
@@ -317,3 +356,51 @@ struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr)
return NULL;
}
+
+void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts)
+{
+ struct gsm_bts_trx *trx;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ int i;
+
+ /* skip administratively deactivated tranxsceivers */
+ if (!nm_is_running(&trx->nm_state) ||
+ !nm_is_running(&trx->bb_transc.nm_state))
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ struct load_counter *pl = &cl->pchan[ts->pchan];
+ int j;
+
+ /* skip administratively deactivated timeslots */
+ if (!nm_is_running(&ts->nm_state))
+ continue;
+
+ for (j = 0; j < subslots_per_pchan[ts->pchan]; j++) {
+ struct gsm_lchan *lchan = &ts->lchan[j];
+
+ pl->total++;
+
+ switch (lchan->state) {
+ case LCHAN_S_NONE:
+ break;
+ default:
+ pl->used++;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void network_chan_load(struct pchan_load *pl, struct gsm_network *net)
+{
+ struct gsm_bts *bts;
+
+ memset(pl, 0, sizeof(*pl));
+
+ llist_for_each_entry(bts, &net->bts_list, list)
+ bts_chan_load(pl, bts);
+}