bts: "Repair" broken channels if we receive the release ack

We had issues with odd behavior on the nanoBTS which lead
to the introduction of the "broken" state. On busy multi
BTS cells (e.g. rhizomatica) with wifi backhaul the timeout
we set to wait for a RF Channe Release ACK is sometimes too
little and channels are marked broken that look to be okay
(besides the still to be determined delay).

In case of a sysmoBTS we now know that we can change the
state of a broken channel back to normal in case we do
receive the right response.

Manually verified using the Smalltalk BTS code

PackageLoader fileInPackage: 'FakeBTS'
bts := FakeBTS.BTS new.
bts btsId: '1903/0/0'.
bts connect: 'localhost'.
bts waitForBTSReady.
test := FakeBTS.OpenBSCTest new.
test bts: bts.

test requireAnyChannel

... wait for NITB output
<0004> abis_rsl.c:223 (bts=0,trx=0,ts=0,ss=0) Timeout during deactivation! Marked as broken.

... process pending messages
stdin next
<0004> abis_rsl.c:735 (bts=0,trx=0,ts=0,ss=0) CHAN REL ACK for broken channel. Releasing it.

So the channel went from broken to unallocated.
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index 3fa30d1..41289dd 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -720,10 +720,21 @@
 	osmo_timer_del(&lchan->act_timer);
 	osmo_timer_del(&lchan->T3111);
 
+	/*
+	 * The BTS didn't respond within the timeout to our channel
+	 * release request and we have marked the channel as broken.
+	 * Now we do receive an ACK and let's be conservative. If it
+	 * is a sysmoBTS we know that only one RF Channel Release ACK
+	 * will be sent. So let's "repair" the channel.
+	 */
 	if (lchan->state == LCHAN_S_BROKEN) {
-		/* we are leaving this channel broken for now */
-		LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK for broken channel.\n",
-			gsm_lchan_name(lchan));
+		int do_free = is_sysmobts_v2(lchan->ts->trx->bts);
+		LOGP(DRSL, LOGL_NOTICE,
+			"%s CHAN REL ACK for broken channel. %s.\n",
+			gsm_lchan_name(lchan),
+			do_free ? "Releasing it" : "Keeping it broken");
+		if (do_free)
+			do_lchan_free(lchan);
 		return 0;
 	}