fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmocom-bb/+/32504 )


Change subject: [WIP] l1gprs: implement queueing of Uplink blocks
......................................................................

[WIP] l1gprs: implement queueing of Uplink blocks

Change-Id: If9638a670f97f602c922ea8d3375674d03c15f53
Related: OS#5500
---
M include/l1ctl_proto.h
M include/l1gprs.h
M src/host/layer23/include/osmocom/bb/common/l1ctl.h
M src/host/layer23/src/common/l1ctl.c
M src/host/layer23/src/modem/rlcmac.c
M src/host/trxcon/src/l1ctl.c
M src/host/trxcon/src/trxcon_fsm.c
M src/host/virt_phy/src/virt_prim_pdch.c
M src/shared/l1gprs.c
9 files changed, 187 insertions(+), 100 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/04/32504/1

diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h
index 3512424..b1f59f9 100644
--- a/include/l1ctl_proto.h
+++ b/include/l1ctl_proto.h
@@ -345,19 +345,15 @@
        uint8_t data[0];
 } __attribute__((packed));

-/* payload of L1CTL_GPRS_UL_TBF_CFG_REQ */
-struct l1ctl_gprs_ul_tbf_cfg_req {
+/* payload of L1CTL_GPRS_{UL,DL}_TBF_CFG_REQ */
+struct l1ctl_gprs_tbf_cfg_req {
        uint8_t tbf_ref;
        uint8_t slotmask;
        uint8_t padding[2];
-} __attribute__((packed));
-
-/* payload of L1CTL_GPRS_DL_TBF_CFG_REQ */
-struct l1ctl_gprs_dl_tbf_cfg_req {
-       uint8_t tbf_ref;
-       uint8_t slotmask;
-       uint8_t dl_tfi;
-       uint8_t padding[1];
+       union {
+               uint8_t ul_usf[8];
+               uint8_t dl_tfi;
+       } __attribute__((packed));
 } __attribute__((packed));

 /* part of L1CTL_GPRS_{UL,DL}_BLOCK_{REQ,IND} */
@@ -370,6 +366,7 @@
 /* payload of L1CTL_GPRS_UL_BLOCK_REQ */
 struct l1ctl_gprs_ul_block_req {
        struct l1ctl_gprs_block_hdr hdr;
+       uint8_t tbf_ref;
        uint8_t data[0];
 } __attribute__((packed));

diff --git a/include/l1gprs.h b/include/l1gprs.h
index bbd654d..f7f49c2 100644
--- a/include/l1gprs.h
+++ b/include/l1gprs.h
@@ -4,6 +4,13 @@
 #include <stdbool.h>

 #include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm0502.h>
+
+/* Calculate TDMA Fn of the next block from TDMA Fn of the current block.
+ * Every fn % 13 == 12 we have either a PTCCH or an IDLE slot, thus
+ * every fn % 13 ==  8 we add 5 frames, or 4 frames othrwise. */
+#define L1GPRS_NEXT_BLOCK_FN(fn) \
+       GSM_TDMA_FN_SUM(fn, (fn % 13 == 8) ? 5 : 4)

 struct l1gprs_state;
 struct msgb;
@@ -17,8 +24,13 @@
        uint8_t tbf_ref;
        /*! PDCH timeslots used by this TBF */
        uint8_t slotmask;
-       /*! (Downlink only) DL TFI (Temporary Flow Indentity): 0..31 */
-       uint8_t dl_tfi;
+       /*! UL/DL specific parameters */
+       union {
+               /*! USF for each PDCH indicated in the slotmask */
+               uint8_t ul_usf[8];
+               /*! DL TFI for all PDCHs indicated in the slotmask */
+               uint8_t dl_tfi;
+       };
 };

 struct l1gprs_pdch {
@@ -32,6 +44,12 @@
        uint8_t dl_tbf_count;
        /*! DL TFI mask */
        uint32_t dl_tfi_mask;
+       /*! last USF received on this PDCH */
+       uint8_t last_usf;
+       /*! Tx block queue: blocks sent whenever USF matches */
+       struct llist_head tx_queue_usf;
+       /*! Tx block queue: blocks with TDMA Fn, sorted */
+       struct llist_head tx_queue_abs;
 };

 struct l1gprs_state {
@@ -74,8 +92,7 @@
        const uint8_t *data;
 };

