Change in osmo-bts[master]: osmo-bts-trx: introduce and use struct trx_dl_burst_req

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

fixeria gerrit-no-reply at lists.osmocom.org
Sat Jun 13 17:24:57 UTC 2020


fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/18821 )


Change subject: osmo-bts-trx: introduce and use struct trx_dl_burst_req
......................................................................

osmo-bts-trx: introduce and use struct trx_dl_burst_req

This change is similar to what we did for Uplink bursts:

  - group all Downlink burst parameters into a single structure,
  - allocate it once and pass a pointer to lchan handlers,
  - pass a pointer to trx_if_send_burst().

Given that the structure is allocated and (zero-)initialized in
trx_sched_fn(), we can get rid of some memset() calls in lchan
handlers and thus improve the overall performance a bit.

Change-Id: If3014e69746559963569b77561dbf7b163c68ffa
---
M include/osmo-bts/scheduler.h
M include/osmo-bts/scheduler_backend.h
M src/common/scheduler.c
M src/osmo-bts-trx/sched_lchan_fcch_sch.c
M src/osmo-bts-trx/sched_lchan_pdtch.c
M src/osmo-bts-trx/sched_lchan_tchf.c
M src/osmo-bts-trx/sched_lchan_tchh.c
M src/osmo-bts-trx/sched_lchan_xcch.c
M src/osmo-bts-trx/scheduler_trx.c
M src/osmo-bts-trx/trx_if.c
M src/osmo-bts-trx/trx_if.h
M src/osmo-bts-virtual/scheduler_virtbts.c
12 files changed, 214 insertions(+), 241 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/21/18821/1

diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index 74102f3..a7bc6c7 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -250,6 +250,17 @@
 	size_t burst_len;
 };
 
+/*! DL burst request with the corresponding meta info */
+struct trx_dl_burst_req {
+	uint32_t fn;		/*!< TDMA frame number */
+	uint8_t tn;		/*!< TDMA timeslot number */
+	uint8_t att;		/*!< Tx power attenuation */
+
+	/*! Burst hard-bits buffer */
+	ubit_t burst[EGPRS_BURST_LEN];
+	size_t burst_len;
+};
+
 /*! Handle an UL burst received by PHY */
 int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi);
 
diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h
index cfbe7f2..be23c47 100644
--- a/include/osmo-bts/scheduler_backend.h
+++ b/include/osmo-bts/scheduler_backend.h
@@ -9,9 +9,8 @@
 typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn,
 			       uint32_t fn, enum trx_chan_type chan);
 
-typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
-				  uint32_t fn, enum trx_chan_type chan,
-				  uint8_t bid, uint16_t *nbits);
+typedef int trx_sched_dl_func(struct l1sched_trx *l1t, enum trx_chan_type chan,
+			      uint8_t bid, struct trx_dl_burst_req *br);
 
 typedef int trx_sched_ul_func(struct l1sched_trx *l1t, enum trx_chan_type chan,
 			      uint8_t bid, const struct trx_ul_burst_ind *bi);
@@ -56,20 +55,21 @@
 			   int16_t ta_offs_256bits, uint16_t ber10k, float rssi,
 			   uint8_t is_sub);
 
-ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
-ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
-ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
-ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
-ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
-ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
-ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
+int tx_idle_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+int tx_fcch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+int tx_sch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+int tx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+int tx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+int tx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+int tx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br);
+
 int rx_rach_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
 	       uint8_t bid, const struct trx_ul_burst_ind *bi);
 int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
@@ -81,7 +81,6 @@
 int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
 	       uint8_t bid, const struct trx_ul_burst_ind *bi);
 
-const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
-			      uint32_t fn, uint16_t *nbits);
+void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br);
 int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
 void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate);
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index 021a4cd..ed6c623 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -1154,23 +1154,21 @@
 }
 
 /* process downlink burst */
-const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
-				uint32_t fn, uint16_t *nbits)
+void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br)
 {
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn);
 	struct l1sched_chan_state *l1cs;
 	const struct trx_sched_frame *frame;
 	uint8_t offset, period, bid;
 	trx_sched_dl_func *func;
 	enum trx_chan_type chan;
