pdch: Move enable/disable into the PDCH code

When a PDCH is disabled all resources should be freed. This is
currently not possible as the PDCH does not know where it belongs
to. On top of that the list (and other resources) should be
properly initialized on construction so that disable() is idempotent
and does not check if it was disabled. During the re-factoring I
noticed that during a sysmobts re-start some resources are not
freed. I left a warning in the code to resolve this issue later.
diff --git a/src/bts.cpp b/src/bts.cpp
index 29cd3e5..ca01288 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -20,6 +20,13 @@
 
 #include <bts.h>
 #include <poll_controller.h>
+#include <tbf.h>
+
+#include <gprs_rlcmac.h>
+
+extern "C" {
+	#include <osmocom/core/talloc.h>
+}
 
 #include <string.h>
 
@@ -53,3 +60,40 @@
 	m_cur_fn = fn;
 	m_pollController.expireTimedout(m_cur_fn);
 }
+
+void gprs_rlcmac_pdch::enable()
+{
+	/* TODO: Check if there are still allocated resources.. */
+	INIT_LLIST_HEAD(&paging_list);
+	m_is_enabled = 1;
+}
+
+void gprs_rlcmac_pdch::disable()
+{
+	/* TODO.. kick free_resources once we know the TRX/TS we are on */
+	m_is_enabled = 0;
+}
+
+void gprs_rlcmac_pdch::free_resources(uint8_t trx, uint8_t ts)
+{
+	struct gprs_rlcmac_paging *pag;
+	struct gprs_rlcmac_sba *sba, *sba2;
+
+	/* we are not enabled. there should be no resources */
+	if (!is_enabled())
+		return;
+
+	/* kick all TBF on slot */
+	gprs_rlcmac_tbf::free_all(this);
+
+	/* flush all pending paging messages */
+	while ((pag = gprs_rlcmac_dequeue_paging(this)))
+		talloc_free(pag);
+
+	llist_for_each_entry_safe(sba, sba2, &gprs_rlcmac_sbas, list) {
+		if (sba->trx == trx && sba->ts == ts) {
+			llist_del(&sba->list);
+			talloc_free(sba);
+		}
+	}
+}
diff --git a/src/bts.h b/src/bts.h
index 4babd25..8e88bc9 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -39,7 +39,17 @@
  * PDCH instance
  */
 struct gprs_rlcmac_pdch {
-	uint8_t enable; /* TS is enabled */
+#ifdef __cplusplus
+	/* TODO: the PDCH should know the trx/ts it belongs to */
+	void free_resources(uint8_t trx, uint8_t ts);
+
+	bool is_enabled() const;
+
+	void enable();
+	void disable();
+#endif
+
+	uint8_t m_is_enabled; /* TS is enabled */
 	uint8_t tsc; /* TSC of this slot */
 	uint8_t next_ul_tfi; /* next uplink TBF/TFI to schedule (0..31) */
 	uint8_t next_dl_tfi; /* next downlink TBF/TFI to schedule (0..31) */
@@ -135,4 +145,9 @@
 	struct gprs_rlcmac_bts *bts_main_data();
 #ifdef __cplusplus
 }
