summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2023-06-21 19:03:57 +0700
committerPau Espin Pedrol <pespin@sysmocom.de>2023-08-11 19:47:32 +0200
commitfb384998fbddcc545eec76da41db1aa41b583aa9 (patch)
tree04e864b15df7d1aeeac536249b68cf15b56dbc94
parent3ac817108eeb94ead29b0644c872d0a67abf2943 (diff)
trxcon: properly handle PDCH slotmask in UL/DL TBF CFG.Req
-rw-r--r--include/l1gprs.h12
-rw-r--r--src/host/trxcon/src/trxcon_fsm.c25
-rw-r--r--src/shared/l1gprs.c27
3 files changed, 64 insertions, 0 deletions
diff --git a/include/l1gprs.h b/include/l1gprs.h
index bbd654d3..060366e7 100644
--- a/include/l1gprs.h
+++ b/include/l1gprs.h
@@ -2,6 +2,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include <stddef.h>
#include <osmocom/core/linuxlist.h>
@@ -34,6 +35,14 @@ struct l1gprs_pdch {
uint32_t dl_tfi_mask;
};
+static inline size_t l1gprs_pdch_use_count(const struct l1gprs_pdch *pdch)
+{
+ return pdch->ul_tbf_count + pdch->dl_tbf_count;
+}
+
+
+typedef void (*l1gprs_pdch_changed_t)(struct l1gprs_pdch *pdch, bool active);
+
struct l1gprs_state {
/*! PDCH state for each timeslot */
struct l1gprs_pdch pdch[8];
@@ -43,11 +52,14 @@ struct l1gprs_state {
char *log_prefix;
/*! Some private data for API user */
void *priv;
+ /*! Callback triggered to signal lower layers when a PDCH TS has to be activated/deactivated */
+ l1gprs_pdch_changed_t pdch_changed_cb;
};
void l1gprs_logging_init(int logc);
struct l1gprs_state *l1gprs_state_alloc(void *ctx, const char *log_prefix, void *priv);
void l1gprs_state_free(struct l1gprs_state *gprs);
+void l1gprs_state_set_pdch_changed_cb(struct l1gprs_state *gprs, l1gprs_pdch_changed_t pdch_changed_cb);
int l1gprs_handle_ul_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg);
int l1gprs_handle_dl_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg);
diff --git a/src/host/trxcon/src/trxcon_fsm.c b/src/host/trxcon/src/trxcon_fsm.c
index eabab3d2..e7c60f26 100644
--- a/src/host/trxcon/src/trxcon_fsm.c
+++ b/src/host/trxcon/src/trxcon_fsm.c
@@ -517,6 +517,30 @@ static void trxcon_st_dedicated_action(struct osmo_fsm_inst *fi,
}
}
+static void handle_tbf_cfg_req(struct trxcon_inst *trxcon, uint8_t tn, bool active)
+{
+ struct l1sched_state *sched = trxcon->sched;
+
+ if (active) {
+ if (sched->ts[tn] != NULL) /* already enabled */
+ return;
+ if (l1sched_configure_ts(sched, tn, GSM_PCHAN_PDCH) != 0)
+ return;
+ OSMO_ASSERT(sched->ts[tn] != NULL);
+
+ l1sched_activate_lchan(sched->ts[tn], L1SCHED_PDTCH);
+ l1sched_activate_lchan(sched->ts[tn], L1SCHED_PTCCH);
+ /* FIXME: set TSC for both lchans */
+ } else {
+ l1sched_del_ts(sched, tn);
+ }
+}
+
+static void trxcon_l1gprs_state_changed_cb(struct l1gprs_pdch *pdch, bool active)
+{
+ handle_tbf_cfg_req(pdch->gprs->priv, pdch->tn, active);
+}
+
static void trxcon_st_packet_data_onenter(struct osmo_fsm_inst *fi,
uint32_t prev_state)
{
@@ -524,6 +548,7 @@ static void trxcon_st_packet_data_onenter(struct osmo_fsm_inst *fi,
OSMO_ASSERT(trxcon->gprs == NULL);
trxcon->gprs = l1gprs_state_alloc(trxcon, trxcon->log_prefix, trxcon);
+ l1gprs_state_set_pdch_changed_cb(trxcon->gprs, trxcon_l1gprs_state_changed_cb);
OSMO_ASSERT(trxcon->gprs != NULL);
}
diff --git a/src/shared/l1gprs.c b/src/shared/l1gprs.c
index 1c3dba89..bae13d2c 100644
--- a/src/shared/l1gprs.c
+++ b/src/shared/l1gprs.c
@@ -118,6 +118,12 @@ static void l1gprs_register_tbf(struct l1gprs_state *gprs,
LOGP_PDCH(pdch, LOGL_DEBUG,
"Linked " LOG_TBF_FMT "\n",
LOG_TBF_ARGS(tbf));
+
+ /* If just got first use: */
+ if (l1gprs_pdch_use_count(pdch) == 1) {
+ if (gprs->pdch_changed_cb)
+ gprs->pdch_changed_cb(pdch, true);
+ }
}
llist_add_tail(&tbf->list, &gprs->tbf_list);
@@ -154,6 +160,11 @@ static void l1gprs_update_tbf(struct l1gprs_state *gprs, struct l1gprs_tbf *tbf,
}
LOGP_PDCH(pdch, LOGL_DEBUG, "Unlinked " LOG_TBF_FMT "\n",
LOG_TBF_ARGS(tbf));
+ /* If not more in use: */
+ if (l1gprs_pdch_use_count(pdch) == 0) {
+ if (gprs->pdch_changed_cb)
+ gprs->pdch_changed_cb(pdch, false);
+ }
} else {
/* Slot was not set, add it */
if (tbf->uplink) {
@@ -164,6 +175,11 @@ static void l1gprs_update_tbf(struct l1gprs_state *gprs, struct l1gprs_tbf *tbf,
}
LOGP_PDCH(pdch, LOGL_DEBUG, "Linked " LOG_TBF_FMT "\n",
LOG_TBF_ARGS(tbf));
+ /* If just got first use: */
+ if (l1gprs_pdch_use_count(pdch) == 1) {
+ if (gprs->pdch_changed_cb)
+ gprs->pdch_changed_cb(pdch, true);
+ }
}
}
@@ -197,6 +213,12 @@ static void l1gprs_unregister_tbf(struct l1gprs_state *gprs, struct l1gprs_tbf *
LOGP_PDCH(pdch, LOGL_DEBUG,
"Unlinked " LOG_TBF_FMT "\n",
LOG_TBF_ARGS(tbf));
+
+ /* If not more in use: */
+ if (l1gprs_pdch_use_count(pdch) == 0) {
+ if (gprs->pdch_changed_cb)
+ gprs->pdch_changed_cb(pdch, false);
+ }
}
LOGP_GPRS(gprs, LOGL_INFO,
@@ -309,6 +331,11 @@ void l1gprs_state_free(struct l1gprs_state *gprs)
talloc_free(gprs);
}
+void l1gprs_state_set_pdch_changed_cb(struct l1gprs_state *gprs, l1gprs_pdch_changed_t pdch_changed_cb)
+{
+ gprs->pdch_changed_cb = pdch_changed_cb;
+}
+
int l1gprs_handle_ul_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg)
{
const struct l1ctl_gprs_ul_tbf_cfg_req *req = (void *)msg->l1h;