-	ubit_t *bits = NULL;
 
 	if (!l1ts->mf_index)
 		goto no_data;
 
 	/* get frame from multiframe */
 	period = l1ts->mf_period;
-	offset = fn % period;
+	offset = br->fn % period;
 	frame = l1ts->mf_frames + offset;
 
 	chan = frame->dl_chan;
@@ -1180,42 +1178,37 @@
 	l1cs = &l1ts->chan_state[chan];
 
 	/* check if channel is active */
-	if (!TRX_CHAN_IS_ACTIVE(l1cs, chan)) {
-		if (nbits)
-			*nbits = GSM_BURST_LEN;
+	if (!TRX_CHAN_IS_ACTIVE(l1cs, chan))
 		goto no_data;
-	}
 
 	/* get burst from function */
-	bits = func(l1t, tn, fn, chan, bid, nbits);
+	if (func(l1t, chan, bid, br) != 0)
+		goto no_data;
 
 	/* encrypt */
-	if (bits && l1cs->dl_encr_algo) {
+	if (br->burst_len && l1cs->dl_encr_algo) {
 		ubit_t ks[114];
 		int i;
 
-		osmo_a5(l1cs->dl_encr_algo, l1cs->dl_encr_key, fn, ks, NULL);
+		osmo_a5(l1cs->dl_encr_algo, l1cs->dl_encr_key, br->fn, ks, NULL);
 		for (i = 0; i < 57; i++) {
-			bits[i + 3] ^= ks[i];
-			bits[i + 88] ^= ks[i + 57];
+			br->burst[i +  3] ^= ks[i];
+			br->burst[i + 88] ^= ks[i + 57];
 		}
 	}
 
 no_data:
 	/* in case of C0, we need a dummy burst to maintain RF power */
-	if (bits == NULL && l1t->trx == l1t->trx->bts->c0) {
+	if (!br->burst_len && l1t->trx == l1t->trx->bts->c0) {
 #if 0
 		if (chan != TRXC_IDLE) // hack
 			LOGP(DL1C, LOGL_DEBUG, "No burst data for %s fn=%u ts=%u "
 			     "burst=%d on C0, so filling with dummy burst\n",
 			     trx_chan_desc[chan].name, fn, tn, bid);
 #endif
-		bits = (ubit_t *) dummy_burst;
-		if (nbits)
-			*nbits = ARRAY_SIZE(dummy_burst);
+		memcpy(br->burst, dummy_burst, ARRAY_SIZE(dummy_burst));
+		br->burst_len = ARRAY_SIZE(dummy_burst);
 	}
-
-	return bits;
 }
 
 #define TDMA_FN_SUM(a, b) \
diff --git a/src/osmo-bts-trx/sched_lchan_fcch_sch.c b/src/osmo-bts-trx/sched_lchan_fcch_sch.c
index 63dd468..bc03f81 100644
--- a/src/osmo-bts-trx/sched_lchan_fcch_sch.c
+++ b/src/osmo-bts-trx/sched_lchan_fcch_sch.c
@@ -35,34 +35,32 @@
 #include <sched_utils.h>
 
 /* obtain a to-be-transmitted FCCH (frequency correction channel) burst */
-ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-		   enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_fcch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting FCCH\n");
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting FCCH\n");
 
-	if (nbits)
-		*nbits = GSM_BURST_LEN;
+	memcpy(br->burst, _sched_fcch_burst, GSM_BURST_LEN);
+	br->burst_len = GSM_BURST_LEN;
 
-	/* BURST BYPASS */
-
-	return (ubit_t *) _sched_fcch_burst;
+	return 0;
 }
 
 /* obtain a to-be-transmitted SCH (synchronization channel) burst */
-ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-		  enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_sch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	      uint8_t bid, struct trx_dl_burst_req *br)
 {
-	static ubit_t bits[GSM_BURST_LEN], burst[78];
+	ubit_t burst[78];
 	uint8_t sb_info[4];
 	struct	gsm_time t;
 	uint8_t t3p, bsic;
 
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting SCH\n");
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting SCH\n");
 
 	/* BURST BYPASS */
 
 	/* create SB info from GSM time and BSIC */
-	gsm_fn2gsmtime(&t, fn);
+	gsm_fn2gsmtime(&t, br->fn);
 	t3p = t.t3 / 10;
 	bsic = l1t->trx->bts->bsic;
 	sb_info[0] =
@@ -81,14 +79,11 @@
 	gsm0503_sch_encode(burst, sb_info);
 
 	/* compose burst */
-	memset(bits, 0, 3);
-	memcpy(bits + 3, burst, 39);
-	memcpy(bits + 42, _sched_sch_train, 64);
-	memcpy(bits + 106, burst + 39, 39);
-	memset(bits + 145, 0, 3);
+	memcpy(br->burst + 3, burst, 39);
+	memcpy(br->burst + 42, _sched_sch_train, 64);
+	memcpy(br->burst + 106, burst + 39, 39);
 
-	if (nbits)
-		*nbits = GSM_BURST_LEN;
+	br->burst_len = GSM_BURST_LEN;
 
-	return bits;
+	return 0;
 }
diff --git a/src/osmo-bts-trx/sched_lchan_pdtch.c b/src/osmo-bts-trx/sched_lchan_pdtch.c
index 8b39797..259d336 100644
--- a/src/osmo-bts-trx/sched_lchan_pdtch.c
+++ b/src/osmo-bts-trx/sched_lchan_pdtch.c
@@ -154,30 +154,29 @@
 }
 
 /* obtain a to-be-transmitted PDTCH (packet data) burst */
-ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-		    enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	        uint8_t bid, struct trx_dl_burst_req *br)
 {
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
-	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn);
+	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn];
 	struct msgb *msg = NULL; /* make GCC happy */
 	ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts;
 	enum trx_burst_type *burst_type = &l1ts->chan_state[chan].dl_burst_type;
-	static ubit_t bits[EGPRS_BURST_LEN];
 	int rc = 0;
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
 		if (!*bursts_p)
-			return NULL;
+			return 0;
 		goto send_burst;
 	}
 
 	/* get mac block from queue */
-	msg = _sched_dequeue_prim(l1t, tn, fn, chan);
+	msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan);
 	if (msg)
 		goto got_msg;
 
-	LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No prim for transmit.\n");
+	LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No prim for transmit.\n");
 
 no_msg:
 	/* free burst memory */
@@ -185,7 +184,7 @@
 		talloc_free(*bursts_p);
 		*bursts_p = NULL;
 	}
-	return NULL;
+	return -ENODEV;
 
 got_msg:
 	/* BURST BYPASS */
@@ -195,7 +194,7 @@
 		*bursts_p = talloc_zero_size(tall_bts_ctx,
 					     GSM0503_EGPRS_BURSTS_NBITS);
 		if (!*bursts_p)
-			return NULL;
+			return -ENOMEM;
 	}
 
 	/* encode bursts */
@@ -205,7 +204,7 @@
 
 	/* check validity of message */
 	if (rc < 0) {
-		LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim invalid length, please FIX! "
+		LOGL1S(DL1P, LOGL_FATAL, l1t, br->tn, chan, br->fn, "Prim invalid length, please FIX! "
 			"(len=%ld)\n", (long)(msg->tail - msg->l2h));
 		/* free message */
 		msgb_free(msg);
@@ -223,27 +222,23 @@
 	/* compose burst */
 	if (*burst_type == TRX_BURST_8PSK) {
 		burst = *bursts_p + bid * 348;
-		memset(bits, 1, 9);
-		memcpy(bits + 9, burst, 174);
-		memcpy(bits + 183, _sched_egprs_tsc[gsm_ts_tsc(ts)], 78);
-		memcpy(bits + 261, burst + 174, 174);
-		memset(bits + 435, 1, 9);
+		memset(br->burst, 1, 9);
+		memcpy(br->burst + 9, burst, 174);
+		memcpy(br->burst + 183, _sched_egprs_tsc[gsm_ts_tsc(ts)], 78);
+		memcpy(br->burst + 261, burst + 174, 174);
+		memset(br->burst + 435, 1, 9);
 
-		if (nbits)
-			*nbits = EGPRS_BURST_LEN;
+		br->burst_len = EGPRS_BURST_LEN;
 	} else {
 		burst = *bursts_p + bid * 116;
-		memset(bits, 0, 3);
-		memcpy(bits + 3, burst, 58);
-		memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
-		memcpy(bits + 87, burst + 58, 58);
-		memset(bits + 145, 0, 3);
+		memcpy(br->burst + 3, burst, 58);
+		memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
+		memcpy(br->burst + 87, burst + 58, 58);
 
-		if (nbits)
-			*nbits = GSM_BURST_LEN;
+		br->burst_len = GSM_BURST_LEN;
 	}
 
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid);
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid);
 
