Refactor code related to DL-TBF upgrade to multislot

* Make clear the code relates to DL-TBF and not UL-TBF.
* Change wording to "upgrade" to match the existing field and API
  "tbf_can_upgrade_to_multislot()".
* Free the TBF if we cannot allocate new resources.

Change-Id: I0e4f8d7e46235a471b2124b280c81ff07b6967a4
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 8358b8f..2cc6053 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -206,7 +206,7 @@
 		ms_attach_tbf(m_ms, this);
 }
 
-static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
+void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
 {
 	int ts;
 
@@ -277,33 +277,6 @@
 			OSMO_MAX(64, (the_pcu->vty.ws_base + num_pdch * the_pcu->vty.ws_pdch) / 32 * 32));
 }
 
-int gprs_rlcmac_tbf::update()
-{
-	int rc;
-
-	LOGP(DTBF, LOGL_DEBUG, "********** DL-TBF update **********\n");
-	OSMO_ASSERT(direction == GPRS_RLCMAC_DL_TBF);
-
-	tbf_unlink_pdch(this);
-	rc = the_pcu->alloc_algorithm(bts, this, false, -1);
-	/* if no resource */
-	if (rc < 0) {
-		LOGPTBF(this, LOGL_ERROR, "No resource after update???\n");
-		bts_do_rate_ctr_inc(bts, CTR_TBF_ALLOC_FAIL);
-		return rc;
-	}
-
-	if (is_egprs_enabled()) {
-		gprs_rlcmac_dl_tbf *dl_tbf = tbf_as_dl_tbf(this);
-		if (dl_tbf)
-			dl_tbf->set_window_size();
-	}
-
-	tbf_update_state_fsm_name(this);
-
-	return 0;
-}
-
 void tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf)
 {
 	int8_t first_common_ts = ms_first_common_ts(tbf_ms(tbf));
@@ -885,12 +858,6 @@
 {
 	return tbf->upgrade_to_multislot;
 }
-
-int tbf_update(struct gprs_rlcmac_tbf *tbf)
-{
-	return tbf->update();
-}
-
 /* first TS used by TBF */
 struct gprs_rlcmac_pdch *tbf_get_first_ts(struct gprs_rlcmac_tbf *tbf)
 {
diff --git a/src/tbf.h b/src/tbf.h
index 4a08da9..29f0d6f 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -147,10 +147,10 @@
 const char* tbf_rlcmac_diag(const struct gprs_rlcmac_tbf *tbf);
 bool tbf_is_control_ts(const struct gprs_rlcmac_tbf *tbf, const struct gprs_rlcmac_pdch *pdch);
 bool tbf_can_upgrade_to_multislot(const struct gprs_rlcmac_tbf *tbf);
-int tbf_update(struct gprs_rlcmac_tbf *tbf);
 struct gprs_rlcmac_pdch *tbf_get_first_ts(struct gprs_rlcmac_tbf *tbf);
 const struct gprs_rlcmac_pdch *tbf_get_first_ts_const(const struct gprs_rlcmac_tbf *tbf);
 struct gprs_rlcmac_trx *tbf_get_trx(struct gprs_rlcmac_tbf *tbf);
+void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf);
 void tbf_stop_timers(struct gprs_rlcmac_tbf *tbf, const char *reason);
 #ifdef __cplusplus
 }
@@ -183,7 +183,6 @@
 	bool n_inc(enum tbf_counters n);
 	void n_reset(enum tbf_counters n);
 
-	int update();
 	void handle_timeout();
 	void stop_timers(const char *reason);
 	bool timers_pending(enum tbf_timers t);
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index f5637f9..c5ce666 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -446,6 +446,30 @@
 	bts_snd_dl_ass(ms->bts, tbf);
 }
 