-int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs,
-                              struct l1gprs_prim_ul_block_req *req,
-                              const struct msgb *msg);
+int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs, struct msgb *msg);
 struct msgb *l1gprs_handle_dl_block_ind(struct l1gprs_state *gprs,
                                        const struct l1gprs_prim_dl_block_ind 
*ind);
+struct msgb *l1gprs_pull_ul_block(struct l1gprs_state *gprs, uint32_t fn, 
uint8_t tn);
diff --git a/src/host/layer23/include/osmocom/bb/common/l1ctl.h 
b/src/host/layer23/include/osmocom/bb/common/l1ctl.h
index 25bc6e8..2ad19e7 100644
--- a/src/host/layer23/include/osmocom/bb/common/l1ctl.h
+++ b/src/host/layer23/include/osmocom/bb/common/l1ctl.h
@@ -81,7 +81,7 @@

 /* Transmit L1CTL_GPRS_UL_TBF_CFG_REQ */
 int l1ctl_tx_gprs_ul_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref,
-                                uint8_t slotmask);
+                                uint8_t slotmask, const uint8_t usf[8]);

 /* Transmit L1CTL_GPRS_DL_TBF_CFG_REQ */
 int l1ctl_tx_gprs_dl_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref,
diff --git a/src/host/layer23/src/common/l1ctl.c 
b/src/host/layer23/src/common/l1ctl.c
index 8e55b7b..affb80d 100644
--- a/src/host/layer23/src/common/l1ctl.c
+++ b/src/host/layer23/src/common/l1ctl.c
@@ -1009,34 +1009,11 @@
        return 0;
 }

-/* Transmit L1CTL_GPRS_UL_BLOCK_REQ */
-int l1ctl_tx_gprs_ul_block_req(struct osmocom_ms *ms, uint32_t fn, uint8_t tn,
-                              const uint8_t *data, size_t data_len)
-{
-       struct l1ctl_gprs_ul_block_req *req;
-       struct msgb *msg;
-
-       msg = osmo_l1_alloc(L1CTL_GPRS_UL_BLOCK_REQ);
-       if (!msg)
-               return -ENOMEM;
-
-       req = (void *)msgb_put(msg, sizeof(*req));
-       req->hdr.fn = htonl(fn);
-       req->hdr.tn = tn;
-       if (data_len > 0)
-               memcpy(msgb_put(msg, data_len), data, data_len);
-
-       DEBUGP(DL1C, "Tx GPRS UL block (fn=%u, tn=%u, len=%zu): %s\n",
-              fn, tn, data_len, osmo_hexdump(data, data_len));
-
-       return osmo_send_l1(ms, msg);
-}
-
 /* Transmit L1CTL_GPRS_UL_TBF_CFG_REQ */
 int l1ctl_tx_gprs_ul_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref,
-                                uint8_t slotmask)
+                                uint8_t slotmask, const uint8_t usf[8])
 {
-       struct l1ctl_gprs_ul_tbf_cfg_req *req;
+       struct l1ctl_gprs_tbf_cfg_req *req;
        struct msgb *msg;

        msg = osmo_l1_alloc(L1CTL_GPRS_UL_TBF_CFG_REQ);
@@ -1044,13 +1021,12 @@
                return -ENOMEM;

        req = (void *)msgb_put(msg, sizeof(*req));
-       *req = (struct l1ctl_gprs_ul_tbf_cfg_req) {
-               .tbf_ref = tbf_ref,
-               .slotmask = slotmask,
-       };
+       req->tbf_ref = tbf_ref;
+       req->slotmask = slotmask;
+       memcpy(&req->ul_usf[0], &usf[0], sizeof(req->ul_usf));

-       DEBUGP(DL1C, "Tx GPRS UL TBF CFG (tbf_ref=%u, slotmask=0x%02x)\n",
-              tbf_ref, slotmask);
+       DEBUGP(DL1C, "Tx GPRS UL TBF CFG (tbf_ref=%u, slotmask=0x%02x): %s\n",
+              tbf_ref, slotmask, osmo_hexdump(&req->ul_usf[0], 
sizeof(req->ul_usf)));

        return osmo_send_l1(ms, msg);
 }
