diff options
author | Vadim Yanitskiy <axilirator@gmail.com> | 2017-12-18 04:39:27 +0700 |
---|---|---|
committer | Vadim Yanitskiy <axilirator@gmail.com> | 2017-12-18 05:26:57 +0700 |
commit | 32c2a1d74c1bb3f1cfa9a56b2e15b93fa321f942 (patch) | |
tree | 53a4f56fda4f2471cd9974d679f4f9e00279aea7 | |
parent | a403215beab8f92f7bd90fe8f80535bd61841b30 (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.c | 78 |
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); } /** |