+
+inline bool gprs_rlcmac_pdch::is_enabled() const
+{
+	return m_is_enabled;
+}
 #endif
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index 7726481..e83de21 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -149,7 +149,7 @@
 	for (trx = trx_from; trx <= trx_to; trx++) {
 		for (ts = 0; ts < 8; ts++) {
 			pdch = &bts->trx[trx].pdch[ts];
-			if (!pdch->enable)
+			if (!pdch->is_enabled())
 				continue;
 			break;
 		}
@@ -205,7 +205,7 @@
 	for (trx = 0; trx < 8; trx++) {
 		for (ts = 0; ts < 8; ts++) {
 			pdch = &bts->trx[trx].pdch[ts];
-			if (!pdch->enable)
+			if (!pdch->is_enabled())
 				continue;
 			break;
 		}
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index 67946df..c0154fc 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -241,7 +241,7 @@
 		return -EINVAL;
 	pdch = &bts->trx[trx].pdch[ts];
 
-	if (!pdch->enable) {
+	if (!pdch->is_enabled()) {
 		LOGP(DRLCMACSCHED, LOGL_ERROR, "Received RTS on disabled PDCH: "
 			"TRX=%d TS=%d\n", trx, ts);
 		return -EIO;
diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp
index e5ca5b6..bf69296 100644
--- a/src/gprs_rlcmac_ts_alloc.cpp
+++ b/src/gprs_rlcmac_ts_alloc.cpp
@@ -104,7 +104,7 @@
 		struct gprs_rlcmac_pdch *pdch;
 
 		pdch = &trx->pdch[ts];
-		if (!pdch->enable) {
+		if (!pdch->is_enabled()) {
 			LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
 				"not enabled\n", ts);
 			continue;
@@ -265,7 +265,7 @@
 	for (ts = 0, i = 0; ts < 8; ts++) {
 		pdch = &tbf->trx->pdch[ts];
 		/* check if enabled */
-		if (!pdch->enable) {
+		if (!pdch->is_enabled()) {
 			LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
 				"not enabled\n", ts);
 			/* increase window for Type 1 */
@@ -421,7 +421,7 @@
 		for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
 			pdch = &tbf->trx->pdch[ts];
 			/* check if enabled */
-			if (!pdch->enable) {
+			if (!pdch->is_enabled()) {
 				LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
 					"because not enabled\n", ts);
 				continue;
@@ -493,7 +493,7 @@
 		for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
 			pdch = &tbf->trx->pdch[ts];
 			/* check if enabled */
-			if (!pdch->enable) {
+			if (!pdch->is_enabled()) {
 				LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
 					"because not enabled\n", ts);
 				continue;
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 438bfa8..49c9147 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -295,28 +295,6 @@
 	return rc;
 }
 
-int flush_pdch(struct gprs_rlcmac_pdch *pdch, uint8_t trx, uint8_t ts)
-{
-	struct gprs_rlcmac_paging *pag;
-	struct gprs_rlcmac_sba *sba, *sba2;
-
-	/* kick all TBF on slot */
-	gprs_rlcmac_tbf::free_all(pdch);
-
-	/* flush all pending paging messages */
-	while ((pag = gprs_rlcmac_dequeue_paging(pdch)))
-		talloc_free(pag);
-
-	llist_for_each_entry_safe(sba, sba2, &gprs_rlcmac_sbas, list) {
-		if (sba->trx == trx && sba->ts == ts) {
-			llist_del(&sba->list);
-			talloc_free(sba);
-		}
-	}
-
-	return 0;
-}
-
 static int pcu_rx_info_ind(struct gsm_pcu_if_info_ind *info_ind)
 {
 	struct gprs_rlcmac_bts *bts = bts_main_data();
@@ -342,11 +320,8 @@
 		/* free all TBF */
 		for (trx = 0; trx < 8; trx++) {
 			bts->trx[trx].arfcn = info_ind->trx[trx].arfcn;
-			for (ts = 0; ts < 8; ts++) {
-				if (bts->trx[trx].pdch[ts].enable)
-					flush_pdch(&bts->trx[trx].pdch[ts],
-						trx, ts);
-			}
+			for (ts = 0; ts < 8; ts++)
+				bts->trx[trx].pdch[ts].free_resources(trx, ts);
 		}
 		gprs_bssgp_destroy_or_exit();
 		return 0;
@@ -465,7 +440,7 @@
 			pdch = &bts->trx[trx].pdch[ts];
 			if ((info_ind->trx[trx].pdch_mask & (1 << ts))) {
 				/* FIXME: activate dynamically at RLCMAC */
-				if (!pdch->enable) {
+				if (!pdch->is_enabled()) {
 #ifdef ENABLE_SYSMODSP
 					if ((info_ind->flags &
 							PCU_IF_FLAG_SYSMO))
@@ -473,17 +448,16 @@
 							bts->trx[trx].fl1h, ts);
 #endif
 					pcu_tx_act_req(trx, ts, 1);
-					INIT_LLIST_HEAD(&pdch->paging_list);
-					pdch->enable = 1;
+					pdch->enable();
 				}
 				pdch->tsc = info_ind->trx[trx].tsc[ts];
 				LOGP(DL1IF, LOGL_INFO, "PDCH: trx=%d ts=%d\n",
 					trx, ts);
 			} else {
-				if (pdch->enable) {
+				if (pdch->is_enabled()) {
 					pcu_tx_act_req(trx, ts, 0);
-					pdch->enable = 0;
-					flush_pdch(pdch, trx, ts);
+					pdch->free_resources(trx, ts);
+					pdch->disable();
 				}
 			}
 		}
diff --git a/src/sysmo_sock.cpp b/src/sysmo_sock.cpp
index 2852c0e..6af2e9a 100644
--- a/src/sysmo_sock.cpp
+++ b/src/sysmo_sock.cpp
@@ -106,7 +106,8 @@
 		}
 #endif
 		for (ts = 0; ts < 8; ts++)
-			bts->trx[trx].pdch[ts].enable = 0;
+			bts->trx[trx].pdch[ts].disable();
+#warning "NOT ALL RESOURCES are freed in this case... inconsistent with the other code. Share the code with pcu_l1if.c for the reset."
 		gprs_rlcmac_tbf::free_all(&bts->trx[trx]);
 	}