@@ -1059,7 +1035,7 @@
 int l1ctl_tx_gprs_dl_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref,
                                 uint8_t slotmask, uint8_t dl_tfi)
 {
-       struct l1ctl_gprs_dl_tbf_cfg_req *req;
+       struct l1ctl_gprs_tbf_cfg_req *req;
        struct msgb *msg;

        msg = osmo_l1_alloc(L1CTL_GPRS_DL_TBF_CFG_REQ);
@@ -1067,11 +1043,9 @@
                return -ENOMEM;

        req = (void *)msgb_put(msg, sizeof(*req));
-       *req = (struct l1ctl_gprs_dl_tbf_cfg_req) {
-               .tbf_ref = tbf_ref,
-               .slotmask = slotmask,
-               .dl_tfi = dl_tfi,
-       };
+       req->tbf_ref = tbf_ref;
+       req->slotmask = slotmask;
+       req->dl_tfi = dl_tfi;

        DEBUGP(DL1C, "Tx GPRS DL TBF CFG (tbf_ref=%u, slotmask=0x%02x, 
dl_tfi=%u)\n",
               tbf_ref, slotmask, dl_tfi);
diff --git a/src/host/layer23/src/modem/rlcmac.c 
b/src/host/layer23/src/modem/rlcmac.c
index deb366a..68d3c43 100644
--- a/src/host/layer23/src/modem/rlcmac.c
+++ b/src/host/layer23/src/modem/rlcmac.c
@@ -143,6 +143,7 @@
                return modem_grr_tx_chan_req(ms, lp->rach_req.ra);
        case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_REQUEST):
                return l1ctl_tx_gprs_ul_block_req(ms,
+                                                 0, /* XXX: 
lp->pdch_data_req.tbf_ref, */
                                                  lp->pdch_data_req.fn,
                                                  lp->pdch_data_req.ts_nr,
                                                  lp->pdch_data_req.data,
@@ -150,7 +151,8 @@
        case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, PRIM_OP_REQUEST):
                return l1ctl_tx_gprs_ul_tbf_cfg_req(ms,
                                                    
lp->cfg_ul_tbf_req.ul_tbf_nr,
-                                                   
lp->cfg_ul_tbf_req.ul_slotmask);
+                                                   
lp->cfg_ul_tbf_req.ul_slotmask,
+                                                   lp->cfg_ul_tbf_req.ul_usf);
        case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, PRIM_OP_REQUEST):
                return l1ctl_tx_gprs_dl_tbf_cfg_req(ms,
                                                    
lp->cfg_dl_tbf_req.dl_tbf_nr,
diff --git a/src/host/trxcon/src/l1ctl.c b/src/host/trxcon/src/l1ctl.c
index a45bc2c..5ddb5b2 100644
--- a/src/host/trxcon/src/l1ctl.c
+++ b/src/host/trxcon/src/l1ctl.c
@@ -828,8 +828,10 @@
                msgb_free(msg);
                return rc;
        case L1CTL_GPRS_UL_BLOCK_REQ:
+               /* pass ownership of the msgb to trxcon_fsm/l1gprs */
                rc = osmo_fsm_inst_dispatch(trxcon->fi, 
TRXCON_EV_GPRS_UL_BLOCK_REQ, msg);
-               msgb_free(msg);
+               if (rc != 0)
+                       msgb_free(msg);
                return rc;
        /* Not (yet) handled messages */
        case L1CTL_NEIGH_PM_REQ:
diff --git a/src/host/trxcon/src/trxcon_fsm.c b/src/host/trxcon/src/trxcon_fsm.c
index 219f0c0..83f971a 100644
--- a/src/host/trxcon/src/trxcon_fsm.c
+++ b/src/host/trxcon/src/trxcon_fsm.c
@@ -29,7 +29,6 @@
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/logging.h>
 #include <osmocom/gsm/gsm0502.h>
-#include <osmocom/gsm/protocol/gsm_08_58.h>

 #include <osmocom/bb/trxcon/trxcon.h>
 #include <osmocom/bb/trxcon/trxcon_fsm.h>
@@ -556,31 +555,17 @@
                break;
        case TRXCON_EV_GPRS_UL_BLOCK_REQ:
        {
-               struct l1gprs_prim_ul_block_req block_req;
-               struct l1sched_prim *prim;
                struct msgb *msg = data;

-               if (l1gprs_handle_ul_block_req(trxcon->gprs, &block_req, msg) 
!= 0)
-                       return;
-
-               msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST, 
block_req.data_len);
-               OSMO_ASSERT(msg != NULL);
-
-               prim = l1sched_prim_from_msgb(msg);
-               prim->data_req = (struct l1sched_prim_chdr) {
-                       .frame_nr = block_req.hdr.fn,
-                       .chan_nr = RSL_CHAN_OSMO_PDCH | block_req.hdr.tn,
-                       .link_id = 0x00,
-               };
-
-               memcpy(msgb_put(msg, block_req.data_len), block_req.data, 
block_req.data_len);
-               l1sched_prim_from_user(trxcon->sched, msg);
+               if (l1gprs_handle_ul_block_req(trxcon->gprs, msg) != 0)
+                       msgb_free(msg);
                break;
        }
        case TRXCON_EV_RX_DATA_IND:
        {
                const struct trxcon_param_rx_data_ind *ind = data;
                struct l1gprs_prim_dl_block_ind block_ind;
+               struct l1sched_prim *prim;
                struct msgb *msg;

                block_ind = (struct l1gprs_prim_dl_block_ind) {
@@ -602,9 +587,27 @@
                else
                        block_ind.meas.ber10k = 10000 * ind->n_errors / 
ind->n_bits_total;

+               /* feed l1gprs with the received data */
                msg = l1gprs_handle_dl_block_ind(trxcon->gprs, &block_ind);
-               if (msg != NULL)
+               if (msg != NULL) /* pass ownership of msgb to l1ctl */
                        trxcon_l1ctl_send(trxcon, msg);
+
+               /* pull an Uplink block from l1gprs */
+               const uint32_t next_block_fn = 
L1GPRS_NEXT_BLOCK_FN(ind->frame_nr);
+               msg = l1gprs_pull_ul_block(trxcon->gprs, next_block_fn, 
ind->chan_nr & 0x07);
+               if (msg == NULL)
+                       return;
+
+               /* push a l1sched_prim header in front */
+               l1sched_prim_init(msg, L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST);
+               prim = l1sched_prim_from_msgb(msg);
+               prim->data_req = (struct l1sched_prim_chdr) {
+                       .frame_nr = next_block_fn,
+                       .chan_nr = ind->chan_nr,
+               };
+
+               /* enqueue an Uplink block for transmission */
+               l1sched_prim_from_user(trxcon->sched, msg);
                break;
        }
        case TRXCON_EV_DCH_EST_REQ:
diff --git a/src/host/virt_phy/src/virt_prim_pdch.c 
b/src/host/virt_phy/src/virt_prim_pdch.c
index 65551d3..23bd1e6 100644
--- a/src/host/virt_phy/src/virt_prim_pdch.c
+++ b/src/host/virt_phy/src/virt_prim_pdch.c
@@ -51,7 +51,6 @@
 void l1ctl_rx_gprs_ul_block_req(struct l1_model_ms *ms, struct msgb *msg)
 {
        const struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
-       struct l1gprs_prim_ul_block_req req;

        if (OSMO_UNLIKELY(ms->gprs == NULL)) {
                LOGPMS(DL1P, LOGL_ERROR, ms, "l1gprs is not initialized\n");
@@ -60,14 +59,10 @@
        }

        msg->l1h = (void *)l1h->data;
-       if (l1gprs_handle_ul_block_req(ms->gprs, &req, msg) != 0) {
+       if (l1gprs_handle_ul_block_req(ms->gprs, msg) != 0) {
                msgb_free(msg);
                return;
        }
-       msg->l2h = (void *)&req.data[0];
-
-       virt_l1_sched_schedule(ms, msg, req.hdr.fn, req.hdr.tn,
-                              &gsmtapl1_tx_to_virt_um_inst);
 }

 void l1ctl_tx_gprs_dl_block_ind(struct l1_model_ms *ms, const struct msgb *msg,
@@ -93,7 +88,14 @@
                .data_len = msgb_length(msg),
        };

+       /* feed l1gprs with the received data */
        nmsg = l1gprs_handle_dl_block_ind(ms->gprs, &ind);
-       if (nmsg != NULL)
+       if (nmsg != NULL) /* pass ownership of msgb to l1ctl */
                l1ctl_sap_tx_to_l23_inst(ms, nmsg);
+
+       /* pull an Uplink block from l1gprs */
+       nmsg = l1gprs_pull_ul_block(ms->gprs, L1GPRS_NEXT_BLOCK_FN(fn), tn);
+       if (nmsg == NULL) /* schedule for transmission (pass ownership of msgb) 
*/
+               virt_l1_sched_schedule(ms, nmsg, next_block_fn, tn,
+                                      &gsmtapl1_tx_to_virt_um_inst);
 }
diff --git a/src/shared/l1gprs.c b/src/shared/l1gprs.c
index 5874b48..769c9c0 100644
--- a/src/shared/l1gprs.c
+++ b/src/shared/l1gprs.c
@@ -35,6 +35,9 @@
 #include <osmocom/bb/l1ctl_proto.h>
 #include <osmocom/bb/l1gprs.h>

+#define FN_INVALID             0xffffffff
+#define USF_INVALID            0xff
+
 #define LOGP_GPRS(gprs, level, fmt, args...) \
        LOGP(l1gprs_log_cat, level, "%s" fmt, \
             (gprs)->log_prefix, ## args)
@@ -239,6 +242,9 @@

                pdch->tn = tn;
                pdch->gprs = gprs;
+               pdch->last_usf = USF_INVALID;
+               INIT_LLIST_HEAD(&pdch->tx_queue_usf);
+               INIT_LLIST_HEAD(&pdch->tx_queue_abs);
        }

        INIT_LLIST_HEAD(&gprs->tbf_list);
@@ -257,6 +263,23 @@
        if (gprs == NULL)
                return;

+       for (unsigned int tn = 0; tn < ARRAY_SIZE(gprs->pdch); tn++) {
+               struct l1gprs_pdch *pdch = &gprs->pdch[tn];
+               struct msgb *msg;
+
+               while (!llist_empty(&pdch->tx_queue_usf)) {
+                       msg = llist_first_entry(&pdch->tx_queue_usf, struct 
msgb, list);
+                       llist_del(&msg->list);
+                       msgb_free(msg);
+               }
+
+               while (!llist_empty(&pdch->tx_queue_abs)) {
+                       msg = llist_first_entry(&pdch->tx_queue_abs, struct 
msgb, list);
+                       llist_del(&msg->list);
+                       msgb_free(msg);
+               }
+       }
+
        while (!llist_empty(&gprs->tbf_list)) {
                struct l1gprs_tbf *tbf;

@@ -335,13 +358,10 @@
        return 0;
 }

-int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs,
-                              struct l1gprs_prim_ul_block_req *req,
-                              const struct msgb *msg)
+int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs, struct msgb *msg)
 {
-       const struct l1ctl_gprs_ul_block_req *l1br = (void *)msg->l1h;
-       const struct l1gprs_pdch *pdch = NULL;
-       size_t data_len;
+       struct l1ctl_gprs_ul_block_req *l1br = (void *)msg->l1h;
+       struct l1gprs_pdch *pdch;

        OSMO_ASSERT(l1br != NULL);

@@ -358,12 +378,20 @@
                return -EINVAL;
        }

