Review at  https://gerrit.osmocom.org/6807

trxcon/scheduler: separate primitive management code

It's good to write, keep and make the source code as much modular
as possible. So, Tte primitive management code was separated to
the 'sched_prim.c' and going to be extended in the near future.

Change-Id: Ifec8c9e4f2c95c72b00772688bcb5dc9c11d6de7
---
M src/host/trxcon/Makefile.am
M src/host/trxcon/l1ctl.c
M src/host/trxcon/sched_lchan_common.c
M src/host/trxcon/sched_lchan_tchf.c
A src/host/trxcon/sched_prim.c
M src/host/trxcon/sched_trx.c
M src/host/trxcon/sched_trx.h
7 files changed, 214 insertions(+), 141 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/07/6807/1

diff --git a/src/host/trxcon/Makefile.am b/src/host/trxcon/Makefile.am
index 88ff2be..c9cc170 100644
--- a/src/host/trxcon/Makefile.am
+++ b/src/host/trxcon/Makefile.am
@@ -39,6 +39,7 @@
        sched_lchan_sch.c \
        sched_mframe.c \
        sched_clck.c \
+       sched_prim.c \
        sched_trx.c \
        $(NULL)
 
diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c
index b72f5ea..a11e792 100644
--- a/src/host/trxcon/l1ctl.c
+++ b/src/host/trxcon/l1ctl.c
@@ -495,8 +495,7 @@
                "(offset=%u ra=0x%02x)\n", req->offset, req->ra);
 
        /* Init a new primitive */
-       rc = sched_trx_init_prim(l1l->trx, &prim, len,
-               chan_nr, link_id);
+       rc = sched_prim_init(l1l->trx, &prim, len, chan_nr, link_id);
        if (rc)
                goto exit;
 
@@ -506,7 +505,7 @@
         * FIXME: what if requested TS is not configured?
         * Or what if one (such as TCH) has no TRXC_RACH slots?
         */
-       rc = sched_trx_push_prim(l1l->trx, prim, chan_nr);
+       rc = sched_prim_push(l1l->trx, prim, chan_nr);
        if (rc) {
                talloc_free(prim);
                goto exit;
@@ -619,13 +618,13 @@
                "link_id=0x%02x)\n", chan_nr, link_id);
 
        /* Init a new primitive */
-       rc = sched_trx_init_prim(l1l->trx, &prim, 23,
+       rc = sched_prim_init(l1l->trx, &prim, 23,
                chan_nr, link_id);
        if (rc)
                goto exit;
 
        /* Push this primitive to transmit queue */
-       rc = sched_trx_push_prim(l1l->trx, prim, chan_nr);
+       rc = sched_prim_push(l1l->trx, prim, chan_nr);
        if (rc) {
                talloc_free(prim);
                goto exit;
@@ -657,13 +656,13 @@
                "link_id=0x%02x)\n", chan_nr, link_id);
 
        /* Init a new primitive */
-       rc = sched_trx_init_prim(l1l->trx, &prim, TRAFFIC_DATA_LEN,
+       rc = sched_prim_init(l1l->trx, &prim, TRAFFIC_DATA_LEN,
                chan_nr, link_id);
        if (rc)
                goto exit;
 
        /* Push this primitive to transmit queue */
-       rc = sched_trx_push_prim(l1l->trx, prim, chan_nr);
+       rc = sched_prim_push(l1l->trx, prim, chan_nr);
        if (rc) {
                talloc_free(prim);
                goto exit;
diff --git a/src/host/trxcon/sched_lchan_common.c 
b/src/host/trxcon/sched_lchan_common.c
index bf47541..9eccc3e 100644
--- a/src/host/trxcon/sched_lchan_common.c
+++ b/src/host/trxcon/sched_lchan_common.c
@@ -185,52 +185,3 @@
                return 0;
        }
 }
-
-#define CHAN_IS_TCH(chan) \
-       (chan == TRXC_TCHF || chan == TRXC_TCHH_0 || chan == TRXC_TCHH_1)
-
-#define PRIM_IS_TCH(prim) \
-       CHAN_IS_TCH(prim->chan) && prim->payload_len != GSM_MACBLOCK_LEN
-
-#define PRIM_IS_FACCH(prim) \
-       CHAN_IS_TCH(prim->chan) && prim->payload_len == GSM_MACBLOCK_LEN
-
-struct trx_ts_prim *sched_dequeue_tch_prim(struct llist_head *queue)
-{
-       struct trx_ts_prim *a, *b;
-
-       /* Obtain the first prim from TX queue */
-       a = llist_entry(queue->next, struct trx_ts_prim, list);
-
-       /* If this is the only one => do nothing... */
-       if (queue->next->next == queue)
-               return a;
-
-       /* Obtain the second prim from TX queue */
-       b = llist_entry(queue->next->next, struct trx_ts_prim, list);
-
-       /* Find and prioritize FACCH  */
-       if (PRIM_IS_FACCH(a) && PRIM_IS_TCH(b)) {
-               /**
-                * Case 1: first is FACCH, second is TCH:
-                * Prioritize FACCH, dropping TCH
-                */
-               llist_del(&b->list);
-               talloc_free(b);
-               return a;
-       } else if (PRIM_IS_TCH(a) && PRIM_IS_FACCH(b)) {
-               /**
-                * Case 2: first is TCH, second is FACCH:
-                * Prioritize FACCH, dropping TCH
-                */
-               llist_del(&a->list);
-               talloc_free(a);
-               return b;
-       } else {
-               /**
-                * Otherwise: both are TCH or FACCH frames:
-                * Nothing to prioritize, return the first one
-                */
-               return a;
-       }
-}
diff --git a/src/host/trxcon/sched_lchan_tchf.c 
b/src/host/trxcon/sched_lchan_tchf.c
index 7860007..da24b23 100644
--- a/src/host/trxcon/sched_lchan_tchf.c
+++ b/src/host/trxcon/sched_lchan_tchf.c
@@ -217,7 +217,7 @@
        }
 
        /* Get a message from TX queue */
