fixeria has submitted this change. ( 
https://gerrit.osmocom.org/c/osmocom-bb/+/33708 )

Change subject: trxcon/l1sched: rework dequeueing of Tx prims
......................................................................

trxcon/l1sched: rework dequeueing of Tx prims

Centralized dequeueing of Tx prims in l1sched_pull_burst() is a working
approach, but doing this in each logical channel handler individually
is a lot more flexible.  This is how it's done in osmo-bts-trx, and
this allows implementing FACCH support for CSD channels.

Change-Id: I3d6c2136ff1855ab0aa9062b20b2a64fd0e5fe28
Related: OS#4396, OS#1572
---
M src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
M src/host/trxcon/include/osmocom/bb/l1sched/prim.h
M src/host/trxcon/src/sched_lchan_desc.c
M src/host/trxcon/src/sched_lchan_pdtch.c
M src/host/trxcon/src/sched_lchan_rach.c
M src/host/trxcon/src/sched_lchan_tchf.c
M src/host/trxcon/src/sched_lchan_tchh.c
M src/host/trxcon/src/sched_lchan_xcch.c
M src/host/trxcon/src/sched_prim.c
M src/host/trxcon/src/sched_trx.c
10 files changed, 174 insertions(+), 227 deletions(-)

Approvals:
  laforge: Looks good to me, but someone else must approve
  fixeria: Verified
  pespin: Looks good to me, approved




diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h 
b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
index 715b9a0..cee2660 100644
--- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
@@ -30,8 +30,6 @@
 #define L1SCHED_CH_FLAG_PDCH   (1 << 0)
 /* Should a channel be activated automatically */
 #define L1SCHED_CH_FLAG_AUTO   (1 << 1)
-/* Is continuous burst transmission assumed */
-#define L1SCHED_CH_FLAG_CBTX   (1 << 2)

 #define MAX_A5_KEY_LEN         (128 / 8)
 #define TRX_TS_COUNT           8
diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/prim.h 
b/src/host/trxcon/include/osmocom/bb/l1sched/prim.h
index 0575ad8..c0e6af6 100644
--- a/src/host/trxcon/include/osmocom/bb/l1sched/prim.h
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/prim.h
@@ -116,8 +116,9 @@
 struct msgb *l1sched_prim_alloc(enum l1sched_prim_type type,
                                enum osmo_prim_operation op);

-struct msgb *l1sched_lchan_prim_dequeue(struct l1sched_lchan_state *lchan, 
uint32_t fn);
-void l1sched_lchan_prim_assign_dummy(struct l1sched_lchan_state *lchan);
+struct msgb *l1sched_lchan_prim_dequeue_sacch(struct l1sched_lchan_state 
*lchan);
+struct msgb *l1sched_lchan_prim_dequeue_tch(struct l1sched_lchan_state *lchan, 
bool facch);
+struct msgb *l1sched_lchan_prim_dummy(struct l1sched_lchan_state *lchan);
 void l1sched_lchan_prim_drop(struct l1sched_lchan_state *lchan);

 int l1sched_lchan_emit_data_ind(struct l1sched_lchan_state *lchan,
diff --git a/src/host/trxcon/src/sched_lchan_desc.c 
b/src/host/trxcon/src/sched_lchan_desc.c
index 3b37c57..4943a71 100644
--- a/src/host/trxcon/src/sched_lchan_desc.c
+++ b/src/host/trxcon/src/sched_lchan_desc.c
@@ -131,7 +131,6 @@
                 * The MS shall continuously transmit bursts, even if there is 
nothing
                 * to send, unless DTX (Discontinuous Transmission) is used. */
                .burst_buf_size = 8 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_tchf_fn,
                .tx_fn = tx_tchf_fn,
        },
@@ -158,7 +157,6 @@
                 * The MS shall continuously transmit bursts, even if there is 
nothing
                 * to send, unless DTX (Discontinuous Transmission) is used. */
                .burst_buf_size = 6 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_tchh_fn,
                .tx_fn = tx_tchh_fn,
        },
@@ -170,7 +168,6 @@

                /* Same as for L1SCHED_TCHH_0, see above. */
                .burst_buf_size = 6 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_tchh_fn,
                .tx_fn = tx_tchh_fn,
        },
