Add new PDCH UL Controller, drop SBAllocator class

Right now we handle different types of UL allocations in different
classes like PollAllocator and SBAllocator, and they usually don't take
into account the other one in most cases. Furthermore, those objects are
usually per-BTS object, instead of per PDCH object.

This is a first step towards having a unified per-PDCH controller which
takes care of controlling what is scheduled and hence expected on the
uplink. Each PDCH has a UL Controller which keeps track of all reserved
uplink frame, be it SB, RRBP poll or USF assigned, all under the same
API.

As a first step, only the SBA part is fully implemented and used (being
it the easiest part to replace); TBF poll+usf will come in follow-up
patches later on. As a result, the SBAllocator per-BTS class dissappears
but some of its code is refactored/reused to provide more features to the
gprs_rlcmac_sba object, which is also further integrated into the new UL
Controller.

Related: OS#5020
Change-Id: I84b24beea4a1aa2c1528f41435f77bd16df2b947
diff --git a/src/bts.cpp b/src/bts.cpp
index 1d3f690..a7d475c 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -212,7 +212,6 @@
 	 * m_ms_store's destructor */
 	bts->ms_store->cleanup();
 	delete bts->ms_store;
-	delete bts->sba;
 	delete bts->pollController;
 
 	if (bts->ratectrs) {
@@ -246,7 +245,6 @@
 	bts->nr = bts_nr;
 
 	bts->pollController = new PollController(*bts);
-	bts->sba = new SBAController(*bts);
 	bts->ms_store = new GprsMsStorage(bts);
 
 	bts->cur_fn = 0;
@@ -819,10 +817,43 @@
 	return 0;
 }
 
+struct gprs_rlcmac_sba *bts_alloc_sba(struct gprs_rlcmac_bts *bts, uint8_t ta)
+{
+	struct gprs_rlcmac_pdch *pdch;
+	struct gprs_rlcmac_sba *sba = NULL;
+	int8_t trx, ts;
+
+	if (!gsm48_ta_is_valid(ta))
+		return NULL;
+
+	for (trx = 0; trx < 8; trx++) {
+		for (ts = 7; ts >= 0; ts--) {
+			pdch = &bts->trx[trx].pdch[ts];
+			if (!pdch->is_enabled())
+				continue;
+			break;
+		}
+		if (ts >= 0)
+			break;
+	}
+	if (trx == 8) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");
+		return NULL;
+	}
+
+	sba = sba_alloc(bts, pdch, ta);
+	if (!sba)
+		return NULL;
+
+	bts_do_rate_ctr_inc(bts, CTR_SBA_ALLOCATED);
+	return sba;
+}
+
 int bts_rcv_rach(struct gprs_rlcmac_bts *bts, const struct rach_ind_params *rip)
 {
 	struct chan_req_params chan_req = { 0 };
 	struct gprs_rlcmac_ul_tbf *tbf = NULL;
+	struct gprs_rlcmac_sba *sba;
 	uint8_t trx_no, ts_no;
 	uint32_t sb_fn = 0;
 	uint8_t usf = 7;
@@ -864,14 +895,18 @@
 
 	/* Should we allocate a single block or an Uplink TBF? */
 	if (chan_req.single_block) {
-		rc = bts_sba(bts)->alloc(&trx_no, &ts_no, &sb_fn, ta);
-		if (rc < 0) {
+		sba = bts_alloc_sba(bts, ta);
+		if (!sba) {
 			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource for "
-			     "single block allocation: rc=%d\n", rc);
+			     "single block allocation\n");
+			rc = -EBUSY;
 			/* Send RR Immediate Assignment Reject */
 			goto send_imm_ass_rej;
 		}
 
+		trx_no = sba->pdch->trx_no();
+		ts_no = sba->pdch->ts_no;
+		sb_fn = sba->fn;
 		tsc = bts->trx[trx_no].pdch[ts_no].tsc;
 		LOGP(DRLCMAC, LOGL_DEBUG, "Allocated a single block at "
 		     "SBFn=%u TRX=%u TS=%u\n", sb_fn, trx_no, ts_no);
@@ -1076,11 +1111,6 @@
 	return ms;
 }
 
-struct SBAController *bts_sba(struct gprs_rlcmac_bts *bts)
-{
-	return bts->sba;
-}
-
 struct GprsMsStorage *bts_ms_store(struct gprs_rlcmac_bts *bts)
 {
 	return bts->ms_store;