-	return bits;
+	return 0;
 }
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c
index fb11f45..80115a9 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -491,25 +491,24 @@
 }
 
 /* obtain a to-be-transmitted TCH/F (Full Traffic Channel) burst */
-ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-		   enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
 	struct msgb *msg_tch = NULL, *msg_facch = NULL;
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
-	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn);
+	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn];
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
 	uint8_t tch_mode = chan_state->tch_mode;
 	ubit_t *burst, **bursts_p = &chan_state->dl_bursts;
-	static ubit_t bits[GSM_BURST_LEN];
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
 		if (!*bursts_p)
-			return NULL;
+			return 0;
 		goto send_burst;
 	}
 
-	tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch);
+	tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch);
 
 	/* BURST BYPASS */
 
@@ -518,7 +517,7 @@
 	if (!*bursts_p) {
 		*bursts_p = talloc_zero_size(tall_bts_ctx, 928);
 		if (!*bursts_p)
-			return NULL;
+			return -ENOMEM;
 	} else {
 		memcpy(*bursts_p, *bursts_p + 464, 464);
 		memset(*bursts_p + 464, 0, 464);
@@ -526,7 +525,7 @@
 
 	/* no message at all */
 	if (!msg_tch && !msg_facch) {
-		LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No TCH or FACCH prim for transmit.\n");
+		LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No TCH or FACCH prim for transmit.\n");
 		goto send_burst;
 	}
 
@@ -539,7 +538,7 @@
 		 * the first FN 0,8,17 defines that CMR is included in frame.
 		 */
 		gsm0503_tch_afs_encode(*bursts_p, msg_tch->l2h + 2,
-			msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(fn),
+			msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn),
 			chan_state->codec, chan_state->codecs,
 			chan_state->dl_ft,
 			chan_state->dl_cmr);
@@ -555,16 +554,13 @@
 send_burst:
 	/* compose burst */
 	burst = *bursts_p + bid * 116;
-	memset(bits, 0, 3);
-	memcpy(bits + 3, burst, 58);
-	memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
-	memcpy(bits + 87, burst + 58, 58);
-	memset(bits + 145, 0, 3);
+	memcpy(br->burst + 3, burst, 58);
+	memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
+	memcpy(br->burst + 87, burst + 58, 58);
 
-	if (nbits)
-		*nbits = GSM_BURST_LEN;
+	br->burst_len = GSM_BURST_LEN;
 
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid);
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid);
 
-	return bits;
+	return 0;
 }
diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c
index 1895038..8adaec3 100644
--- a/src/osmo-bts-trx/sched_lchan_tchh.c
+++ b/src/osmo-bts-trx/sched_lchan_tchh.c
@@ -313,30 +313,29 @@
 			  struct msgb **_msg_tch, struct msgb **_msg_facch);
 
 /* obtain a to-be-transmitted TCH/H (Half Traffic Channel) burst */
-ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-		   enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
 	struct msgb *msg_tch = NULL, *msg_facch = NULL;
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
-	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn);
+	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn];
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
 	uint8_t tch_mode = chan_state->tch_mode;
 	ubit_t *burst, **bursts_p = &chan_state->dl_bursts;
-	static ubit_t bits[GSM_BURST_LEN];
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
 		if (!*bursts_p)
-			return NULL;
+			return 0;
 		goto send_burst;
 	}
 
 	/* get TCH and/or FACCH */
-	tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch);
+	tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch);
 
 	/* check for FACCH alignment */