@@ -182,7 +179,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -194,7 +190,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -206,7 +201,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -218,7 +212,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -230,7 +223,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -242,7 +234,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -254,7 +245,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -266,7 +256,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -278,7 +267,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -290,7 +278,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -302,7 +289,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -314,7 +300,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -326,7 +311,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -338,7 +322,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -350,7 +333,6 @@

                /* Same as for L1SCHED_BCCH (xCCH), see above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -362,7 +344,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -374,7 +355,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -386,7 +366,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -398,7 +377,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH4_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -410,7 +388,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -422,7 +399,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -434,7 +410,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -446,7 +421,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -458,7 +432,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -470,7 +443,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -482,7 +454,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
@@ -494,7 +465,6 @@

                /* Same as for L1SCHED_BCCH and L1SCHED_SDCCH8_* (xCCH), see 
above. */
                .burst_buf_size = 4 * GSM_NBITS_NB_GMSK_PAYLOAD,
-               .flags = L1SCHED_CH_FLAG_CBTX,
                .rx_fn = rx_data_fn,
                .tx_fn = tx_data_fn,
        },
diff --git a/src/host/trxcon/src/sched_lchan_pdtch.c 
b/src/host/trxcon/src/sched_lchan_pdtch.c
index 4b5ffdf..03d43ce 100644
--- a/src/host/trxcon/src/sched_lchan_pdtch.c
+++ b/src/host/trxcon/src/sched_lchan_pdtch.c
@@ -101,6 +101,24 @@
        return 0;
 }

+static struct msgb *prim_dequeue_pdtch(struct l1sched_lchan_state *lchan, 
uint32_t fn)
+{
+       const struct l1sched_prim *prim;
+       struct msgb *msg;
+
+       msg = msgb_dequeue(&lchan->tx_prims);
+       if (msg == NULL)
+               return NULL;
+       prim = l1sched_prim_from_msgb(msg);
+
+       if (OSMO_LIKELY(prim->data_req.frame_nr == fn))
+               return msg;
+       LOGP_LCHAND(lchan, LOGL_ERROR,
+                   "%s(): dropping Tx primitive (current Fn=%u, prim Fn=%u)\n",
+                   __func__, fn, prim->data_req.frame_nr);
+       msgb_free(msg);
+       return NULL;
+}

 int tx_pdtch_fn(struct l1sched_lchan_state *lchan,
                struct l1sched_burst_req *br)
@@ -114,8 +132,17 @@
        mask = &lchan->tx_burst_mask;
        bursts_p = lchan->tx_bursts;

-       if (br->bid > 0)
+       if (br->bid > 0) {
+               if ((*mask & 0x01) != 0x01)
+                       return -ENOENT;
                goto send_burst;
+       }
+
+       *mask = *mask << 4;
+
+       lchan->prim = prim_dequeue_pdtch(lchan, br->fn);
+       if (lchan->prim == NULL)
+               return -ENOENT;

        /* Encode payload */
        rc = gsm0503_pdtch_encode(bursts_p, msgb_l2(lchan->prim), 
msgb_l2len(lchan->prim));
@@ -150,9 +177,6 @@
        if ((*mask & 0x0f) == 0x0f) {
                /* Confirm data / traffic sending (pass ownership of the prim) 
*/
                l1sched_lchan_emit_data_cnf(lchan, br->fn);
-
-               /* Reset mask */
-               *mask = 0x00;
        }

        return 0;
diff --git a/src/host/trxcon/src/sched_lchan_rach.c 
b/src/host/trxcon/src/sched_lchan_rach.c
index 109d100..8df7fa2 100644
--- a/src/host/trxcon/src/sched_lchan_rach.c
+++ b/src/host/trxcon/src/sched_lchan_rach.c
@@ -78,6 +78,11 @@
        uint8_t payload[36];
        int i, rc;

+       if (lchan->prim == NULL) {
+               lchan->prim = msgb_dequeue(&lchan->tx_prims);
+               if (lchan->prim == NULL)
+                       return 0;
+       }
        prim = l1sched_prim_from_msgb(lchan->prim);

        /* Delay sending according to offset value */
diff --git a/src/host/trxcon/src/sched_lchan_tchf.c 
b/src/host/trxcon/src/sched_lchan_tchf.c
index 9e8256f..6d48fc7 100644
--- a/src/host/trxcon/src/sched_lchan_tchf.c
+++ b/src/host/trxcon/src/sched_lchan_tchf.c
@@ -213,6 +213,30 @@
                                           n_errors, n_bits_total, true);
 }

