diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2023-07-10 02:04:48 +0700 |
---|---|---|
committer | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2023-07-12 03:52:34 +0700 |
commit | 21aacfe7096ef27fe40c22d20a86d2303f9cba91 (patch) | |
tree | ed76fb72d394e2ace84cfecaf0fcc686348e8714 | |
parent | a22acea3a9db44d891080caaed8619114386afff (diff) |
trxcon/l1sched: peoperly prioritize FACCH/H over TCH
Unlike FACCH/F, which steals one TCH frame, FACCH/H steals two TCH
frames. This is what prim_dequeue_tchh() aims to implement, but
the current implementation is not 100% correct.
The problem is that we're attempting to dequeue and drop two TCH frames
in one go, whenever we get a FACCH/H frame. Most likely, there will be
no 2nd TCH frame in the Tx queue at that time, so it will never be
dropped and will clog the queue.
Let's replicate what osmo-bts-trx does:
* dequeue and drop the 1st TCH frame when sending 1st/6 burst of FACCH,
* dequeue and drop the 2nd TCH frame when sending 3rd/6 burst of FACCH.
Change-Id: I513d6805ddf97783c002be285fb3ca7893e42377
Related: OS#4396, OS#1572
-rw-r--r-- | src/host/trxcon/src/sched_lchan_tchh.c | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/src/host/trxcon/src/sched_lchan_tchh.c b/src/host/trxcon/src/sched_lchan_tchh.c index 6affbc5d..67e21320 100644 --- a/src/host/trxcon/src/sched_lchan_tchh.c +++ b/src/host/trxcon/src/sched_lchan_tchh.c @@ -414,36 +414,23 @@ bfi: static struct msgb *prim_dequeue_tchh(struct l1sched_lchan_state *lchan, uint32_t fn) { - struct msgb *facch; - struct msgb *tch; - bool facch_now; - - /* Can we initiate an UL FACCH/H frame transmission at this Fn? */ - facch_now = l1sched_tchh_facch_start(lchan->type, fn, true); - if (!facch_now) - goto no_facch; - - /* If there are no FACCH/H prims in the queue */ - facch = l1sched_lchan_prim_dequeue_tch(lchan, true); - if (!facch) /* Just dequeue a TCH/H prim */ - goto no_facch; - - /* FACCH/H prim replaces two TCH/F prims */ - tch = l1sched_lchan_prim_dequeue_tch(lchan, false); - if (tch) { - /* At least one TCH/H prim is dropped */ - msgb_free(tch); - - /* Attempt to find another */ - tch = l1sched_lchan_prim_dequeue_tch(lchan, false); - if (tch) /* Drop the second TCH/H prim */ - msgb_free(tch); + struct msgb *msg_facch; + struct msgb *msg_tch; + + /* dequeue a pair of TCH and FACCH frames */ + msg_tch = l1sched_lchan_prim_dequeue_tch(lchan, false); + if (l1sched_tchh_facch_start(lchan->type, fn, true)) + msg_facch = l1sched_lchan_prim_dequeue_tch(lchan, true); + else + msg_facch = NULL; + + /* prioritize FACCH over TCH */ + if (msg_facch != NULL) { + msgb_free(msg_tch); /* drop 1st TCH/HS block */ + return msg_facch; } - return facch; - -no_facch: - return l1sched_lchan_prim_dequeue_tch(lchan, false); + return msg_tch; } int tx_tchh_fn(struct l1sched_lchan_state *lchan, @@ -478,8 +465,11 @@ int tx_tchh_fn(struct l1sched_lchan_state *lchan, *mask = *mask << 2; /* If FACCH/H blocks are still pending */ - if (lchan->ul_facch_blocks > 2) + if (lchan->ul_facch_blocks > 2) { + struct msgb *msg = l1sched_lchan_prim_dequeue_tch(lchan, false); + msgb_free(msg); /* drop 2nd TCH/HS block */ goto send_burst; + } lchan->prim = prim_dequeue_tchh(lchan, br->fn); if (lchan->prim == NULL) { |