-	if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) {
-		LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot transmit FACCH starting on "
+	if (msg_facch && ((((br->fn + 4) % 26) >> 2) & 1)) {
+		LOGL1S(DL1P, LOGL_ERROR, l1t, br->tn, chan, br->fn, "Cannot transmit FACCH starting on "
 			"even frames, please fix RTS!\n");
 		msgb_free(msg_facch);
 		msg_facch = NULL;
@@ -349,7 +348,7 @@
 	if (!*bursts_p) {
 		*bursts_p = talloc_zero_size(tall_bts_ctx, 696);
 		if (!*bursts_p)
-			return NULL;
+			return -ENOMEM;
 	} else {
 		memcpy(*bursts_p, *bursts_p + 232, 232);
 		if (chan_state->dl_ongoing_facch) {
@@ -362,7 +361,7 @@
 
 	/* no message at all */
 	if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) {
-		LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No TCH or FACCH prim for transmit.\n");
+		LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No TCH or FACCH prim for transmit.\n");
 		goto send_burst;
 	}
 
@@ -377,7 +376,7 @@
 		 * in frame, the first FN 0,8,17 or 1,9,18 defines that CMR is
 		 * included in frame. */
 		gsm0503_tch_ahs_encode(*bursts_p, msg_tch->l2h + 2,
-			msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(fn),
+			msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn),
 			chan_state->codec, chan_state->codecs,
 			chan_state->dl_ft,
 			chan_state->dl_cmr);
@@ -393,16 +392,13 @@
 send_burst:
 	/* compose burst */
 	burst = *bursts_p + bid * 116;
-	memset(bits, 0, 3);
-	memcpy(bits + 3, burst, 58);
-	memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
-	memcpy(bits + 87, burst + 58, 58);
-	memset(bits + 145, 0, 3);
+	memcpy(br->burst + 3, burst, 58);
+	memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
+	memcpy(br->burst + 87, burst + 58, 58);
 
-	if (nbits)
-		*nbits = GSM_BURST_LEN;
+	br->burst_len = GSM_BURST_LEN;
 
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid);
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid);
 
-	return bits;
+	return 0;
 }
diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c b/src/osmo-bts-trx/sched_lchan_xcch.c
index a16553f..e2670d8 100644
--- a/src/osmo-bts-trx/sched_lchan_xcch.c
+++ b/src/osmo-bts-trx/sched_lchan_xcch.c
@@ -145,28 +145,27 @@
 }
 
 /* obtain a to-be-transmitted xCCH (e.g SACCH or SDCCH) burst */
-ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-		   enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
-	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn);
+	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn];
 	struct msgb *msg = NULL; /* make GCC happy */
 	ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts;
-	static ubit_t bits[GSM_BURST_LEN];
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
 		if (!*bursts_p)
-			return NULL;
+			return 0;
 		goto send_burst;
 	}
 
 	/* get mac block from queue */
-	msg = _sched_dequeue_prim(l1t, tn, fn, chan);
+	msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan);
 	if (msg)
 		goto got_msg;
 
-	LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No prim for transmit.\n");
+	LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No prim for transmit.\n");
 
 no_msg:
 	/* free burst memory */
@@ -174,12 +173,12 @@
 		talloc_free(*bursts_p);
 		*bursts_p = NULL;
 	}
-	return NULL;
+	return -ENODEV;
 
 got_msg:
 	/* check validity of message */
 	if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) {
-		LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! "
+		LOGL1S(DL1P, LOGL_FATAL, l1t, br->tn, chan, br->fn, "Prim not 23 bytes, please FIX! "
 			"(len=%d)\n", msgb_l2len(msg));
 		/* free message */
 		msgb_free(msg);
@@ -197,7 +196,7 @@
 
 			/* Note: RSSI is set to 0 to indicate to the higher
 			 * layers that this is a faked ph_data_ind */
-			_sched_compose_ph_data_ind(l1t, tn, 0, chan, NULL, 0,
+			_sched_compose_ph_data_ind(l1t, br->tn, 0, chan, NULL, 0,
 						   0, 0, 0, 10000,
 						   PRES_INFO_INVALID);
 		}
@@ -207,7 +206,7 @@
 	if (!*bursts_p) {
 		*bursts_p = talloc_zero_size(tall_bts_ctx, 464);
 		if (!*bursts_p)
-			return NULL;
+			return -ENOMEM;
 	}
 
 	/* encode bursts */
@@ -219,16 +218,13 @@
 send_burst:
 	/* compose burst */
 	burst = *bursts_p + bid * 116;
-	memset(bits, 0, 3);
-	memcpy(bits + 3, burst, 58);
-	memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
-	memcpy(bits + 87, burst + 58, 58);
-	memset(bits + 145, 0, 3);
+	memcpy(br->burst + 3, burst, 58);
+	memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
+	memcpy(br->burst + 87, burst + 58, 58);
 
-	if (nbits)
-		*nbits = GSM_BURST_LEN;
+	br->burst_len = GSM_BURST_LEN;
 
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid);
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid);
 
