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); 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_int64_t str_to_imsi(const char *imsi_str);
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan); 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 */ /* to be provided by external code */
int abis_rsl_sendmsg(struct msgb *msg); int abis_rsl_sendmsg(struct msgb *msg);

View File

@@ -34,13 +34,13 @@
lchan->nr, lchan->use_count); \ lchan->nr, lchan->use_count); \
} while(0); } while(0);
#define put_lchan(lchan) \ #define put_lchan(lchan, reason) \
do { lchan->use_count--; \ do { lchan->use_count--; \
DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \ 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->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
lchan->nr, lchan->use_count); \ lchan->nr, lchan->use_count); \
if (lchan->use_count <= 0) \ if (lchan->use_count <= 0) \
_lchan_release(lchan); \ _lchan_release(lchan, reason); \
} while(0); } 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); void lchan_free(struct gsm_lchan *lchan);
/* internal.. do not use */ /* 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 { struct load_counter {
unsigned int total; 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, RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
lchan_free() */ 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; struct msgb *msg;
msg = rsl_rll_simple(RSL_MT_REL_REQ, lchan2chan_nr(lchan), msg = rsl_rll_simple(RSL_MT_REL_REQ, lchan2chan_nr(lchan),
link_id, 0); 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; lchan->state = LCHAN_S_REL_REQ;
/* FIXME: start some timer in case we don't receive a REL ACK ? */ /* 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."); DEBUGP(DMSC, "ERROR: The lchan is still associated\n.");
lchan->msc_data = NULL; lchan->msc_data = NULL;
put_lchan(lchan); put_lchan(lchan, 0);
} }
bss_sccp_free_data((struct bss_sccp_connection_data *)conn->data_ctx); 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) { if (!msg->lchan->msc_data) {
DEBUGP(DMSC, "No MSC data\n"); DEBUGP(DMSC, "No MSC data\n");
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
return -1; return -1;
} }
if (msg->lchan->msc_data->secondary_lchan != msg->lchan) { if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n"); LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
return -1; return -1;
} }
if (msgb_l3len(msg) - sizeof(*gh) != 1) { if (msgb_l3len(msg) - sizeof(*gh) != 1) {
DEBUGP(DMSC, "assignment failure invalid: %d\n", DEBUGP(DMSC, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh)); msgb_l3len(msg) - sizeof(*gh));
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
return -1; 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 */ /* give up the old channel to not do a SACCH deactivate */
subscr_put(old_chan->subscr); subscr_put(old_chan->subscr);
old_chan->subscr = NULL; old_chan->subscr = NULL;
put_lchan(old_chan); put_lchan(old_chan, 1);
/* activate audio on it... */ /* activate audio on it... */
if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && msg->lchan->tch_mode != GSM48_CMODE_SIGN) 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"); DEBUGP(DMSC, "ASSIGNMENT FAILURE from MS, forwarding to MSC\n");
if (!msg->lchan->msc_data) { if (!msg->lchan->msc_data) {
DEBUGP(DMSC, "No MSC data\n"); DEBUGP(DMSC, "No MSC data\n");
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
return -1; return -1;
} }
if (msg->lchan->msc_data->secondary_lchan != msg->lchan) { if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n"); LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
return -1; return -1;
} }
if (msgb_l3len(msg) - sizeof(*gh) != 1) { if (msgb_l3len(msg) - sizeof(*gh) != 1) {
DEBUGP(DMSC, "assignment failure invalid: %d\n", DEBUGP(DMSC, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh)); msgb_l3len(msg) - sizeof(*gh));
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
return -1; 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) static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type)
{ {
llist_del(&rllr->list); llist_del(&rllr->list);
put_lchan(rllr->lchan); put_lchan(rllr->lchan, 0);
rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type); rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
talloc_free(rllr); 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 */ /* we might got killed during an assignment */
if (msg->lchan->msc_data->secondary_lchan) 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; msg->lchan->msc_data = NULL;
put_lchan(msg->lchan); put_lchan(msg->lchan, 0);
} }
/* send the clear complete message */ /* send the clear complete message */
@@ -439,13 +439,13 @@ static void continue_new_assignment(struct gsm_lchan *new_lchan)
{ {
if (!new_lchan->msc_data) { if (!new_lchan->msc_data) {
LOGP(DMSC, LOGL_ERROR, "No BSS data found.\n"); LOGP(DMSC, LOGL_ERROR, "No BSS data found.\n");
put_lchan(new_lchan); put_lchan(new_lchan, 0);
return; return;
} }
if (new_lchan->msc_data->secondary_lchan != new_lchan) { if (new_lchan->msc_data->secondary_lchan != new_lchan) {
LOGP(DMSC, LOGL_ERROR, "This is not the secondary channel?\n"); LOGP(DMSC, LOGL_ERROR, "This is not the secondary channel?\n");
put_lchan(new_lchan); put_lchan(new_lchan, 0);
return; return;
} }

View File

@@ -300,7 +300,7 @@ void lchan_free(struct gsm_lchan *lchan)
} }
/* Consider releasing the channel now */ /* 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) { if (lchan->use_count > 0) {
DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n"); 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); lchan->use_count);
DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
rsl_release_request(lchan, 0); rsl_release_request(lchan, 0, release_reason);
return 1; 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); bsc_del_timer(&lchan->loc_operation->updating_timer);
talloc_free(lchan->loc_operation); talloc_free(lchan->loc_operation);
lchan->loc_operation = 0; lchan->loc_operation = 0;
put_lchan(lchan); put_lchan(lchan, 0);
} }
static void allocate_loc_updating_req(struct gsm_lchan *lchan) 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 */ /* release channel if done */
if (!sms) if (!sms)
rsl_release_request(msg->lchan, trans->sms.link_id); rsl_release_request(msg->lchan, trans->sms.link_id, 0);
return 0; return 0;
} }
@@ -837,7 +837,7 @@ static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
if (sms) if (sms)
gsm411_send_sms_lchan(msg->lchan, sms); gsm411_send_sms_lchan(msg->lchan, sms);
else else
rsl_release_request(msg->lchan, trans->sms.link_id); rsl_release_request(msg->lchan, trans->sms.link_id, 0);
return rc; 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 * will listen to the paging requests before we timeout
*/ */
put_lchan(lchan); put_lchan(lchan, 0);
if (lchan->subscr && !llist_empty(&lchan->subscr->requests)) if (lchan->subscr && !llist_empty(&lchan->subscr->requests))
subscr_send_paging_request(lchan->subscr); 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); bsc_del_timer(&ho->T3103);
llist_del(&ho->list); llist_del(&ho->list);
put_lchan(ho->new_lchan); put_lchan(ho->new_lchan, 0);
talloc_free(ho); talloc_free(ho);
return 0; return 0;

View File

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

View File

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