aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-06-30 12:58:14 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-06-30 13:02:08 +0800
commitf2553a6c3a9c677f71fd7f123c54d80a915f7a0a (patch)
tree51d5c3b09e5f367be10225b55335ae427afae705
parent0610947f4cb0efd7f68e3e0e8df3663f0cdd64e5 (diff)
handover: Call bsc_handover_clear from gsm0808_clear
The bsc_handover_clear will release an in-progress handover and free the lchana and the data associated with this handover
-rw-r--r--openbsc/include/openbsc/handover.h6
-rw-r--r--openbsc/src/bsc_api.c3
-rw-r--r--openbsc/src/chan_alloc.c9
-rw-r--r--openbsc/src/handover_logic.c24
4 files changed, 35 insertions, 7 deletions
diff --git a/openbsc/include/openbsc/handover.h b/openbsc/include/openbsc/handover.h
index 8ab1b0642..5d710576c 100644
--- a/openbsc/include/openbsc/handover.h
+++ b/openbsc/include/openbsc/handover.h
@@ -1,8 +1,14 @@
#ifndef _HANDOVER_H
#define _HANDOVER_H
+
+struct gsm_subscriber_connection;
+
/* Hand over the specified logical channel to the specified new BTS.
* This is the main entry point for the actual handover algorithm,
* after it has decided it wants to initiate HO to a specific BTS */
int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
+/* clear any operation for this connection */
+void bsc_clear_handover(struct gsm_subscriber_connection *conn);
+
#endif /* _HANDOVER_H */
diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c
index 9c1d09063..856dc615c 100644
--- a/openbsc/src/bsc_api.c
+++ b/openbsc/src/bsc_api.c
@@ -28,6 +28,7 @@
#include <openbsc/signal.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/chan_alloc.h>
+#include <openbsc/handover.h>
#include <osmocore/talloc.h>
@@ -115,6 +116,8 @@ int gsm0808_clear(struct gsm_subscriber_connection* conn)
{
struct gsm_lchan *lchan;
+ bsc_clear_handover(conn);
+
lchan = conn->lchan;
subscr_con_free(conn);
lchan_release(lchan, 1, 0);
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 675cbbb1d..dda5ff20d 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -478,13 +478,8 @@ void subscr_con_free(struct gsm_subscriber_connection *conn)
}
- /* Release a handover that might be in operation */
- if (conn->ho_lchan) {
- conn->ho_lchan->conn = NULL;
- lchan_release(conn->ho_lchan, 0, 1);
- conn->ho_lchan = NULL;
- }
-
+ if (conn->ho_lchan)
+ LOGP(DNM, LOGL_ERROR, "The ho_lchan should have been cleared.\n");
lchan = conn->lchan;
talloc_free(conn);
diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c
index 42dc5d8e6..cdb066447 100644
--- a/openbsc/src/handover_logic.c
+++ b/openbsc/src/handover_logic.c
@@ -149,6 +149,30 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
return 0;
}
+void bsc_clear_handover(struct gsm_subscriber_connection *conn)
+{
+ struct bsc_handover *ho;
+
+ ho = bsc_ho_by_new_lchan(conn->ho_lchan);
+
+
+ if (!ho && conn->ho_lchan)
+ LOGP(DHO, LOGL_ERROR, "BUG: We lost some state.\n");
+
+ if (!ho) {
+ LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");
+ return;
+ }
+
+ conn->ho_lchan->conn = NULL;
+ conn->ho_lchan = NULL;
+ lchan_release(ho->new_lchan, 0, 1);
+
+ bsc_del_timer(&ho->T3103);
+ llist_del(&ho->list);
+ talloc_free(ho);
+}
+
/* T3103 expired: Handover has failed without HO COMPLETE or HO FAIL */
static void ho_T3103_cb(void *_ho)
{