-	return bits;
+	return 0;
 }
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index 4fb0e23..6996593 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -48,25 +48,19 @@
 #include "trx_if.h"
 
 /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */
-ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_idle_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
-	LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting IDLE\n");
-
-	if (nbits)
-		*nbits = GSM_BURST_LEN;
-
-	return NULL;
+	LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting IDLE\n");
+	return 0;
 }
 
 /* schedule all frames of all TRX for given FN */
 static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
 {
+	struct trx_dl_burst_req br;
 	struct gsm_bts_trx *trx;
 	uint8_t tn;
-	const ubit_t *bits;
-	uint8_t gain;
-	uint16_t nbits = 0;
 
 	/* send time indication */
 	l1if_mph_time_ind(bts, fn);
@@ -91,15 +85,21 @@
 			/* ready-to-send */
 			_sched_rts(l1t, tn,
 				(fn + plink->u.osmotrx.rts_advance) % GSM_HYPERFRAME);
+
+			/* TODO: Tx attenuation is always 0? */
+			br = (struct trx_dl_burst_req) {
+				.fn = fn, .tn = tn,
+				.att = 0,
+			};
+
 			/* get burst for FN */
-			bits = _sched_dl_burst(l1t, tn, fn, &nbits);
-			if (!bits) {
+			_sched_dl_burst(l1t, &br);
+			if (br.burst_len == 0) {
 				/* if no bits, send no burst */
 				continue;
-			} else
-				gain = 0;
-			if (nbits)
-				trx_if_send_burst(l1h, tn, fn, gain, bits, nbits);
+			}
+
+			trx_if_send_burst(l1h, &br);
 		}
 	}
 
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index ccbcd2f..1953f71 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -1101,27 +1101,23 @@
 
 /*! Send burst data for given FN/timeslot to TRX
  *  \param[inout] l1h TRX Layer1 handle referring to TX
- *  \param[in] tn Timeslot Number (0..7)
- *  \param[in] fn GSM Frame Number
- *  \param[in] pwr Transmit Power to use
- *  \param[in] bits Unpacked bits to be transmitted
- *  \param[in] nbits Number of \a bits
+ *  \param[in] br Downlink burst request structure
  *  \returns 0 on success; negative on error */
-int trx_if_send_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
-	const ubit_t *bits, uint16_t nbits)
+int trx_if_send_burst(struct trx_l1h *l1h, const struct trx_dl_burst_req *br)
 {
 	ssize_t snd_len;
 	uint8_t hdr_ver = l1h->config.trxd_hdr_ver_use;
 	uint8_t buf[TRX_DATA_MSG_MAX_LEN];
 
-	if ((nbits != GSM_BURST_LEN) && (nbits != EGPRS_BURST_LEN)) {
-		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, "Tx burst length %u invalid\n", nbits);
+	if ((br->burst_len != GSM_BURST_LEN) && (br->burst_len != EGPRS_BURST_LEN)) {
+		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, "Tx burst length %zu invalid\n",
+			br->burst_len);
 		return -1;
 	}
 
 	LOGPPHI(l1h->phy_inst, DTRX, LOGL_DEBUG,
-		"Tx burst (hdr_ver=%u): tn=%u fn=%u pwr=%u\n",
-		hdr_ver, tn, fn, pwr);
+		"Tx burst (hdr_ver=%u): tn=%u fn=%u att=%u\n",
+		hdr_ver, br->tn, br->fn, br->att);
 
 	switch (hdr_ver) {
 	case 0:
@@ -1135,16 +1131,16 @@
 		return -ENOTSUP;
 	}
 