+       msg->l2h = &l1br->data[0];
+       l1br->hdr.fn = ntohl(l1br->hdr.fn);
+
        pdch = &gprs->pdch[l1br->hdr.tn];
-       data_len = msgb_l1len(msg) - sizeof(*l1br);

        LOGP_PDCH(pdch, LOGL_DEBUG,
-                 "Rx UL BLOCK.req (fn=%u, len=%zu): %s\n",
-                 ntohl(l1br->hdr.fn), data_len, osmo_hexdump(l1br->data, 
data_len));
+                 "Rx UL BLOCK.req (tbf_ref=%u, fn=%u, len=%u): %s\n",
+                 l1br->tbf_ref, l1br->hdr.fn, msgb_l2len(msg), 
msgb_hexdump_l2(msg));
+
+       if (OSMO_UNLIKELY(msgb_l2len(msg) == 0)) {
+               LOGP_PDCH(pdch, LOGL_ERROR,
+                         "Rx UL BLOCK.req with empty payload\n");
+               return -EINVAL;
+       }

        if ((pdch->ul_tbf_count == 0) && (pdch->dl_tbf_count == 0)) {
                LOGP_PDCH(pdch, LOGL_ERROR,
@@ -371,14 +399,10 @@
                return -EINVAL;
        }

-       *req = (struct l1gprs_prim_ul_block_req) {
-               .hdr = {
-                       .fn = ntohl(l1br->hdr.fn),
-                       .tn = l1br->hdr.tn,
-               },
-               .data = &l1br->data[0],
-               .data_len = data_len,
-       };
+       if (l1br->hdr.fn == FN_INVALID)
+               msgb_enqueue(&pdch->tx_queue_usf, msg);
+       else /* TODO: sorted insertion */
+               msgb_enqueue(&pdch->tx_queue_abs, msg);

        return 0;
 }
