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.orgReview 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>