-	buf[0] = ((hdr_ver & 0x0f) << 4) | tn;
-	osmo_store32be(fn, buf + 1);
-	buf[5] = pwr;
+	buf[0] = ((hdr_ver & 0x0f) << 4) | br->tn;
+	osmo_store32be(br->fn, buf + 1);
+	buf[5] = br->att;
 
 	/* copy ubits {0,1} */
-	memcpy(buf + 6, bits, nbits);
+	memcpy(buf + 6, br->burst, br->burst_len);
 
 	/* we must be sure that TRX is on */
 	if (trx_if_powered(l1h)) {
-		snd_len = send(l1h->trx_ofd_data.fd, buf, nbits + 6, 0);
+		snd_len = send(l1h->trx_ofd_data.fd, buf, br->burst_len + 6, 0);
 		if (snd_len <= 0) {
 			strerror_r(errno, (char *)buf, sizeof(buf));
 			LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR,
diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h
index 34335f8..16b6c76 100644
--- a/src/osmo-bts-trx/trx_if.h
+++ b/src/osmo-bts-trx/trx_if.h
@@ -1,6 +1,7 @@
 #ifndef TRX_IF_H
 #define TRX_IF_H
 
+struct trx_dl_burst_req;
 struct trx_l1h;
 
 struct trx_ctrl_msg {
@@ -33,8 +34,7 @@
 int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn);
 int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
 int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
-int trx_if_send_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
-	const ubit_t *bits, uint16_t nbits);
+int trx_if_send_burst(struct trx_l1h *l1h, const struct trx_dl_burst_req *br);
 int trx_if_powered(struct trx_l1h *l1h);
 
 /* The latest supported TRXD header format version */
diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c
index eabd23b..d3fdf1a 100644
--- a/src/osmo-bts-virtual/scheduler_virtbts.c
+++ b/src/osmo-bts-virtual/scheduler_virtbts.c
@@ -173,72 +173,72 @@
  */
 
 /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */
-ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_idle_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
-	return NULL;
+	return 0;
 }
 
-ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_fcch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
-	return NULL;
+	return 0;
 }
 
-ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_sch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
-	return NULL;
+	return 0;
 }
 
-ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
 	struct msgb *msg;
 
 	if (bid > 0)
-		return NULL;
+		return 0;
 
 	/* get mac block from queue */
-	msg = _sched_dequeue_prim(l1t, tn, fn, chan);
+	msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan);
 	if (!msg) {
-		LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n");
-		return NULL;
+		LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n");
+		return -ENODEV;
 	}
 
 	/* check validity of message */
 	if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) {
-		LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! (len=%d)\n",
+		LOGL1S(DL1P, LOGL_FATAL, l1t, br->tn, chan, br->fn, "Prim not 23 bytes, please FIX! (len=%d)\n",
 			msgb_l2len(msg));
 		/* free message */
 		msgb_free(msg);
-		return NULL;
+		return -EINVAL;
 	}
 
 	/* transmit the msg received on dl from bsc to layer1 (virt Um) */
-	tx_to_virt_um(l1t, tn, fn, chan, msg);
+	tx_to_virt_um(l1t, br->tn, br->fn, chan, msg);
 
-	return NULL;
+	return 0;
 }
 
-ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
 	struct msgb *msg = NULL; /* make GCC happy */
 
 	if (bid > 0)
-		return NULL;
+		return 0;
 
 	/* get mac block from queue */
-	msg = _sched_dequeue_prim(l1t, tn, fn, chan);
+	msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan);
 	if (!msg) {
-		LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n");
-		return NULL;
+		LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n");
+		return -ENODEV;
 	}
 
-	tx_to_virt_um(l1t, tn, fn, chan, msg);
+	tx_to_virt_um(l1t, br->tn, br->fn, chan, msg);
 
-	return NULL;
+	return 0;
 }
 
 static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
@@ -418,53 +418,51 @@
 	*_msg_facch = msg_facch;
 }
 
-ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
 	struct msgb *msg_tch = NULL, *msg_facch = NULL;
 
 	if (bid > 0)
-		return NULL;
+		return 0;
 
