diff options
Diffstat (limited to 'openbsc/src/chan_alloc.c')
-rw-r--r-- | openbsc/src/chan_alloc.c | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 4274697e8..5ca47f909 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -150,6 +150,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 * @@ -165,7 +166,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++) { @@ -175,6 +183,7 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) return lc; } } + return NULL; } @@ -250,7 +259,6 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) if (lchan) { lchan->type = type; - lchan->use_count = 0; /* clear sapis */ memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis)); @@ -261,6 +269,15 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) /* clear any msc reference */ lchan->msc_data = NULL; + /* clear per MSC/BSC data */ + memset(&lchan->conn, 0, sizeof(lchan->conn)); + lchan->conn.lchan = lchan; + lchan->conn.bts = lchan->ts->trx->bts; + } else { + struct challoc_signal_data sig; + sig.bts = bts; + sig.type = type; + dispatch_signal(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig); } return lchan; @@ -269,18 +286,20 @@ 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->subscr) { - subscr_put(lchan->subscr); - lchan->subscr = NULL; + if (lchan->conn.subscr) { + subscr_put(lchan->conn.subscr); + lchan->conn.subscr = NULL; } /* We might kill an active channel... */ - if (lchan->use_count != 0) { + if (lchan->conn.use_count != 0) { dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); - lchan->use_count = 0; + lchan->conn.use_count = 0; } bsc_del_timer(&lchan->T3101); @@ -293,7 +312,11 @@ 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; + 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 */ @@ -302,22 +325,22 @@ void lchan_free(struct gsm_lchan *lchan) /* Consider releasing the channel now */ int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) { - if (lchan->use_count > 0) { + if (lchan->conn.use_count > 0) { DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n"); return 0; } /* Assume we have GSM04.08 running and send a release */ - if (lchan->subscr) { - ++lchan->use_count; + if (lchan->conn.subscr) { + ++lchan->conn.use_count; gsm48_send_rr_release(lchan); - --lchan->use_count; + --lchan->conn.use_count; } /* spoofed? message */ - if (lchan->use_count < 0) + if (lchan->conn.use_count < 0) LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", - lchan->use_count); + lchan->conn.use_count); DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_release_request(lchan, 0, release_reason); @@ -326,14 +349,14 @@ int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { struct gsm_bts_trx *trx; - int ts_no, lchan_no; + int ts_no, lchan_no; llist_for_each_entry(trx, &bts->trx_list, list) { for (ts_no = 0; ts_no < 8; ++ts_no) { for (lchan_no = 0; lchan_no < TS_MAX_LCHAN; ++lchan_no) { struct gsm_lchan *lchan = &trx->ts[ts_no].lchan[lchan_no]; - if (subscr == lchan->subscr) + if (subscr == lchan->conn.subscr) return lchan; } } |