@@ -386,8 +410,8 @@
 struct msgb *l1gprs_handle_dl_block_ind(struct l1gprs_state *gprs,
                                        const struct l1gprs_prim_dl_block_ind 
*ind)
 {
-       const struct l1gprs_pdch *pdch = NULL;
        struct l1ctl_gprs_dl_block_ind *l1bi;
+       struct l1gprs_pdch *pdch = NULL;
        enum osmo_gprs_cs cs;
        struct msgb *msg;

@@ -400,6 +424,9 @@

        pdch = &gprs->pdch[ind->hdr.tn];

+       /* reset last seen USF */
+       pdch->last_usf = USF_INVALID;
+
        LOGP_PDCH(pdch, LOGL_DEBUG,
                  "Rx DL BLOCK.ind (fn=%u, len=%zu): %s\n",
                  ind->hdr.fn, ind->data_len, osmo_hexdump(ind->data, 
ind->data_len));
@@ -427,7 +454,7 @@
                        .ci_cb = htons(ind->meas.ci_cb),
                        .rx_lev = ind->meas.rx_lev,
                },
-               .usf = 0xff,
+               .usf = USF_INVALID,
        };

        if (ind->data_len == 0)
@@ -440,6 +467,7 @@
        case OSMO_GPRS_CS3:
        case OSMO_GPRS_CS4:
                l1bi->usf = ind->data[0] & 0x07;
