[alloc] Assign a TCH for LU when all SDCCHs are occupied.

When the cell becomes visible we will be bombed with location
updating requests and to reduce the load on the network we should
assign as many channels for it as possible. During load peek it
is even more important than to have a spare voice channel and in
general the LU procedure is pretty fast.
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
index 3afcb3c..63f875b 100644
--- a/openbsc/include/openbsc/chan_alloc.h
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -40,7 +40,7 @@
 struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *subscr);
 
 /* Allocate a logical channel (SDCCH, TCH, ...) */
-struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
+struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
 
 /* Free a logical channel (SDCCH, TCH, ...) */
 void lchan_free(struct gsm_lchan *lchan);
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 7068422..d83af4a 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -1167,6 +1167,7 @@
 	enum gsm_chreq_reason_t chreq_reason;
 	struct gsm_lchan *lchan;
 	u_int8_t rqd_ta;
+	int is_lu;
 
 	u_int16_t arfcn;
 	u_int8_t ts_number, subch;
@@ -1189,8 +1190,14 @@
 
 	counter_inc(bts->network->stats.chreq.total);
 
+	/*
+	 * We want LOCATION UPDATES to succeed and will assign a TCH
+	 * if we have no SDCCH available.
+	 */
+	is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
+
 	/* check availability / allocate channel */
-	lchan = lchan_alloc(bts, lctype);
+	lchan = lchan_alloc(bts, lctype, is_lu);
 	if (!lchan) {
 		LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
 		     msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 5325dc0..a0eda54 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -225,7 +225,8 @@
 }
 
 /* Allocate a logical channel */
-struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
+struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
+			      int allow_bigger)
 {
 	struct gsm_lchan *lchan = NULL;
 	enum gsm_phys_chan_config first, second;
@@ -243,6 +244,19 @@
 		lchan = _lc_find_bts(bts, first);
 		if (lchan == NULL)
 			lchan = _lc_find_bts(bts, second);
+
+		/* allow to assign bigger channels */
+		if (allow_bigger) {
+			if (lchan == NULL) {
+				lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
+				type = GSM_LCHAN_TCH_H;
+			}
+
+			if (lchan == NULL) {
+				lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
+				type = GSM_LCHAN_TCH_F;
+			}
+		}
 		break;
 	case GSM_LCHAN_TCH_F:
 		lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c
index 92580bf..30cea7b 100644
--- a/openbsc/src/handover_logic.c
+++ b/openbsc/src/handover_logic.c
@@ -104,7 +104,7 @@
 		return -ENOSPC;
 	}
 
-	new_lchan = lchan_alloc(bts, old_lchan->type);
+	new_lchan = lchan_alloc(bts, old_lchan->type, 0);
 	if (!new_lchan) {
 		LOGP(DHO, LOGL_NOTICE, "No free channel\n");
 		counter_inc(bts->network->stats.handover.no_channel);