diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-06-28 15:47:12 +0800 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-06-28 16:12:39 +0800 |
commit | 2412a07965ace5fc425b401438d21ff86ceeb2df (patch) | |
tree | 43f862deafccf9500b8f81621862a708b144f6c7 /openbsc/src/chan_alloc.c | |
parent | 94d625bfa09be748aa1a157da8320bd75761d431 (diff) |
bsc_api: Allocate the subscriber_connection dynamically
This is a big change to the way we use the subscriber
connection. From now on it is is dynamically allocated
and we will slowly move from a 1:1 lchan to conn to
having more than one lchan per connection.
This is the first commit, the subscr_con* methods will
move to gsm_data once the use_count is removed from the
connection, the freeing of the connection will also change.
Diffstat (limited to 'openbsc/src/chan_alloc.c')
-rw-r--r-- | openbsc/src/chan_alloc.c | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 8115d8719..f5c4ec65e 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -271,15 +271,10 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf)); /* clear per MSC/BSC data */ - memset(&lchan->conn, 0, sizeof(lchan->conn)); - - /* Configure the time and start it so it will be closed */ - lchan->conn.lchan = lchan; - lchan->conn.bts = lchan->ts->trx->bts; - lchan->conn.release_timer.cb = auto_release_channel; - lchan->conn.release_timer.data = lchan; - bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); - + if (lchan->conn) { + LOGP(DRLL, LOGL_ERROR, "lchan->conn should be NULL.\n"); + subscr_con_free(lchan->conn); + } } else { struct challoc_signal_data sig; sig.bts = bts; @@ -298,19 +293,25 @@ void lchan_free(struct gsm_lchan *lchan) sig.type = lchan->type; lchan->type = GSM_LCHAN_NONE; - if (lchan->conn.subscr) { - subscr_put(lchan->conn.subscr); - lchan->conn.subscr = NULL; - } - /* We might kill an active channel... */ - if (lchan->conn.use_count != 0) { - dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); - lchan->conn.use_count = 0; + + if (lchan->conn) { + if (lchan->conn->subscr) { + subscr_put(lchan->conn->subscr); + lchan->conn->subscr = NULL; + } + + /* We might kill an active channel... */ + if (lchan->conn->use_count != 0) { + dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); + lchan->conn->use_count = 0; + } + /* stop the timer */ + bsc_del_timer(&lchan->conn->release_timer); } + /* stop the timer */ - bsc_del_timer(&lchan->conn.release_timer); bsc_del_timer(&lchan->T3101); /* clear cached measuement reports */ @@ -328,12 +329,15 @@ void lchan_free(struct gsm_lchan *lchan) lchan->rqd_ta = 0; } - lchan->conn.silent_call = 0; - sig.lchan = lchan; sig.bts = lchan->ts->trx->bts; dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig); + if (lchan->conn) { + subscr_con_free(lchan->conn); + lchan->conn = NULL; + } + /* FIXME: ts_free() the timeslot, if we're the last logical * channel using it */ } @@ -362,19 +366,22 @@ void lchan_reset(struct gsm_lchan *lchan) /* Consider releasing the channel now */ int lchan_auto_release(struct gsm_lchan *lchan) { - if (lchan->conn.use_count > 0) { + if (!lchan->conn) + return 0; + + if (lchan->conn->use_count > 0) { return 0; } /* Assume we have GSM04.08 running and send a release */ - if (lchan->conn.subscr) { + if (lchan->conn->subscr) { gsm48_send_rr_release(lchan); } /* spoofed? message */ - if (lchan->conn.use_count < 0) + if (lchan->conn->use_count < 0) LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", - lchan->conn.use_count); + lchan->conn->use_count); DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ); @@ -388,7 +395,7 @@ static void auto_release_channel(void *_lchan) struct gsm_lchan *lchan = _lchan; if (!lchan_auto_release(lchan)) - bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); + bsc_schedule_timer(&lchan->conn->release_timer, LCHAN_RELEASE_TIMEOUT); } static struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { @@ -400,7 +407,7 @@ static struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber * 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->conn.subscr) + if (lchan->conn && subscr == lchan->conn->subscr) return lchan; } } @@ -418,7 +425,7 @@ struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *s llist_for_each_entry(bts, &net->bts_list, list) { lchan = lchan_find(bts, subscr); if (lchan) - return &lchan->conn; + return lchan->conn; } return NULL; @@ -471,3 +478,38 @@ void network_chan_load(struct pchan_load *pl, struct gsm_network *net) llist_for_each_entry(bts, &net->bts_list, list) bts_chan_load(pl, bts); } + +struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan) +{ + struct gsm_subscriber_connection *conn; + + conn = talloc_zero(lchan->ts->trx->bts, struct gsm_subscriber_connection); + if (!conn) + return NULL; + + /* Configure the time and start it so it will be closed */ + conn->lchan = lchan; + conn->bts = lchan->ts->trx->bts; + conn->release_timer.cb = auto_release_channel; + conn->release_timer.data = lchan; + bsc_schedule_timer(&conn->release_timer, LCHAN_RELEASE_TIMEOUT); + + lchan->conn = conn; + return conn; +} + +/* TODO: move subscriber put here... */ +void subscr_con_free(struct gsm_subscriber_connection *conn) +{ + struct gsm_lchan *lchan; + + + if (!conn) + return; + + lchan = conn->lchan; + talloc_free(conn); + + if (lchan) + lchan->conn = NULL; +} |