aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-04-09 14:30:52 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-04-09 14:30:52 +0200
commitf0fbae94ea7e22e18a732eb5907137f8033bdf1d (patch)
treede318137388e044e51ee37a4867f13002cd832a0
parent8fe4df503c92f1d2e990bce3f37a61610e5664c2 (diff)
[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...
-rw-r--r--openbsc/include/openbsc/abis_rsl.h1
-rw-r--r--openbsc/include/openbsc/gsm_data.h3
-rw-r--r--openbsc/src/abis_rsl.c18
-rw-r--r--openbsc/src/chan_alloc.c60
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;
}