From f0fbae94ea7e22e18a732eb5907137f8033bdf1d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 9 Apr 2010 14:30:52 +0200 Subject: [rsl] Rework the lchan channel release procedure 1.) free every SAPI from 1-7 and wait for the confirmation and then continue until all of them are freed. If the SAPI is not torn down we will receive a timeout and then we force the RF Channel Release... 2.) once SAPI is down we send the RR Release, SACCH Deact 3.) the abis_rsl will see that all SAPIs are down and then will release channel... --- openbsc/include/openbsc/abis_rsl.h | 1 + openbsc/include/openbsc/gsm_data.h | 3 ++ openbsc/src/abis_rsl.c | 18 ++++++++++-- openbsc/src/chan_alloc.c | 60 ++++++++++++++++++++++++++++++++++---- 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index 415db52f6..cba6a9ba2 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -75,6 +75,7 @@ int rsl_lchan_set_state(struct gsm_lchan *lchan, int); /* to be provided by external code */ int abis_rsl_sendmsg(struct msgb *msg); int rsl_deact_sacch(struct gsm_lchan *lchan); +int rsl_lchan_rll_release(struct gsm_lchan *lchan, u_int8_t link_id); /* BCCH related code */ int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index fc4241ada..42b31a62c 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -281,6 +281,9 @@ struct gsm_lchan { } abis_ip; struct gsm_subscriber_connection conn; + + /* release reason */ + u_int8_t release_reason; }; struct gsm_e1_subslot { diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 03626e7e3..ccd272f17 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1299,11 +1299,21 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) static void rsl_handle_release(struct gsm_lchan *lchan) { + int sapi; struct gsm_bts *bts; + + /* maybe we have only brought down one RLL */ if (lchan->state != LCHAN_S_REL_REQ) - LOGP(DRSL, LOGL_ERROR, "RF release on %s but state %s\n", - gsm_lchan_name(lchan), - gsm_lchans_name(lchan->state)); + return; + + for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) { + if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) + continue; + LOGP(DRSL, LOGL_NOTICE, "%s waiting for SAPI=%d to be released.\n", + gsm_lchan_name(lchan), sapi); + return; + } + /* wait a bit to send the RF Channel Release */ @@ -1365,6 +1375,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_REL_IND); rsl_handle_release(msg->lchan); + rsl_lchan_rll_release(msg->lchan, rllh->link_id); break; case RSL_MT_REL_CONF: /* BTS informs us of having received UA from MS, @@ -1372,6 +1383,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) DEBUGPC(DRLL, "RELEASE CONFIRMATION\n"); msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED; rsl_handle_release(msg->lchan); + rsl_lchan_rll_release(msg->lchan, rllh->link_id); break; case RSL_MT_ERROR_IND: rc = rsl_rx_rll_err_ind(msg); diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 08d9b85ac..48732f76c 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -322,14 +322,31 @@ void lchan_free(struct gsm_lchan *lchan) * channel using it */ } -/* Consider releasing the channel now */ -int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) +static int _lchan_release_next_sapi(struct gsm_lchan *lchan) { - if (lchan->conn.use_count > 0) { - DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n"); + int sapi; + + for (sapi = 1; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) { + u_int8_t link_id; + if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) + continue; + + link_id = sapi; + if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H) + link_id |= 0x40; + rsl_release_request(lchan, link_id, lchan->release_reason); return 0; } + return 1; +} + +static void _lchan_handle_release(struct gsm_lchan *lchan) +{ + /* Ask for SAPI != 0 to be freed first and stop if we need to wait */ + if (_lchan_release_next_sapi(lchan) == 0) + return; + /* Assume we have GSM04.08 running and send a release */ if (lchan->conn.subscr) { ++lchan->conn.use_count; @@ -342,9 +359,42 @@ int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", lchan->conn.use_count); + rsl_release_request(lchan, 0, lchan->release_reason); +} + +/* called from abis rsl */ +int rsl_lchan_rll_release(struct gsm_lchan *lchan, u_int8_t link_id) +{ + if (lchan->state != LCHAN_S_REL_REQ) + return -1; + + if ((link_id & 0x7) != 0) + _lchan_handle_release(lchan); + return 0; +} + + +/* + * Start the channel release procedure now. We will start by shutting + * down SAPI!=0, then we will deactivate the SACCH and finish by releasing + * the last SAPI at which point the RSL code will send the channel release + * for us. We should guard the whole shutdown by T3109 or similiar and then + * update the fixme inside gsm_04_08_utils.c + * When we request to release the RLL and we don't get an answer within T200 + * the BTS will send us an Error indication which we will handle by closing + * the channel and be done. + */ +int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) +{ + if (lchan->conn.use_count > 0) { + DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n"); + return 0; + } + DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ); - rsl_release_request(lchan, 0, release_reason); + lchan->release_reason = release_reason; + _lchan_handle_release(lchan); return 1; } -- cgit v1.2.3