+static struct msgb *prim_dequeue_tchf(struct l1sched_lchan_state *lchan)
+{
+       struct msgb *facch;
+       struct msgb *tch;
+
+       /* Attempt to find a pair of FACCH/F and TCH/F frames */
+       facch = l1sched_lchan_prim_dequeue_tch(lchan, true);
+       tch = l1sched_lchan_prim_dequeue_tch(lchan, false);
+
+       /* Prioritize FACCH/F, if found */
+       if (facch) {
+               /* One TCH/F prim is replaced */
+               if (tch)
+                       msgb_free(tch);
+               return facch;
+       } else if (tch) {
+               /* Only TCH/F prim was found */
+               return tch;
+       } else {
+               /* Nothing was found */
+               return NULL;
+       }
+}
+
 int tx_tchf_fn(struct l1sched_lchan_state *lchan,
               struct l1sched_burst_req *br)
 {
@@ -225,14 +249,24 @@
        mask = &lchan->tx_burst_mask;
        bursts_p = lchan->tx_bursts;

-       if (br->bid > 0)
+       if (br->bid > 0) {
+               if ((*mask & 0x01) != 0x01)
+                       return -ENOENT;
                goto send_burst;
+       }

        /* Shift the burst buffer by 4 bursts leftwards for interleaving */
        memcpy(&bursts_p[0], &bursts_p[464], 464);
        memset(&bursts_p[464], 0, 464);
        *mask = *mask << 4;

+       lchan->prim = prim_dequeue_tchf(lchan);
+       if (lchan->prim == NULL) {
+               lchan->prim = l1sched_lchan_prim_dummy(lchan);
+               if (lchan->prim == NULL)
+                       return -ENOENT;
+       }
+
        /* populate the buffer with bursts */
        switch (lchan->tch_mode) {
        case GSM48_CMODE_SIGN:
diff --git a/src/host/trxcon/src/sched_lchan_tchh.c 
b/src/host/trxcon/src/sched_lchan_tchh.c
index 6973f91..6affbc5 100644
--- a/src/host/trxcon/src/sched_lchan_tchh.c
+++ b/src/host/trxcon/src/sched_lchan_tchh.c
@@ -412,6 +412,40 @@
                                           n_errors, n_bits_total, true);
 }

+static struct msgb *prim_dequeue_tchh(struct l1sched_lchan_state *lchan, 
uint32_t fn)
+{
+       struct msgb *facch;
+       struct msgb *tch;
+       bool facch_now;
+
+       /* Can we initiate an UL FACCH/H frame transmission at this Fn? */
+       facch_now = l1sched_tchh_facch_start(lchan->type, fn, true);
+       if (!facch_now)
+               goto no_facch;
+
+       /* If there are no FACCH/H prims in the queue */
+       facch = l1sched_lchan_prim_dequeue_tch(lchan, true);
+       if (!facch) /* Just dequeue a TCH/H prim */
+               goto no_facch;
+
+       /* FACCH/H prim replaces two TCH/F prims */
+       tch = l1sched_lchan_prim_dequeue_tch(lchan, false);
+       if (tch) {
+               /* At least one TCH/H prim is dropped */
+               msgb_free(tch);
+
+               /* Attempt to find another */
+               tch = l1sched_lchan_prim_dequeue_tch(lchan, false);
+               if (tch) /* Drop the second TCH/H prim */
+                       msgb_free(tch);
+       }
+
+       return facch;
+
+no_facch:
+       return l1sched_lchan_prim_dequeue_tch(lchan, false);
+}
+
 int tx_tchh_fn(struct l1sched_lchan_state *lchan,
               struct l1sched_burst_req *br)
 {
@@ -424,8 +458,11 @@
        mask = &lchan->tx_burst_mask;
        bursts_p = lchan->tx_bursts;

-       if (br->bid > 0)
+       if (br->bid > 0) {
+               if ((*mask & 0x01) != 0x01)
+                       return -ENOENT;
                goto send_burst;
+       }

        if (*mask == 0x00) {
                /* Align transmission of the first FACCH/H frame */
@@ -444,6 +481,13 @@
        if (lchan->ul_facch_blocks > 2)
                goto send_burst;

+       lchan->prim = prim_dequeue_tchh(lchan, br->fn);
+       if (lchan->prim == NULL) {
+               lchan->prim = l1sched_lchan_prim_dummy(lchan);
+               if (lchan->prim == NULL)
+                       return -ENOENT;
+       }
+
        if (msgb_l2len(lchan->prim) == GSM_MACBLOCK_LEN)
                lchan->ul_facch_blocks = 6;

diff --git a/src/host/trxcon/src/sched_lchan_xcch.c 
b/src/host/trxcon/src/sched_lchan_xcch.c
index f76d518..7f1dd11 100644
--- a/src/host/trxcon/src/sched_lchan_xcch.c
+++ b/src/host/trxcon/src/sched_lchan_xcch.c
@@ -98,6 +98,27 @@
                                           n_errors, n_bits_total, false);
 }

