summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2017-12-18 04:39:27 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2017-12-18 05:26:57 +0700
commit32c2a1d74c1bb3f1cfa9a56b2e15b93fa321f942 (patch)
tree53a4f56fda4f2471cd9974d679f4f9e00279aea7
parenta403215beab8f92f7bd90fe8f80535bd61841b30 (diff)
trxcon/scheduler: prioritize FACCH correctly
Previously we used to compare two consecutive first primitives, taken from a transmit queue. This approach may cause some delay, which is critical for FACCH e.g. in case of handover. Let's walk through a whole transmit queue to find a pair of both FACCH frames, and only then decide what to do. Change-Id: I925cca77bfaa255dd095bc882c901d41c9bc4633
-rw-r--r--src/host/trxcon/sched_prim.c78
1 files changed, 43 insertions, 35 deletions
diff --git a/src/host/trxcon/sched_prim.c b/src/host/trxcon/sched_prim.c
index 3a46ab64..da2ff3be 100644
--- a/src/host/trxcon/sched_prim.c
+++ b/src/host/trxcon/sched_prim.c
@@ -145,43 +145,51 @@ int sched_prim_push(struct trx_instance *trx,
*/
static struct trx_ts_prim *sched_prim_dequeue_tch(struct llist_head *queue)
{
- struct trx_ts_prim *a, *b;
-
- /* Dequeue the first prim */
- a = llist_entry(queue->next, struct trx_ts_prim, list);
- llist_del(&a->list);
+ struct trx_ts_prim *facch = NULL;
+ struct trx_ts_prim *tch = NULL;
+ struct trx_ts_prim *i;
+
+ /* Attempt to find a pair of FACCH and TCH frames */
+ llist_for_each_entry(i, queue, list) {
+ /* Find one FACCH frame */
+ if (!facch && PRIM_IS_FACCH(i))
+ facch = i;
+
+ /* Find one TCH frame */
+ if (!tch && PRIM_IS_TCH(i))
+ tch = i;
+
+ /* If both are found */
+ if (facch && tch)
+ break;
+ }
- /* If this was the only one => do nothing... */
- if (llist_empty(queue))
- return a;
-
- /* Obtain the next prim */
- b = llist_entry(queue->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(&b->list);
- talloc_free(a);
- return b;
- } else {
- /**
- * Otherwise: both are TCH or FACCH frames:
- * Nothing to prioritize, return the first one
- */
- return a;
+ /* There should be at least one frame found */
+ OSMO_ASSERT(facch || tch);
+
+ /* Prioritize FACCH */
+ if (facch && tch) {
+ /* We found a pair, dequeue both */
+ llist_del(&facch->list);
+ llist_del(&tch->list);
+
+ /* Drop TCH */
+ talloc_free(tch);
+
+ /* FACCH replaces TCH */
+ return facch;
+ } else if (facch) {
+ /* Only FACCH was found */
+ llist_del(&facch->list);
+ return facch;
+ } else if (tch) {
+ /* Only TCH was found */
+ llist_del(&tch->list);
+ return tch;
}
+
+ /* Unreachable */
+ OSMO_ASSERT(0);
}
/**