Specify a release reason for the lchan

In case the put_lchan is making the refcount drop to zero use the
release reason specified in the put_lchan call. This is used by the
BSC MSC IP implementation for the assignment handling where the old
channel is getting closed with a local end release (1).
This commit is contained in:
Holger Hans Peter Freyther
2010-03-24 10:45:07 +01:00
parent 1226c93937
commit 82a8d6e393
13 changed files with 30 additions and 29 deletions

View File

@@ -68,7 +68,7 @@ unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res);
u_int64_t str_to_imsi(const char *imsi_str);
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan);
int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id);
int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t release_reason);
/* to be provided by external code */
int abis_rsl_sendmsg(struct msgb *msg);

View File

@@ -34,13 +34,13 @@
lchan->nr, lchan->use_count); \
} while(0);
#define put_lchan(lchan) \
#define put_lchan(lchan, reason) \
do { lchan->use_count--; \
DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
lchan->nr, lchan->use_count); \
if (lchan->use_count <= 0) \
_lchan_release(lchan); \
_lchan_release(lchan, reason); \
} while(0);
@@ -69,7 +69,7 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
void lchan_free(struct gsm_lchan *lchan);
/* internal.. do not use */
int _lchan_release(struct gsm_lchan *lchan);
int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason);
struct load_counter {
unsigned int total;

View File

@@ -718,14 +718,15 @@ int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id)
RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
lchan_free() */
int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t reason)
{
struct msgb *msg;
msg = rsl_rll_simple(RSL_MT_REL_REQ, lchan2chan_nr(lchan),
link_id, 0);
msgb_tv_put(msg, RSL_IE_RELEASE_MODE, 0); /* normal release */
/* 0 is normal release, 1 is local end */
msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
lchan->state = LCHAN_S_REL_REQ;
/* FIXME: start some timer in case we don't receive a REL ACK ? */

View File

@@ -160,7 +160,7 @@ void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
DEBUGP(DMSC, "ERROR: The lchan is still associated\n.");
lchan->msc_data = NULL;
put_lchan(lchan);
put_lchan(lchan, 0);
}
bss_sccp_free_data((struct bss_sccp_connection_data *)conn->data_ctx);
@@ -306,20 +306,20 @@ static int handle_ass_compl(struct msgb *msg)
if (!msg->lchan->msc_data) {
DEBUGP(DMSC, "No MSC data\n");
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
return -1;
}
if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
return -1;
}
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
DEBUGP(DMSC, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh));
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
return -1;
}
@@ -332,7 +332,7 @@ static int handle_ass_compl(struct msgb *msg)
/* give up the old channel to not do a SACCH deactivate */
subscr_put(old_chan->subscr);
old_chan->subscr = NULL;
put_lchan(old_chan);
put_lchan(old_chan, 1);
/* activate audio on it... */
if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && msg->lchan->tch_mode != GSM48_CMODE_SIGN)
@@ -353,20 +353,20 @@ static int handle_ass_fail(struct msgb *msg)
DEBUGP(DMSC, "ASSIGNMENT FAILURE from MS, forwarding to MSC\n");
if (!msg->lchan->msc_data) {
DEBUGP(DMSC, "No MSC data\n");
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
return -1;
}
if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
return -1;
}
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
DEBUGP(DMSC, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh));
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
return -1;
}

View File

@@ -52,7 +52,7 @@ static LLIST_HEAD(bsc_rll_reqs);
static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type)
{
llist_del(&rllr->list);
put_lchan(rllr->lchan);
put_lchan(rllr->lchan, 0);
rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
talloc_free(rllr);
}

View File

@@ -191,10 +191,10 @@ static int bssmap_handle_clear_command(struct sccp_connection *conn,
/* we might got killed during an assignment */
if (msg->lchan->msc_data->secondary_lchan)
put_lchan(msg->lchan->msc_data->secondary_lchan);
put_lchan(msg->lchan->msc_data->secondary_lchan, 0);
msg->lchan->msc_data = NULL;
put_lchan(msg->lchan);
put_lchan(msg->lchan, 0);
}
/* send the clear complete message */
@@ -439,13 +439,13 @@ static void continue_new_assignment(struct gsm_lchan *new_lchan)
{
if (!new_lchan->msc_data) {
LOGP(DMSC, LOGL_ERROR, "No BSS data found.\n");
put_lchan(new_lchan);
put_lchan(new_lchan, 0);
return;
}
if (new_lchan->msc_data->secondary_lchan != new_lchan) {
LOGP(DMSC, LOGL_ERROR, "This is not the secondary channel?\n");
put_lchan(new_lchan);
put_lchan(new_lchan, 0);
return;
}

View File

@@ -300,7 +300,7 @@ void lchan_free(struct gsm_lchan *lchan)
}
/* Consider releasing the channel now */
int _lchan_release(struct gsm_lchan *lchan)
int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason)
{
if (lchan->use_count > 0) {
DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n");
@@ -320,7 +320,7 @@ int _lchan_release(struct gsm_lchan *lchan)
lchan->use_count);
DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
rsl_release_request(lchan, 0);
rsl_release_request(lchan, 0, release_reason);
return 1;
}

View File

@@ -104,7 +104,7 @@ static void release_loc_updating_req(struct gsm_lchan *lchan)
bsc_del_timer(&lchan->loc_operation->updating_timer);
talloc_free(lchan->loc_operation);
lchan->loc_operation = 0;
put_lchan(lchan);
put_lchan(lchan, 0);
}
static void allocate_loc_updating_req(struct gsm_lchan *lchan)

View File

@@ -762,7 +762,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
/* release channel if done */
if (!sms)
rsl_release_request(msg->lchan, trans->sms.link_id);
rsl_release_request(msg->lchan, trans->sms.link_id, 0);
return 0;
}
@@ -837,7 +837,7 @@ static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
if (sms)
gsm411_send_sms_lchan(msg->lchan, sms);
else
rsl_release_request(msg->lchan, trans->sms.link_id);
rsl_release_request(msg->lchan, trans->sms.link_id, 0);
return rc;
}

View File

@@ -207,7 +207,7 @@ void subscr_put_channel(struct gsm_lchan *lchan)
* will listen to the paging requests before we timeout
*/
put_lchan(lchan);
put_lchan(lchan, 0);
if (lchan->subscr && !llist_empty(&lchan->subscr->requests))
subscr_send_paging_request(lchan->subscr);

View File

@@ -255,7 +255,7 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
bsc_del_timer(&ho->T3103);
llist_del(&ho->list);
put_lchan(ho->new_lchan);
put_lchan(ho->new_lchan, 0);
talloc_free(ho);
return 0;

View File

@@ -135,7 +135,7 @@ int gsm_silent_call_stop(struct gsm_subscriber *subscr)
if (!lchan->silent_call)
return -EINVAL;
put_lchan(lchan);
put_lchan(lchan, 0);
return 0;
}

View File

@@ -102,7 +102,7 @@ void trans_free(struct gsm_trans *trans)
}
if (trans->lchan)
put_lchan(trans->lchan);
put_lchan(trans->lchan, 0);
if (trans->subscr)
subscr_put(trans->subscr);
@@ -159,7 +159,7 @@ int trans_lchan_change(struct gsm_lchan *lchan_old,
llist_for_each_entry(trans, &net->trans_list, entry) {
if (trans->lchan == lchan_old) {
/* drop old channel use cound */
put_lchan(trans->lchan);
put_lchan(trans->lchan, 0);
/* assign new channel */
trans->lchan = lchan_new;
/* bump new channel use count */