rsl: add timer to release channel if we don't get release req ack/nack

This patch adds a timer to release the channel after 4 seconds if
we don't get a release request ack/nack from the BTS.

This should fix the problem with channels in release request state in
the Nokia metrostation.
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
index 5eda312..443e39b 100644
--- a/openbsc/include/openbsc/chan_alloc.h
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -48,6 +48,9 @@
 /* Release the given lchan */
 int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason);
 
+/* Schedule release request timer */
+void lchan_timer_rel_req_schedule(struct gsm_lchan *lchan);
+
 struct load_counter {
 	unsigned int total;
 	unsigned int used;
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index 89375cf..099b808 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -183,6 +183,7 @@
 	struct osmo_timer_list T3111;
 	struct osmo_timer_list error_timer;
 	struct osmo_timer_list act_timer;
+	struct osmo_timer_list rel_timer;
 
 	/* table of neighbor cell measurements */
 	struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index cb2c9bc..8b06f2f 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -655,6 +655,7 @@
 	DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
 
 	osmo_timer_del(&lchan->act_timer);
+	osmo_timer_del(&lchan->rel_timer);
 
 	if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
 		LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
@@ -798,7 +799,8 @@
 	/* 0 is normal release, 1 is local end */
 	msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
 
-	/* FIXME: start some timer in case we don't receive a REL ACK ? */
+	/* Start some timer in case we don't receive a REL ACK ? */
+	lchan_timer_rel_req_schedule(lchan);
 
 	msg->trx = lchan->ts->trx;
 
diff --git a/openbsc/src/libbsc/chan_alloc.c b/openbsc/src/libbsc/chan_alloc.c
index 6f4fe20..d0fd9ae 100644
--- a/openbsc/src/libbsc/chan_alloc.c
+++ b/openbsc/src/libbsc/chan_alloc.c
@@ -397,6 +397,8 @@
 
 	if (lchan->sach_deact) {
 		gsm48_send_rr_release(lchan);
+		/* Make sure we don't stay in release request state forever. */
+		lchan_timer_rel_req_schedule(lchan);
 		return;
 	}
 
@@ -509,3 +511,20 @@
 		bts_chan_load(pl, bts);
 }
 
+static void lchan_rel_tmr_cb(void *data)
+{
+	struct gsm_lchan *lchan = data;
+
+	LOGP(DRSL, LOGL_NOTICE, "%s Timeout while in release request state!\n",
+		gsm_lchan_name(lchan));
+
+	rsl_lchan_set_state(lchan, LCHAN_S_NONE);
+	lchan_free(lchan);
+}
+
+void lchan_timer_rel_req_schedule(struct gsm_lchan *lchan)
+{
+	lchan->rel_timer.cb = lchan_rel_tmr_cb;
+	lchan->rel_timer.data = lchan;
+	osmo_timer_schedule(&lchan->rel_timer, 4, 0);
+}