+               pdch->last_usf = l1bi->usf;
                /* Determine whether to include the payload or not */
                if (l1gprs_pdch_filter_dl_block(pdch, ind->data))
                        memcpy(msgb_put(msg, ind->data_len), ind->data, 
ind->data_len);
@@ -455,3 +483,55 @@

        return msg;
 }
+
+struct msgb *l1gprs_pull_ul_block(struct l1gprs_state *gprs, uint32_t fn, 
uint8_t tn)
+{
+       struct l1gprs_pdch *pdch;
+       struct msgb *msg;
+
+       OSMO_ASSERT(tn < ARRAY_SIZE(gprs->pdch));
+       pdch = &gprs->pdch[tn];
+
+       /* check if we have a block scheduled for this TDMA Fn */
+       llist_for_each_entry(msg, &pdch->tx_queue_abs, list) {
+               const struct l1ctl_gprs_ul_block_req *l1br = (void *)msg->l1h;
+
+               if (l1br->hdr.fn != fn)
+                       continue;
+
+               LOGP_PDCH(pdch, LOGL_DEBUG,
+                         "%s(fn=%u): found an UL block with matching TDMA Fn: 
%s\n",
+                         __func__, fn, msgb_hexdump_l2(msg));
+
+               llist_del(&msg->list);
+               msgb_pull_to_l2(msg);
+               return msg;
+       }
+
+       /* USF of the last received DL block must be known */
+       if (pdch->last_usf == USF_INVALID)
+               return NULL;
+
+       /* check if we have a block with matching USF */
+       llist_for_each_entry(msg, &pdch->tx_queue_usf, list) {
+               const struct l1ctl_gprs_ul_block_req *l1br = (void *)msg->l1h;
+               const struct l1gprs_tbf *tbf;
+
+               /* find an Uplink TBF for this block */
+               tbf = l1gprs_find_tbf(gprs, true, l1br->tbf_ref);
+               if (tbf == NULL)
+                       continue;
+               if (tbf->ul_usf != pdch->last_usf)
+                       continue;
+
+               LOGP_PDCH(pdch, LOGL_DEBUG,
+                         "%s(fn=%u): found an UL block with matching USF %u: 
%s\n",
+                         __func__, fn, pdch->last_usf, msgb_hexdump_l2(msg));
+
+               llist_del(&msg->list);
+               msgb_pull_to_l2(msg);
+               return msg;
+       }
+
+       return NULL;
+}

--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/32504
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: If9638a670f97f602c922ea8d3375674d03c15f53
Gerrit-Change-Number: 32504
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>
Gerrit-MessageType: newchange

Reply via email to