-       prim = sched_dequeue_tch_prim(&ts->tx_prims);
+       prim = sched_prim_dequeue_tch(&ts->tx_prims);
        l2 = (uint8_t *) prim->payload;
 
        /* Determine payload length */
diff --git a/src/host/trxcon/sched_prim.c b/src/host/trxcon/sched_prim.c
new file mode 100644
index 0000000..1d1a940
--- /dev/null
+++ b/src/host/trxcon/sched_prim.c
@@ -0,0 +1,199 @@
+/*
+ * OsmocomBB <-> SDR connection bridge
+ * TDMA scheduler: primitive management
+ *
+ * (C) 2017 by Vadim Yanitskiy <axilira...@gmail.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <talloc.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/linuxlist.h>
+
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include "scheduler.h"
+#include "sched_trx.h"
+#include "trx_if.h"
+#include "logging.h"
+
+/**
+ * Initializes a new primitive by allocating memory
+ * and filling some meta-information (e.g. lchan type).
+ *
+ * @param  trx     TRX instance to be used as initial talloc context
+ * @param  prim    external prim pointer (will point to the allocated prim)
+ * @param  pl_len  prim payload length
+ * @param  chan_nr RSL channel description (used to set a proper chan)
+ * @param  link_id RSL link description (used to set a proper chan)
+ * @return         zero in case of success, otherwise a error number
+ */
+int sched_prim_init(struct trx_instance *trx,
+       struct trx_ts_prim **prim, size_t pl_len,
+       uint8_t chan_nr, uint8_t link_id)
+{
+       enum trx_lchan_type lchan_type;
+       struct trx_ts_prim *new_prim;
+       uint8_t len;
+
+       /* Determine lchan type */
+       lchan_type = sched_trx_chan_nr2lchan_type(chan_nr, link_id);
+       if (!lchan_type) {
+               LOGP(DSCH, LOGL_ERROR, "Couldn't determine lchan type "
+                       "for chan_nr=%02x and link_id=%02x\n", chan_nr, 
link_id);
+               return -EINVAL;
+       }
+
+       /* How much memory do we need? */
+       len  = sizeof(struct trx_ts_prim); /* Primitive header */
+       len += pl_len; /* Requested payload size */
+
+       /* Allocate a new primitive */
+       new_prim = talloc_zero_size(trx, len);
+       if (new_prim == NULL) {
+               LOGP(DSCH, LOGL_ERROR, "Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       /* Init primitive header */
+       new_prim->payload_len = pl_len;
+       new_prim->chan = lchan_type;
+
+       /* Set external pointer */
+       *prim = new_prim;
+
+       return 0;
+}
+
+/**
+ * Adds a primitive to the end of transmit queue of a particular
+ * timeslot, whose index is parsed from chan_nr.
+ *
+ * @param  trx     TRX instance
+ * @param  prim    to be enqueued primitive
+ * @param  chan_nr RSL channel description
+ * @return         zero in case of success, otherwise a error number
+ */
+int sched_prim_push(struct trx_instance *trx,
+       struct trx_ts_prim *prim, uint8_t chan_nr)
+{
+       struct trx_ts *ts;
+       uint8_t tn;
+
+       /* Determine TS index */
+       tn = chan_nr & 0x7;
+       if (tn > 7) {
+               LOGP(DSCH, LOGL_ERROR, "Incorrect TS index %u\n", tn);
+               return -EINVAL;
+       }
+
+       /* Check whether required timeslot is allocated and configured */
+       ts = trx->ts_list[tn];
+       if (ts == NULL || ts->mf_layout == NULL) {
+               LOGP(DSCH, LOGL_ERROR, "Timeslot %u isn't configured\n", tn);
+               return -EINVAL;
+       }
+
+       /**
+        * Change talloc context of primitive
+        * from trx to the parent ts
+        */
+       talloc_steal(ts, prim);
+
+       /* Add primitive to TS transmit queue */
+       llist_add_tail(&prim->list, &ts->tx_prims);
+
+       return 0;
+}
+
+#define CHAN_IS_TCH(chan) \
+       (chan == TRXC_TCHF || chan == TRXC_TCHH_0 || chan == TRXC_TCHH_1)
+
+#define PRIM_IS_TCH(prim) \
+       CHAN_IS_TCH(prim->chan) && prim->payload_len != GSM_MACBLOCK_LEN
+
+#define PRIM_IS_FACCH(prim) \
+       CHAN_IS_TCH(prim->chan) && prim->payload_len == GSM_MACBLOCK_LEN
+
+/**
+ * Dequeues a TCH or FACCH frame, prioritizing the second.
+ * In case if a FACCH frame is found, a TCH frame is being
+ * dropped (i.e. replaced).
+ *
+ * @param  queue a transmit queue to take a prim from
+ * @return       a FACCH or TCH primitive
+ */
+struct trx_ts_prim *sched_prim_dequeue_tch(struct llist_head *queue)
+{
+       struct trx_ts_prim *a, *b;
+
+       /* Obtain the first prim from TX queue */
+       a = llist_entry(queue->next, struct trx_ts_prim, list);
+
+       /* If this is the only one => do nothing... */
+       if (queue->next->next == queue)
+               return a;
+
+       /* Obtain the second prim from TX queue */
+       b = llist_entry(queue->next->next, struct trx_ts_prim, list);
+
+       /* Find and prioritize FACCH  */
+       if (PRIM_IS_FACCH(a) && PRIM_IS_TCH(b)) {
+               /**
+                * Case 1: first is FACCH, second is TCH:
+                * Prioritize FACCH, dropping TCH
+                */
+               llist_del(&b->list);
+               talloc_free(b);
+               return a;
+       } else if (PRIM_IS_TCH(a) && PRIM_IS_FACCH(b)) {
+               /**
+                * Case 2: first is TCH, second is FACCH:
+                * Prioritize FACCH, dropping TCH
+                */
+               llist_del(&a->list);
+               talloc_free(a);
+               return b;
+       } else {
+               /**
+                * Otherwise: both are TCH or FACCH frames:
+                * Nothing to prioritize, return the first one
+                */
+               return a;
+       }
+}
+
+/**
+ * Flushes a queue of primitives
+ *
+ * @param list list of prims going to be flushed
+ */
+void sched_prim_flush_queue(struct llist_head *list)
+{
+       struct trx_ts_prim *prim, *prim_next;
+
+       llist_for_each_entry_safe(prim, prim_next, list, list) {
+               llist_del(&prim->list);
+               talloc_free(prim);
+       }
+}
diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c
index 02da241..ec2f448 100644
--- a/src/host/trxcon/sched_trx.c
+++ b/src/host/trxcon/sched_trx.c
@@ -37,16 +37,6 @@
 #include "trx_if.h"
 #include "logging.h"
 
-static void prim_queue_flush(struct llist_head *list)
-{
-       struct trx_ts_prim *prim, *prim_next;
-
-       llist_for_each_entry_safe(prim, prim_next, list, list) {
-               llist_del(&prim->list);
-               talloc_free(prim);
-       }
-}
-
 static void sched_frame_clck_cb(struct trx_sched *sched)
 {
        struct trx_instance *trx = (struct trx_instance *) sched->data;
@@ -202,7 +192,7 @@
        LOGP(DSCH, LOGL_NOTICE, "Delete TDMA timeslot #%u\n", tn);
 
        /* Flush queue primitives for TX */
-       prim_queue_flush(&ts->tx_prims);
+       sched_prim_flush_queue(&ts->tx_prims);
 
        /* Remove ts from list and free memory */
        trx->ts_list[tn] = NULL;
@@ -289,7 +279,7 @@
        ts->mf_layout = NULL;
 
        /* Flush queue primitives for TX */
-       prim_queue_flush(&ts->tx_prims);
+       sched_prim_flush_queue(&ts->tx_prims);
 
        /* Free channel states */
        talloc_free(ts->lchans);
@@ -426,75 +416,6 @@
 
                lchan->active = 0;
        }
-}
-
-int sched_trx_init_prim(struct trx_instance *trx,
-       struct trx_ts_prim **prim, size_t pl_len,
-       uint8_t chan_nr, uint8_t link_id)
-{
-       enum trx_lchan_type lchan_type;
-       struct trx_ts_prim *new_prim;
-       uint8_t len;
-
-       /* Determine lchan type */
-       lchan_type = sched_trx_chan_nr2lchan_type(chan_nr, link_id);
-       if (!lchan_type) {
-               LOGP(DSCH, LOGL_ERROR, "Couldn't determine lchan type "
-                       "for chan_nr=%02x and link_id=%02x\n", chan_nr, 
link_id);
-               return -EINVAL;
-       }
-
-       /* How much memory do we need? */
-       len  = sizeof(struct trx_ts_prim); /* Primitive header */
-       len += pl_len; /* Requested payload size */
-
-       /* Allocate a new primitive */
-       new_prim = talloc_zero_size(trx, len);
-       if (new_prim == NULL) {
-               LOGP(DSCH, LOGL_ERROR, "Failed to allocate memory\n");
-               return -ENOMEM;
-       }
-
-       /* Init primitive header */
-       new_prim->payload_len = pl_len;
-       new_prim->chan = lchan_type;
-
-       /* Set external pointer */
-       *prim = new_prim;
-
-       return 0;
-}
-
-int sched_trx_push_prim(struct trx_instance *trx,
-       struct trx_ts_prim *prim, uint8_t chan_nr)
-{
-       struct trx_ts *ts;
-       uint8_t tn;
-
-       /* Determine TS index */
-       tn = chan_nr & 0x7;
-       if (tn > 7) {
-               LOGP(DSCH, LOGL_ERROR, "Incorrect TS index %u\n", tn);
-               return -EINVAL;
-       }
-
-       /* Check whether required timeslot is allocated and configured */
-       ts = trx->ts_list[tn];
-       if (ts == NULL || ts->mf_layout == NULL) {
-               LOGP(DSCH, LOGL_ERROR, "Timeslot %u isn't configured\n", tn);
-               return -EINVAL;
-       }
-
-       /**
-        * Change talloc context of primitive
-        * from trx to the parent ts
-        */
-       talloc_steal(ts, prim);
-
-       /* Add primitive to TS transmit queue */
-       llist_add_tail(&prim->list, &ts->tx_prims);
-
-       return 0;
 }
 
 enum gsm_phys_chan_config sched_trx_chan_nr2pchan_config(uint8_t chan_nr)
diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h
index f2c091e..f1ad7d3 100644
--- a/src/host/trxcon/sched_trx.h
+++ b/src/host/trxcon/sched_trx.h
@@ -264,11 +264,13 @@
        enum trx_lchan_type chan);
 
 /* Primitive management functions */
-int sched_trx_init_prim(struct trx_instance *trx, struct trx_ts_prim **prim,
+int sched_prim_init(struct trx_instance *trx, struct trx_ts_prim **prim,
        size_t pl_len, uint8_t chan_nr, uint8_t link_id);
-int sched_trx_push_prim(struct trx_instance *trx,
+int sched_prim_push(struct trx_instance *trx,
        struct trx_ts_prim *prim, uint8_t chan_nr);
-struct trx_ts_prim *sched_dequeue_tch_prim(struct llist_head *queue);
+
+struct trx_ts_prim *sched_prim_dequeue_tch(struct llist_head *queue);
+void sched_prim_flush_queue(struct llist_head *list);
 
 int sched_trx_handle_rx_burst(struct trx_instance *trx, uint8_t tn,
        uint32_t burst_fn, sbit_t *bits, uint16_t nbits, int8_t rssi, float 
toa);

-- 
To view, visit https://gerrit.osmocom.org/6807
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifec8c9e4f2c95c72b00772688bcb5dc9c11d6de7
Gerrit-PatchSet: 1
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <lafo...@gnumonks.org>

Reply via email to