Convert tbf->control_ts to be a gprs_rlcmac_pdch*

This allows having full information on the control TS easily reachable
(like TRX ofthe PDCH), and makes it easy to compare TS by simply
matching the pointer address.

Change-Id: I6a97b6528b2f9d78dfbca8fb97ab7c621f777fc7
diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp
index facc34c..5cdfda3 100644
--- a/src/pcu_vty_functions.cpp
+++ b/src/pcu_vty_functions.cpp
@@ -68,7 +68,7 @@
 		state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
 		state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH),
 		first_common_ts ? first_common_ts->ts_no : -1,
-		tbf->control_ts,
+		tbf->control_ts ? tbf->control_ts->ts_no : -1,
 		tbf->ms_class(),
 		ms_egprs_ms_class(ms),
 		VTY_NEWLINE);
diff --git a/src/pdch.cpp b/src/pdch.cpp
index c7d92c1..cc93cfe 100644
--- a/src/pdch.cpp
+++ b/src/pdch.cpp
@@ -836,10 +836,11 @@
 	 * sent to tbf_fsm which will call tbf_assign_control_ts(),
 	 * effectively setting back control_ts to tbf->initial_common_ts.
 	 */
-	LOGPTBF(new_ul_tbf, LOGL_INFO, "change control TS %d -> %d until assignment is complete.\n",
-		new_ul_tbf->control_ts, ts_no);
+	LOGPTBF(new_ul_tbf, LOGL_INFO, "Change control TS %s -> %s until assignment is complete.\n",
+		new_ul_tbf->control_ts ? pdch_name_buf(new_ul_tbf->control_ts, buf, sizeof(buf)) : "(none)",
+		pdch_name(this));
 
-	new_ul_tbf->control_ts = ts_no;
+	new_ul_tbf->control_ts = this;
 	/* schedule uplink assignment */
 	osmo_fsm_inst_dispatch(new_ul_tbf->ul_ass_fsm.fi, TBF_UL_ASS_EV_SCHED_ASS, NULL);
 return_unref:
@@ -1312,7 +1313,7 @@
 	 * Get rid of them too: */
 	llist_for_each_entry_safe(pos, pos2, &pdch->trx->ul_tbfs, list) {
 		struct gprs_rlcmac_ul_tbf *ul_tbf = tbf_as_ul_tbf((struct gprs_rlcmac_tbf *)pos->entry);
-		if (ul_tbf->control_ts == pdch->ts_no)
+		if (ul_tbf->control_ts == pdch)
 			tbf_free(ul_tbf);
 	}
 }
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 90e2be6..0af738d 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -90,7 +90,7 @@
 gprs_rlcmac_tbf::gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir) :
 	direction(dir),
 	trx(NULL),
-	control_ts(TBF_TS_UNSET),
+	control_ts(NULL),
 	fT(0),
 	num_fT_exp(0),
 	upgrade_to_multislot(false),
@@ -217,8 +217,8 @@
 	 * confirmation from the MS and goes through the FLOW state. Hence, we
 	 * may have ULC pollings ongoing and we need to make sure we drop all
 	 * reserved nodes there: */
-	if (tbf->control_ts != TBF_TS_UNSET && !tbf->pdch[tbf->control_ts])
-		pdch_ulc_release_tbf(tbf->trx->pdch[tbf->control_ts].ulc, tbf);
+	if (tbf->control_ts)
+		pdch_ulc_release_tbf(tbf->control_ts->ulc, tbf);
 
 	/* Now simply detach from all attached PDCHs */
 	for (ts = 0; ts < 8; ts++) {
@@ -279,15 +279,18 @@
 
 void tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf)
 {
+	char buf[128];
 	struct gprs_rlcmac_pdch *first_common = ms_first_common_ts(tbf_ms(tbf));
 	OSMO_ASSERT(first_common);
-	if (tbf->control_ts == TBF_TS_UNSET)
-		LOGPTBF(tbf, LOGL_INFO, "Setting Control TS %d\n",
-			first_common->ts_no);
-	else if (tbf->control_ts != first_common->ts_no)
-		LOGPTBF(tbf, LOGL_INFO, "Changing Control TS %d -> %d\n",
-			tbf->control_ts, first_common->ts_no);
-	tbf->control_ts = first_common->ts_no;
+
+	if (!tbf->control_ts)
+		LOGPTBF(tbf, LOGL_INFO, "Setting Control TS %s\n",
+			pdch_name(first_common));
+	else if (tbf->control_ts != first_common)
+		LOGPTBF(tbf, LOGL_INFO, "Changing Control TS %s -> %s\n",
+			pdch_name_buf(tbf->control_ts, buf, sizeof(buf)),
+			pdch_name(first_common));
+	tbf->control_ts = first_common;
 }
 
 void gprs_rlcmac_tbf::n_reset(enum tbf_counters n)
@@ -461,8 +464,8 @@
 	int rc;
 	if (!tbf_is_control_ts(this, &this->trx->pdch[ts])) {
 		LOGPTBF(this, LOGL_DEBUG, "Polling cannot be "
-			"scheduled in this TS %d (first control TS %d)\n",
-			ts, control_ts);
+			"scheduled in this TS %d (control TS %s)\n",
+			ts, pdch_name(control_ts));
 		return -EINVAL;
 	}
 
@@ -710,8 +713,8 @@
 	struct gprs_rlcmac_pdch *first_common;
 
 	if (direction == GPRS_RLCMAC_DL_TBF) {
-		if (control_ts < 8)
-			slots |= 1 << control_ts;
+		if (control_ts)
+			slots |= 1 << control_ts->ts_no;
 		first_common = ms_first_common_ts(tbf_ms(this));
 		if (first_common)
 			slots |= 1 << first_common->ts_no;
@@ -853,7 +856,7 @@
 
 bool tbf_is_control_ts(const struct gprs_rlcmac_tbf *tbf, const struct gprs_rlcmac_pdch *pdch)
 {
-	return tbf->control_ts == pdch->ts_no;
+	return tbf->control_ts == pdch;
 }
 
 bool tbf_can_upgrade_to_multislot(const struct gprs_rlcmac_tbf *tbf)
diff --git a/src/tbf.h b/src/tbf.h
index 29f0d6f..a02b8e2 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -112,7 +112,6 @@
 #define GPRS_RLCMAC_FLAG_TO_DL_ACK	3 /* DL TBF: Failed to receive last polled DL ACK/NACK */
 #define GPRS_RLCMAC_FLAG_TO_MASK	0xf0 /* timeout bits */
 
-#define TBF_TS_UNSET 0xff
 #define TBF_TFI_UNSET 0xff
 
 #define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
@@ -219,7 +218,7 @@
 
 	enum gprs_rlcmac_tbf_direction direction;
 	struct gprs_rlcmac_trx *trx;
-	uint8_t control_ts; /* timeslot control messages and polling */
+	struct gprs_rlcmac_pdch *control_ts; /* timeslot control messages and polling */
 	struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
 
 	gprs_llc m_llc;