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

<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If3014e69746559963569b77561dbf7b163c68ffa </div>
<div style="display:none"> Gerrit-Change-Number: 18821 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>