+static struct msgb *prim_dequeue_xcch(struct l1sched_lchan_state *lchan)
+{
+       struct msgb *msg;
+
+       if (L1SCHED_CHAN_IS_SACCH(lchan->type))
+               return l1sched_lchan_prim_dequeue_sacch(lchan);
+       if ((msg = msgb_dequeue(&lchan->tx_prims)) == NULL)
+               return NULL;
+
+       /* Check the prim payload length */
+       if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) {
+               LOGP_LCHAND(lchan, LOGL_ERROR,
+                           "Primitive has odd length %u (expected %u), so 
dropping...\n",
+                           msgb_l2len(msg), GSM_MACBLOCK_LEN);
+               msgb_free(msg);
+               return NULL;
+       }
+
+       return msg;
+}
+
 int tx_data_fn(struct l1sched_lchan_state *lchan,
               struct l1sched_burst_req *br)
 {
@@ -110,18 +131,19 @@
        mask = &lchan->tx_burst_mask;
        bursts_p = lchan->tx_bursts;

-       if (br->bid > 0)
+       if (br->bid > 0) {
+               if ((*mask & 0x01) != 0x01)
+                       return -ENOENT;
                goto send_burst;
-
-       /* Check the prim payload length */
-       if (msgb_l2len(lchan->prim) != GSM_MACBLOCK_LEN) {
-               LOGP_LCHAND(lchan, LOGL_ERROR,
-                           "Primitive has odd length %u (expected %u), so 
dropping...\n",
-                           msgb_l2len(lchan->prim), GSM_MACBLOCK_LEN);
-               l1sched_lchan_prim_drop(lchan);
-               return -EINVAL;
        }

+       *mask = *mask << 4;
+
+       lchan->prim = prim_dequeue_xcch(lchan);
+       if (lchan->prim == NULL)
+               lchan->prim = l1sched_lchan_prim_dummy(lchan);
+       OSMO_ASSERT(lchan->prim != NULL);
+
        /* Encode payload */
        rc = gsm0503_xcch_encode(bursts_p, msgb_l2(lchan->prim));
        if (rc) {
@@ -155,9 +177,6 @@
        if ((*mask & 0x0f) == 0x0f) {
                /* Confirm data sending (pass ownership of the prim) */
                l1sched_lchan_emit_data_cnf(lchan, br->fn);
-
-               /* Reset mask */
-               *mask = 0x00;
        }

        return 0;
diff --git a/src/host/trxcon/src/sched_prim.c b/src/host/trxcon/src/sched_prim.c
index 44cfd37..3301df4 100644
--- a/src/host/trxcon/src/sched_prim.c
+++ b/src/host/trxcon/src/sched_prim.c
@@ -151,7 +151,7 @@
  * @param  lchan lchan to assign a primitive
  * @return       SACCH primitive to be transmitted
  */
-static struct msgb *prim_dequeue_sacch(struct l1sched_lchan_state *lchan)
+struct msgb *l1sched_lchan_prim_dequeue_sacch(struct l1sched_lchan_state 
*lchan)
 {
        struct msgb *msg_nmr = NULL;
        struct msgb *msg_mr = NULL;
@@ -228,7 +228,7 @@
  * @return            either a FACCH, or a TCH primitive if found,
  *                    otherwise NULL
  */
-static struct msgb *prim_dequeue_tch(struct l1sched_lchan_state *lchan, bool 
facch)
+struct msgb *l1sched_lchan_prim_dequeue_tch(struct l1sched_lchan_state *lchan, 
bool facch)
 {
        struct msgb *msg;

@@ -249,146 +249,6 @@
 }

 /**
- * Dequeues either a TCH/F, or a FACCH/F prim (preferred).
- * If a FACCH/F prim is found, one TCH/F prim is being
- * dropped (i.e. replaced).
- *
- * @param  lchan logical channel state
- * @return       either a FACCH/F, or a TCH/F primitive,
- *               otherwise NULL
- */
-static struct msgb *prim_dequeue_tch_f(struct l1sched_lchan_state *lchan)
-{
-       struct msgb *facch;
-       struct msgb *tch;
-
-       /* Attempt to find a pair of both FACCH/F and TCH/F frames */
-       facch = prim_dequeue_tch(lchan, true);
-       tch = prim_dequeue_tch(lchan, false);
-
-       /* Prioritize FACCH/F, if found */
-       if (facch) {
-               /* One TCH/F prim is replaced */
-               if (tch)
-                       msgb_free(tch);
-               return facch;
-       } else if (tch) {
-               /* Only TCH/F prim was found */
-               return tch;
-       } else {
-               /* Nothing was found */
-               return NULL;
-       }
-}
-
-/**
- * Dequeues either a TCH/H, or a FACCH/H prim (preferred).
- * If a FACCH/H prim is found, two TCH/H prims are being
- * dropped (i.e. replaced).
- *
- * According to GSM 05.02, the following blocks can be used
- * to carry FACCH/H data (see clause 7, table 1 of 9):
- *
- * UL FACCH/H0:
- * B0(0,2,4,6,8,10), B1(8,10,13,15,17,19), B2(17,19,21,23,0,2)
- *
- * UL FACCH/H1:
- * B0(1,3,5,7,9,11), B1(9,11,14,16,18,20), B2(18,20,22,24,1,3)
- *
- * where the numbers within brackets are fn % 26.
- *
- * @param  lchan      logical channel state
- * @param  fn         the current frame number
- * @return            either a FACCH/H, or a TCH/H primitive,
- *                    otherwise NULL
- */
-static struct msgb *prim_dequeue_tch_h(struct l1sched_lchan_state *lchan, 
uint32_t fn)
-{
-       struct msgb *facch;
-       struct msgb *tch;
-       bool facch_now;
-
-       /* May we initiate an UL FACCH/H frame transmission now? */
-       facch_now = l1sched_tchh_facch_start(lchan->type, fn, true);
-       if (!facch_now) /* Just dequeue a TCH/H prim */
-               goto no_facch;
-
-       /* If there are no FACCH/H prims in the queue */
-       facch = prim_dequeue_tch(lchan, true);
-       if (!facch) /* Just dequeue a TCH/H prim */
-               goto no_facch;
-
-       /* FACCH/H prim replaces two TCH/F prims */
-       tch = prim_dequeue_tch(lchan, false);
-       if (tch) {
-               /* At least one TCH/H prim is dropped */
-               msgb_free(tch);
-
-               /* Attempt to find another */
-               tch = prim_dequeue_tch(lchan, false);
-               if (tch) /* Drop the second TCH/H prim */
-                       msgb_free(tch);
-       }
-
-       return facch;
-
-no_facch:
-       return prim_dequeue_tch(lchan, false);
-}
-
-/**
- * Dequeues a primitive from the Tx queue of the given lchan.
- *
- * @param  lchan      logical channel state
- * @param  fn         the current frame number (used for FACCH/H)
- * @return            a primitive or NULL if not found
- */
-struct msgb *l1sched_lchan_prim_dequeue(struct l1sched_lchan_state *lchan, 
uint32_t fn)
-{
-       /* SACCH is unorthodox, see 3GPP TS 04.08, section 3.4.1 */
-       if (L1SCHED_CHAN_IS_SACCH(lchan->type))
-               return prim_dequeue_sacch(lchan);
-
-       /* There is nothing to dequeue */
-       if (llist_empty(&lchan->tx_prims))
-               return NULL;
-
-       switch (lchan->type) {
-       /* TCH/F requires FACCH/F prioritization */
-       case L1SCHED_TCHF:
-               return prim_dequeue_tch_f(lchan);
-
-       /* FACCH/H prioritization is a bit more complex */
-       case L1SCHED_TCHH_0:
-       case L1SCHED_TCHH_1:
-               return prim_dequeue_tch_h(lchan, fn);
-
-       /* PDCH is timing critical, we need to check TDMA Fn */
-       case L1SCHED_PDTCH:
-       {
-               struct msgb *msg = msgb_dequeue(&lchan->tx_prims);
-               const struct l1sched_prim *prim;
-
-               if (msg == NULL)
-                       return NULL;
-               prim = l1sched_prim_from_msgb(msg);
-
-               if (OSMO_LIKELY(prim->data_req.frame_nr == fn))
-                       return msg;
-               LOGP_LCHAND(lchan, LOGL_ERROR,
-                           "%s(): dropping Tx primitive (current Fn=%u, prim 
Fn=%u)\n",
-                           __func__, fn, prim->data_req.frame_nr);
-               msgb_free(msg);
-               return NULL;
-       }
-
-       /* Other kinds of logical channels */
-       default:
-               return msgb_dequeue(&lchan->tx_prims);
-       }
-}
-
-/**
  * Drops the current primitive of specified logical channel
  *
  * @param lchan a logical channel to drop prim from
@@ -400,14 +260,13 @@
 }

 /**
- * Assigns a dummy primitive to a lchan depending on its type.
- * Could be used when there is nothing to transmit, but
- * CBTX (Continuous Burst Transmission) is assumed.
+ * Allocate a dummy DATA.req for the given logical channel.
+ * To be used when no suitable DATA.req is present in the Tx queue.
  *
- * @param  lchan lchan to assign a primitive
- * @return       zero in case of success, otherwise a error code
+ * @param  lchan lchan to allocate a dummy primitive for
+ * @return       an msgb with DATA.req primitive, or NULL
  */
-void l1sched_lchan_prim_assign_dummy(struct l1sched_lchan_state *lchan)
+struct msgb *l1sched_lchan_prim_dummy(struct l1sched_lchan_state *lchan)
 {
        const struct l1sched_lchan_desc *lchan_desc;
        enum l1sched_lchan_type chan = lchan->type;
@@ -428,8 +287,6 @@
                /* Pending part is to be randomized */
        };

-       /* Make sure that there is no existing primitive */
-       OSMO_ASSERT(lchan->prim == NULL);
        /* Not applicable for SACCH! */
        OSMO_ASSERT(!L1SCHED_CHAN_IS_SACCH(lchan->type));

@@ -446,7 +303,7 @@
                prim_len = l1sched_bad_frame_ind(prim_buffer, lchan);
        } else if (L1SCHED_CHAN_IS_TCH(chan) && 
L1SCHED_TCH_MODE_IS_DATA(tch_mode)) {
                /* FIXME: should we do anything for CSD? */
-               return;
+               return NULL;
        } else {
                /* Copy LAPDm fill frame's header */
                memcpy(prim_buffer, lapdm_fill_frame, sizeof(lapdm_fill_frame));
@@ -466,7 +323,7 @@

        /* Nothing to allocate / assign */
        if (!prim_len)
-               return;
+               return NULL;

        msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST);
        OSMO_ASSERT(msg != NULL);
@@ -479,10 +336,7 @@

        memcpy(msgb_put(msg, prim_len), &prim_buffer[0], prim_len);

-       /* Assign the current prim */
-       lchan->prim = msg;
-
-       LOGP_LCHAND(lchan, LOGL_DEBUG, "Transmitting a dummy / silence 
frame\n");
+       return msg;
 }

 int l1sched_lchan_emit_data_ind(struct l1sched_lchan_state *lchan,
diff --git a/src/host/trxcon/src/sched_trx.c b/src/host/trxcon/src/sched_trx.c
index 3b452b1..cac3a21 100644
--- a/src/host/trxcon/src/sched_trx.c
+++ b/src/host/trxcon/src/sched_trx.c
@@ -121,27 +121,10 @@
        if (lchan == NULL || !lchan->active)
                return;

-       /* If no primitive is being processed, try obtaining one from Tx queue 
*/
-       if (lchan->prim == NULL) {
-               /* Align to the first burst of a block */
-               if (frame->ul_bid != 0)
-                       return;
-               lchan->prim = l1sched_lchan_prim_dequeue(lchan, br->fn);
-               if (lchan->prim == NULL) {
-                       /* If CBTX (Continuous Burst Transmission) is required 
*/
-                       if (l1sched_lchan_desc[chan].flags & 
L1SCHED_CH_FLAG_CBTX)
-                               l1sched_lchan_prim_assign_dummy(lchan);
-                       if (lchan->prim == NULL)
-                               return;
-               }
-       }
-
-       /* TODO: report TX buffers health to the higher layers */
-
        /* Handover RACH needs to be handled regardless of the
         * current channel type and the associated handler. */
-       if (l1sched_prim_type_from_msgb(lchan->prim) == L1SCHED_PRIM_T_RACH &&
-           lchan->type != L1SCHED_RACH)
+       struct msgb *msg = llist_first_entry_or_null(&lchan->tx_prims, struct 
msgb, list);
+       if (msg && l1sched_prim_type_from_msgb(msg) == L1SCHED_PRIM_T_RACH)
                handler = l1sched_lchan_desc[L1SCHED_RACH].tx_fn;

        /* Poke lchan handler */

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

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I3d6c2136ff1855ab0aa9062b20b2a64fd0e5fe28
Gerrit-Change-Number: 33708
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to