-	tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch,
-		(((fn + 4) % 26) >> 2) & 1);
+	tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch,
+		(((br->fn + 4) % 26) >> 2) & 1);
 
 	/* no message at all */
 	if (!msg_tch && !msg_facch) {
-		LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n");
-		goto send_burst;
+		LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n");
+		return -ENODEV;
 	}
 
 	if (msg_facch) {
-		tx_to_virt_um(l1t, tn, fn, chan, msg_facch);
+		tx_to_virt_um(l1t, br->tn, br->fn, chan, msg_facch);
 		msgb_free(msg_tch);
 	} else if (msg_tch)
-		tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch);
+		tx_to_virt_um_voice_frame(l1t, br->tn, br->fn, chan, msg_tch);
 
-send_burst:
-
-	return NULL;
+	return 0;
 }
 
-ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
+int tx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
+	       uint8_t bid, struct trx_dl_burst_req *br)
 {
 	struct msgb *msg_tch = NULL, *msg_facch = NULL;
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn);
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
 	//uint8_t tch_mode = chan_state->tch_mode;
 
 	/* send burst, if we already got a frame */
 	if (bid > 0)
-		return NULL;
+		return 0;
 
 	/* get TCH and/or FACCH */
-	tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch,
-		(((fn + 4) % 26) >> 2) & 1);
+	tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch,
+		(((br->fn + 4) % 26) >> 2) & 1);
 
 	/* check for FACCH alignment */
-	if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) {
-		LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot transmit FACCH starting on "
+	if (msg_facch && ((((br->fn + 4) % 26) >> 2) & 1)) {
+		LOGL1S(DL1P, LOGL_ERROR, l1t, br->tn, chan, br->fn, "Cannot transmit FACCH starting on "
 			"even frames, please fix RTS!\n");
 		msgb_free(msg_facch);
 		msg_facch = NULL;
@@ -472,18 +470,17 @@
 
 	/* no message at all */
 	if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) {
-		LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n");
-		goto send_burst;
+		LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n");
+		return -ENODEV;
 	}
 
 	if (msg_facch) {
-		tx_to_virt_um(l1t, tn, fn, chan, msg_facch);
+		tx_to_virt_um(l1t, br->tn, br->fn, chan, msg_facch);
 		msgb_free(msg_tch);
 	} else if (msg_tch)
-		tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch);
+		tx_to_virt_um_voice_frame(l1t, br->tn, br->fn, chan, msg_tch);
 
-send_burst:
-	return NULL;
+	return 0;
 }
 
 
@@ -550,11 +547,10 @@
 	llist_for_each_entry(trx, &bts->trx_list, list) {
 		struct phy_instance *pinst = trx_phy_instance(trx);
 		struct l1sched_trx *l1t = &pinst->u.virt.sched;
-		int tn;
-		uint16_t nbits;
+		struct trx_dl_burst_req br = { .fn = fn };
 
 		/* do for each of the 8 timeslots */
-		for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
+		for (br.tn = 0; br.tn < ARRAY_SIZE(l1t->ts); br.tn++) {
 			/* Generate RTS indication to higher layers */
 			/* This will basically do 2 things (check l1_if:bts_model_l1sap_down):
 			 * 1) Get pending messages from layer 2 (from the lapdm queue)
@@ -562,13 +558,13 @@
 			 *    --> Handle and process non-transparent RSL-Messages (activate channel, )
 			 *    --> Forward transparent RSL-DATA-Messages to the ms by appending them to
 			 *        the l1-dl-queue */
-			_sched_rts(l1t, tn, (fn + RTS_ADVANCE) % GSM_HYPERFRAME);
+			_sched_rts(l1t, br.tn, (fn + RTS_ADVANCE) % GSM_HYPERFRAME);
 			/* schedule transmit backend functions */
 			/* Process data in the l1-dlqueue and forward it
 			 * to MS */
 			/* the returned bits are not used here, the routines called will directly forward their
 			 * bits to the virt Um */
-			_sched_dl_burst(l1t, tn, fn, &nbits);
+			_sched_dl_burst(l1t, &br);
 		}
 	}
 

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/18821
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: If3014e69746559963569b77561dbf7b163c68ffa
Gerrit-Change-Number: 18821
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200613/25c0bf1d/attachment.htm>


More information about the gerrit-log mailing list