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 <vyanits...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to