+int dl_tbf_upgrade_to_multislot(struct gprs_rlcmac_dl_tbf *tbf)
+{
+	int rc;
+	struct gprs_rlcmac_trx *trx = tbf_get_trx(tbf);
+	struct gprs_rlcmac_bts *bts = trx->bts;
+
+	LOGPTBFDL(tbf, LOGL_DEBUG, "Upgrade to multislot\n");
+
+	tbf_unlink_pdch(tbf);
+	rc = the_pcu->alloc_algorithm(bts, dl_tbf_as_tbf(tbf), false, -1);
+	/* if no resource */
+	if (rc < 0) {
+		LOGPTBFDL(tbf, LOGL_ERROR, "No resources allocated during upgrade to multislot!\n");
+		bts_do_rate_ctr_inc(bts, CTR_TBF_ALLOC_FAIL);
+		return rc;
+	}
+
+	if (tbf_is_egprs_enabled(dl_tbf_as_tbf(tbf)))
+		tbf->set_window_size();
+	tbf_update_state_fsm_name(tbf);
+
+	return 0;
+}
+
 void gprs_rlcmac_dl_tbf::schedule_next_frame()
 {
 	struct msgb *msg;
diff --git a/src/tbf_dl.h b/src/tbf_dl.h
index 8d4d716..2fc4f5f 100644
--- a/src/tbf_dl.h
+++ b/src/tbf_dl.h
@@ -151,6 +151,7 @@
 void dl_tbf_trigger_ass_on_pacch(struct gprs_rlcmac_dl_tbf *tbf, struct gprs_rlcmac_tbf *old_tbf);
 void dl_tbf_trigger_ass_on_pch(struct gprs_rlcmac_dl_tbf *tbf);
 void dl_tbf_request_dl_ack(struct gprs_rlcmac_dl_tbf *tbf);
+int dl_tbf_upgrade_to_multislot(struct gprs_rlcmac_dl_tbf *tbf);
 
 static inline struct gprs_rlcmac_tbf *dl_tbf_as_tbf(struct gprs_rlcmac_dl_tbf *dl_tbf)
 {
diff --git a/src/tbf_dl_fsm.c b/src/tbf_dl_fsm.c
index f306510..0ab740d 100644
--- a/src/tbf_dl_fsm.c
+++ b/src/tbf_dl_fsm.c
@@ -321,29 +321,35 @@
 static void handle_timeout_X2002(struct osmo_fsm_inst *fi)
 {
 	struct tbf_dl_fsm_ctx *ctx = (struct tbf_dl_fsm_ctx *)fi->priv;
+	int rc;
 
-	if (fi->state == TBF_ST_ASSIGN) {
-		tbf_assign_control_ts(ctx->tbf);
-
-		if (!tbf_can_upgrade_to_multislot(ctx->tbf)) {
-			/* change state to FLOW, so scheduler
-			 * will start transmission */
-			osmo_fsm_inst_dispatch(fi, TBF_EV_ASSIGN_READY_CCCH, NULL);
-			return;
-		}
-
-		/* This tbf can be upgraded to use multiple DL
-		 * timeslots and now that there is already one
-		 * slot assigned send another DL assignment via
-		 * PDCH. */
-
-		/* keep to flags */
-		ctx->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
-
-		tbf_update(ctx->tbf);
-		dl_tbf_trigger_ass_on_pacch(ctx->dl_tbf, ctx->tbf);
-	} else
+	if (fi->state != TBF_ST_ASSIGN) {
 		LOGPTBFDL(ctx->dl_tbf, LOGL_NOTICE, "Continue flow after IMM.ASS confirm\n");
+		return;
+	}
+
+	/* state TBF_ST_ASSIGN: */
+	tbf_assign_control_ts(ctx->tbf);
+
+	if (!tbf_can_upgrade_to_multislot(ctx->tbf)) {
+		/* change state to FLOW, so scheduler will start transmission */
+		osmo_fsm_inst_dispatch(fi, TBF_EV_ASSIGN_READY_CCCH, NULL);
+		return;
+	}
+
+	/* This tbf can be upgraded to use multiple DL timeslots and now that there is already
+	 * one slot assigned send another DL assignment via PDCH.
+	 */
+
+	/* keep TO flags */
+	ctx->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
+
+	rc = dl_tbf_upgrade_to_multislot(ctx->dl_tbf);
+	if (rc < 0) {
+		tbf_free(ctx->tbf);
+		return;
+	}
+	dl_tbf_trigger_ass_on_pacch(ctx->dl_tbf, ctx->tbf);
 }
 
 static int tbf_dl_fsm_timer_cb(struct osmo_fsm_inst *fi)