This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.org
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 <axilirator at 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 <laforge at gnumonks.org>