diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2023-06-21 19:03:57 +0700 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2023-08-11 19:47:32 +0200 |
commit | fb384998fbddcc545eec76da41db1aa41b583aa9 (patch) | |
tree | 04e864b15df7d1aeeac536249b68cf15b56dbc94 | |
parent | 3ac817108eeb94ead29b0644c872d0a67abf2943 (diff) |
trxcon: properly handle PDCH slotmask in UL/DL TBF CFG.Req
Change-Id: I4c2ff25217fba0b6b4704f023071b86ed9afb55c
Related: OS#5500
-rw-r--r-- | include/l1gprs.h | 12 | ||||
-rw-r--r-- | src/host/trxcon/src/trxcon_fsm.c | 25 | ||||
-rw-r--r-- | src/shared/l1gprs.c | 27 |
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; |