From 462bf0952a5b9e16ff0cf81e793f62e9ca777a27 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 7 May 2021 15:47:57 +0200 Subject: [PATCH] [VAMOS] Re-organize osmo-bts-trx specific structures Together with the 'generic' structures which used to be shared between osmo-bsc and osmo-bts some time ago, we also have the following osmo-bts-trx specific structures (in hierarchical order): - struct l1sched_trx (struct gsm_bts_trx), - struct l1sched_ts (struct gsm_bts_trx_ts), - struct l1sched_chan_state (struct gsm_lchan). These structures are not integrated into the tree of the generic structures, but maintained in a _separate tree_ instead. Until recently, only the 'l1sched_trx' had a pointer to generic 'gsm_bts_trx', so in order to find the corresponding 'gsm_lchan' for 'l1sched_chan_state' one would need to traverse all the way up to 'l1sched_trx' and then tracerse another three backwards. + gsm_network | --+ gsm_bts (0..255) | --+ l1sched_trx --------------------> gsm_bts_trx (0..255) | | --+ l1sched_trx_ts --+ gsm_bts_trx_ts (8) | | --+ l1sched_chan_state --+ gsm_lchan (up to 8) I find this architecture a bit over-complicated, especially given that 'l1sched_trx' is kind of a dummy node containing nothing else than a pointer to 'gsm_bts_trx' and the list of 'l1sched_trx_ts'. In this path I slightly change the architecture as follows: + gsm_network | --+ gsm_bts (0..255) | --+ gsm_bts_trx (0..255) | --+ l1sched_trx_ts <----------------> gsm_bts_trx_ts (8) | | --+ l1sched_chan_state --+ gsm_lchan (up to 8) Note that unfortunately we cannot 1:1 map 'l1sched_chan_state' to 'gsm_lchan' (like we do for 'l1sched_trx_ts' and 'gsm_bts_trx_ts') because there is no direct mapping. The former is a higl-level representation of a logical channel, while the later represents one specific logical channel type like FCCH, SDCCH/0 or SACCH/0. osmo-bts-virtual re-uses the osmo-bts-trx hierarchy, so it's also affected by this change. Change-Id: I7c4379e43a25e9d858d582a99bf6c4b65c9af481 --- include/osmo-bts/gsm_data.h | 3 + include/osmo-bts/phy_link.h | 3 - include/osmo-bts/scheduler.h | 31 +-- include/osmo-bts/scheduler_backend.h | 54 ++--- src/common/scheduler.c | 296 +++++++++++------------ src/osmo-bts-trx/l1_if.c | 62 ++--- src/osmo-bts-trx/l1_if.h | 8 - src/osmo-bts-trx/loops.c | 11 +- src/osmo-bts-trx/loops.h | 5 +- src/osmo-bts-trx/sched_lchan_fcch_sch.c | 10 +- src/osmo-bts-trx/sched_lchan_pdtch.c | 27 +-- src/osmo-bts-trx/sched_lchan_rach.c | 19 +- src/osmo-bts-trx/sched_lchan_tchf.c | 76 +++--- src/osmo-bts-trx/sched_lchan_tchh.c | 45 ++-- src/osmo-bts-trx/sched_lchan_xcch.c | 33 ++- src/osmo-bts-trx/scheduler_trx.c | 33 +-- src/osmo-bts-trx/trx_if.c | 10 +- src/osmo-bts-virtual/bts_model.c | 6 +- src/osmo-bts-virtual/l1_if.c | 37 +-- src/osmo-bts-virtual/l1_if.h | 1 - src/osmo-bts-virtual/scheduler_virtbts.c | 139 ++++++----- 21 files changed, 399 insertions(+), 510 deletions(-) diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index ff0c89cba..be1800751 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -455,6 +455,9 @@ struct gsm_bts_trx_ts { /* Transceiver "cache" for frequency hopping */ const struct gsm_bts_trx *fh_trx_list[64]; + /* Implementation specific structure(s) */ + void *priv; + struct gsm_lchan lchan[TS_MAX_LCHAN]; }; diff --git a/include/osmo-bts/phy_link.h b/include/osmo-bts/phy_link.h index 467ad5299..c4b60f36a 100644 --- a/include/osmo-bts/phy_link.h +++ b/include/osmo-bts/phy_link.h @@ -114,9 +114,6 @@ struct phy_instance { struct trx_l1h *hdl; bool sw_act_reported; } osmotrx; - struct { - struct l1sched_trx sched; - } virt; struct { /* logical transceiver number within one PHY */ uint32_t trx_id; diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index 4b1731a7c..3ea08d9e8 100644 --- a/include/osmo-bts/scheduler.h +++ b/include/osmo-bts/scheduler.h @@ -136,6 +136,8 @@ struct l1sched_chan_state { }; struct l1sched_ts { + struct gsm_bts_trx_ts *ts; /* timeslot we belong to */ + uint8_t mf_index; /* selected multiframe index */ uint8_t mf_period; /* period of multiframe */ const struct trx_sched_frame *mf_frames; /* pointer to frame layout */ @@ -148,25 +150,18 @@ struct l1sched_ts { struct l1sched_chan_state chan_state[_TRX_CHAN_MAX]; }; -struct l1sched_trx { - struct gsm_bts_trx *trx; - struct l1sched_ts ts[TRX_NR_TS]; -}; - -struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn); - /*! \brief Initialize the scheduler data structures */ -int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx); +void trx_sched_init(struct gsm_bts_trx *trx); /*! \brief De-initialize the scheduler data structures */ -void trx_sched_exit(struct l1sched_trx *l1t); +void trx_sched_clean(struct gsm_bts_trx *trx); /*! \brief Handle a PH-DATA.req from L2 down to L1 */ -int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap); +int trx_sched_ph_data_req(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); /*! \brief Handle a PH-TCH.req from L2 down to L1 */ -int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap); +int trx_sched_tch_req(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); /*! \brief PHY informs us of new (current) GSM frame number */ int trx_sched_clock(struct gsm_bts *bts, uint32_t fn); @@ -178,21 +173,19 @@ int trx_sched_clock_started(struct gsm_bts *bts); int trx_sched_clock_stopped(struct gsm_bts *bts); /*! \brief set multiframe scheduler to given physical channel config */ -int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn, - enum gsm_phys_chan_config pchan); +int trx_sched_set_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pchan); /*! \brief set all matching logical channels active/inactive */ -int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id, bool active); +int trx_sched_set_lchan(struct gsm_lchan *lchan, uint8_t chan_nr, uint8_t link_id, bool active); /*! \brief set mode of all matching logical channels to given mode(s) */ -int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode, +int trx_sched_set_mode(struct gsm_bts_trx_ts *ts, uint8_t chan_nr, uint8_t rsl_cmode, uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1, uint8_t codec2, uint8_t codec3, uint8_t initial_codec, uint8_t handover); /*! \brief set ciphering on given logical channels */ -int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink, - int algo, uint8_t *key, int key_len); +int trx_sched_set_cipher(struct gsm_lchan *lchan, uint8_t chan_nr, bool downlink); /* frame structures */ struct trx_sched_frame { @@ -287,8 +280,8 @@ struct trx_dl_burst_req { }; /*! Handle an UL burst received by PHY */ -int trx_sched_route_burst_ind(struct trx_ul_burst_ind *bi, struct l1sched_trx *l1t); -int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi); +int trx_sched_route_burst_ind(const struct gsm_bts_trx *trx, struct trx_ul_burst_ind *bi); +int trx_sched_ul_burst(struct l1sched_ts *l1ts, struct trx_ul_burst_ind *bi); /* Averaging mode for trx_sched_meas_avg() */ enum sched_meas_avg_mode { diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h index 13ca71b4a..2a0dd111b 100644 --- a/include/osmo-bts/scheduler_backend.h +++ b/include/osmo-bts/scheduler_backend.h @@ -1,21 +1,18 @@ #pragma once -#define LOGL1S(subsys, level, l1t, tn, chan, fn, fmt, args ...) \ +#define LOGL1S(subsys, level, l1ts, chan, fn, fmt, args ...) \ LOGP(subsys, level, "%s %s %s: " fmt, \ gsm_fn_as_gsmtime_str(fn), \ - gsm_ts_name(&(l1t)->trx->ts[tn]), \ + gsm_ts_name((l1ts)->ts), \ chan >=0 ? trx_chan_desc[chan].name : "", ## args) /* Logging helper adding context from trx_{ul,dl}_burst_{ind,req} */ -#define LOGL1SB(subsys, level, l1t, b, fmt, args ...) \ - LOGL1S(subsys, level, l1t, (b)->tn, (b)->chan, (b)->fn, fmt, ## args) +#define LOGL1SB(subsys, level, l1ts, b, fmt, args ...) \ + LOGL1S(subsys, level, l1ts, (b)->chan, (b)->fn, fmt, ## args) -typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn, - uint32_t fn, enum trx_chan_type chan); - -typedef int trx_sched_dl_func(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); - -typedef int trx_sched_ul_func(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi); +typedef int trx_sched_rts_func(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); +typedef int trx_sched_dl_func(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +typedef int trx_sched_ul_func(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi); struct trx_chan_desc { /*! \brief Human-readable name */ @@ -42,35 +39,34 @@ extern const ubit_t _sched_tsc[8][26]; extern const ubit_t _sched_egprs_tsc[8][78]; extern const ubit_t _sched_sch_train[64]; -struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, - const struct trx_dl_burst_req *br); +struct msgb *_sched_dequeue_prim(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); -int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, +int _sched_compose_ph_data_ind(struct l1sched_ts *l1ts, uint32_t fn, enum trx_chan_type chan, uint8_t *l2, uint8_t l2_len, float rssi, int16_t ta_offs_256bits, int16_t link_qual_cb, uint16_t ber10k, enum osmo_ph_pres_info_type presence_info); -int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, +int _sched_compose_tch_ind(struct l1sched_ts *l1ts, uint32_t fn, enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len, int16_t ta_offs_256bits, uint16_t ber10k, float rssi, uint8_t is_sub); -int tx_idle_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int tx_fcch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int tx_sch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int tx_data_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int tx_pdtch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int tx_tchf_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); +int tx_idle_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int tx_fcch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int tx_sch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int tx_data_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int tx_pdtch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int tx_tchf_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int tx_tchh_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); -int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi); -int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi); -int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi); -int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi); -int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi); +int rx_rach_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi); +int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi); +int rx_pdtch_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi); +int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi); +int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi); -void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br); -int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn); -void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate); +void _sched_dl_burst(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); +int _sched_rts(const struct l1sched_ts *l1ts, uint32_t fn); +void _sched_act_rach_det(struct gsm_bts_trx *trx, uint8_t tn, uint8_t ss, int activate); diff --git a/src/common/scheduler.c b/src/common/scheduler.c index 87a1f60d5..f5a5b895d 100644 --- a/src/common/scheduler.c +++ b/src/common/scheduler.c @@ -3,6 +3,7 @@ /* (C) 2013 by Andreas Eversberg * (C) 2015 by Alexander Chemeris * (C) 2015 by Harald Welte + * Contributions by sysmocom - s.f.m.c. GmbH * * All Rights Reserved * @@ -46,12 +47,9 @@ extern void *tall_bts_ctx; -static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan); -static int rts_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan); -static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan); +static int rts_data_fn(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); +static int rts_tchf_fn(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); +static int rts_tchh_fn(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); /*! \brief Dummy Burst (TS 05.02 Chapter 5.2.6) */ const ubit_t _sched_dummy_burst[GSM_BURST_LEN] = { @@ -576,20 +574,20 @@ static const struct rate_ctr_group_desc l1sched_ts_ctrg_desc = { * init / exit */ -int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx) +void trx_sched_init(struct gsm_bts_trx *trx) { - uint8_t tn; - unsigned int i; + unsigned int tn, i; - if (!trx) - return -EINVAL; + LOGPTRX(trx, DL1C, LOGL_DEBUG, "Init scheduler structures\n"); - l1t->trx = trx; + for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { + struct l1sched_ts *l1ts; - LOGP(DL1C, LOGL_NOTICE, "Init scheduler for trx=%u\n", l1t->trx->nr); + l1ts = talloc_zero(trx, struct l1sched_ts); + OSMO_ASSERT(l1ts != NULL); - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); + trx->ts[tn].priv = l1ts; + l1ts->ts = &trx->ts[tn]; l1ts->mf_index = 0; l1ts->ctrs = rate_ctr_group_alloc(trx, &l1sched_ts_ctrg_desc, (trx->nr + 1) * 10 + tn); @@ -601,20 +599,18 @@ int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx) chan_state->active = false; } } - - return 0; } -void trx_sched_exit(struct l1sched_trx *l1t) +void trx_sched_clean(struct gsm_bts_trx *trx) { - struct gsm_bts_trx_ts *ts; - uint8_t tn; - int i; + unsigned int tn, i; - LOGP(DL1C, LOGL_NOTICE, "Exit scheduler for trx=%u\n", l1t->trx->nr); + LOGPTRX(trx, DL1C, LOGL_DEBUG, "Clean scheduler structures\n"); + + for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { + struct gsm_bts_trx_ts *ts = &trx->ts[tn]; + struct l1sched_ts *l1ts = ts->priv; - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); msgb_queue_flush(&l1ts->dl_prims); rate_ctr_group_free(l1ts->ctrs); l1ts->ctrs = NULL; @@ -631,19 +627,16 @@ void trx_sched_exit(struct l1sched_trx *l1t) } } /* clear lchan channel states */ - ts = &l1t->trx->ts[tn]; for (i = 0; i < ARRAY_SIZE(ts->lchan); i++) lchan_set_state(&ts->lchan[i], LCHAN_S_NONE); } } -struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, - const struct trx_dl_burst_req *br) +struct msgb *_sched_dequeue_prim(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br) { struct msgb *msg, *msg2; uint32_t prim_fn, l1sap_fn; uint8_t chan_nr, link_id; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); /* get prim of current fn from queue */ llist_for_each_entry_safe(msg, msg2, &l1ts->dl_prims, list) { @@ -660,17 +653,17 @@ struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, l1sap_fn = l1sap->u.tch.fn; break; default: - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Prim has wrong type.\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Prim has wrong type.\n"); goto free_msg; } prim_fn = GSM_TDMA_FN_SUB(l1sap_fn, br->fn); if (prim_fn > 100) { /* l1sap_fn < fn */ - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Prim %u is out of range (%u vs exp %u), or channel %s with " "type %s is already disabled. If this happens in " "conjunction with PCU, increase 'rts-advance' by 5.\n", prim_fn, l1sap_fn, br->fn, - get_lchan_by_chan_nr(l1t->trx, chan_nr)->name, + get_lchan_by_chan_nr(l1ts->ts->trx, chan_nr)->name, trx_chan_desc[br->chan].name); rate_ctr_inc2(l1ts->ctrs, L1SCHED_TS_CTR_DL_LATE); /* unlink and free message */ @@ -684,7 +677,7 @@ struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, /* l1sap_fn == fn */ if ((chan_nr ^ (trx_chan_desc[br->chan].chan_nr | br->tn)) || ((link_id & 0xc0) ^ trx_chan_desc[br->chan].link_id)) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Prim has wrong chan_nr=0x%02x link_id=%02x, " + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Prim has wrong chan_nr=0x%02x link_id=%02x, " "expecting chan_nr=0x%02x link_id=%02x.\n", chan_nr, link_id, trx_chan_desc[br->chan].chan_nr | br->tn, trx_chan_desc[br->chan].link_id); goto free_msg; @@ -706,7 +699,7 @@ free_msg: return NULL; } -int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, +int _sched_compose_ph_data_ind(struct l1sched_ts *l1ts, uint32_t fn, enum trx_chan_type chan, uint8_t *l2, uint8_t l2_len, float rssi, int16_t ta_offs_256bits, int16_t link_qual_cb, @@ -715,8 +708,7 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, { struct msgb *msg; struct osmo_phsap_prim *l1sap; - uint8_t chan_nr = trx_chan_desc[chan].chan_nr | tn; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); + uint8_t chan_nr = trx_chan_desc[chan].chan_nr | l1ts->ts->nr; /* compose primitive */ msg = l1sap_msgb_alloc(l2_len); @@ -739,22 +731,20 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, l1ts->chan_state[chan].lost_frames = 0; /* forward primitive */ - l1sap_up(l1t->trx, l1sap); + l1sap_up(l1ts->ts->trx, l1sap); return 0; } -int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, +int _sched_compose_tch_ind(struct l1sched_ts *l1ts, uint32_t fn, enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len, int16_t ta_offs_256bits, uint16_t ber10k, float rssi, uint8_t is_sub) { struct msgb *msg; struct osmo_phsap_prim *l1sap; - struct gsm_bts_trx *trx = l1t->trx; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - uint8_t chan_nr = trx_chan_desc[chan].chan_nr | tn; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; + uint8_t chan_nr = trx_chan_desc[chan].chan_nr | l1ts->ts->nr; + struct gsm_lchan *lchan = &l1ts->ts->lchan[l1sap_chan2ss(chan_nr)]; /* compose primitive */ msg = l1sap_msgb_alloc(tch_len); @@ -775,11 +765,10 @@ int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, if (l1ts->chan_state[chan].lost_frames) l1ts->chan_state[chan].lost_frames--; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.data.fn, - "%s Rx -> RTP: %s\n", + LOGL1S(DL1P, LOGL_DEBUG, l1ts, chan, l1sap->u.data.fn, "%s Rx -> RTP: %s\n", gsm_lchan_name(lchan), osmo_hexdump(msgb_l2(msg), msgb_l2len(msg))); /* forward primitive */ - l1sap_up(l1t->trx, l1sap); + l1sap_up(l1ts->ts->trx, l1sap); return 0; } @@ -790,12 +779,12 @@ int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, * data request (from upper layer) */ -int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap) +int trx_sched_ph_data_req(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) { - uint8_t tn = l1sap->u.data.chan_nr & 7; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); + uint8_t tn = L1SAP_CHAN2TS(l1sap->u.data.chan_nr); + struct l1sched_ts *l1ts = trx->ts[tn].priv; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.data.fn, + LOGL1S(DL1P, LOGL_DEBUG, l1ts, -1, l1sap->u.data.fn, "PH-DATA.req: chan_nr=0x%02x link_id=0x%02x\n", l1sap->u.data.chan_nr, l1sap->u.data.link_id); @@ -813,13 +802,13 @@ int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap return 0; } -int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap) +int trx_sched_tch_req(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) { - uint8_t tn = l1sap->u.tch.chan_nr & 7; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); + uint8_t tn = L1SAP_CHAN2TS(l1sap->u.data.chan_nr); + struct l1sched_ts *l1ts = trx->ts[tn].priv; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.tch.fn, "TCH.req: chan_nr=0x%02x\n", - l1sap->u.tch.chan_nr); + LOGL1S(DL1P, LOGL_DEBUG, l1ts, -1, l1sap->u.tch.fn, + "TCH.req: chan_nr=0x%02x\n", l1sap->u.tch.chan_nr); OSMO_ASSERT(l1sap->oph.operation == PRIM_OP_REQUEST); OSMO_ASSERT(l1sap->oph.msg); @@ -841,31 +830,28 @@ int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap) */ /* RTS for data frame */ -static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan) +static int rts_data_fn(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br) { uint8_t chan_nr, link_id; struct msgb *msg; struct osmo_phsap_prim *l1sap; /* get data for RTS indication */ - chan_nr = trx_chan_desc[chan].chan_nr | tn; - link_id = trx_chan_desc[chan].link_id; + chan_nr = trx_chan_desc[br->chan].chan_nr | br->tn; + link_id = trx_chan_desc[br->chan].link_id; if (!chan_nr) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "RTS func with non-existing chan_nr %d\n", chan_nr); + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "RTS func with non-existing chan_nr 0x%02x\n", chan_nr); return -ENODEV; } /* For handover detection, there are cases where the SACCH should remain inactive until the first RACH * indicating the TA is received. */ if (L1SAP_IS_LINK_SACCH(link_id) - && !l1t->ts[tn].chan_state[chan].lchan->want_dl_sacch_active) + && !l1ts->chan_state[br->chan].lchan->want_dl_sacch_active) return 0; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, - "PH-RTS.ind: chan_nr=0x%02x link_id=0x%02x\n", chan_nr, link_id); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "PH-RTS.ind: chan_nr=0x%02x link_id=0x%02x\n", chan_nr, link_id); /* generate prim */ msg = l1sap_msgb_alloc(200); @@ -876,31 +862,30 @@ static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, PRIM_OP_INDICATION, msg); l1sap->u.data.chan_nr = chan_nr; l1sap->u.data.link_id = link_id; - l1sap->u.data.fn = fn; + l1sap->u.data.fn = br->fn; - return l1sap_up(l1t->trx, l1sap); + return l1sap_up(l1ts->ts->trx, l1sap); } -static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, int facch) +static int rts_tch_common(const struct l1sched_ts *l1ts, + const struct trx_dl_burst_req *br, + bool facch) { uint8_t chan_nr, link_id; struct msgb *msg; struct osmo_phsap_prim *l1sap; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); int rc = 0; /* get data for RTS indication */ - chan_nr = trx_chan_desc[chan].chan_nr | tn; - link_id = trx_chan_desc[chan].link_id; + chan_nr = trx_chan_desc[br->chan].chan_nr | br->tn; + link_id = trx_chan_desc[br->chan].link_id; if (!chan_nr) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "RTS func with non-existing chan_nr %d\n", chan_nr); + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "RTS func with non-existing chan_nr 0x%02x\n", chan_nr); return -ENODEV; } - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr); /* only send, if FACCH is selected */ if (facch) { @@ -913,13 +898,13 @@ static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, PRIM_OP_INDICATION, msg); l1sap->u.data.chan_nr = chan_nr; l1sap->u.data.link_id = link_id; - l1sap->u.data.fn = fn; + l1sap->u.data.fn = br->fn; - rc = l1sap_up(l1t->trx, l1sap); + rc = l1sap_up(l1ts->ts->trx, l1sap); } /* don't send, if TCH is in signalling only mode */ - if (l1ts->chan_state[chan].rsl_cmode != RSL_CMOD_SPD_SIGN) { + if (l1ts->chan_state[br->chan].rsl_cmode != RSL_CMOD_SPD_SIGN) { /* generate prim */ msg = l1sap_msgb_alloc(200); if (!msg) @@ -928,49 +913,44 @@ static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, PRIM_OP_INDICATION, msg); l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; + l1sap->u.tch.fn = br->fn; - return l1sap_up(l1t->trx, l1sap); + return l1sap_up(l1ts->ts->trx, l1sap); } return rc; } /* RTS for full rate traffic frame */ -static int rts_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan) +static int rts_tchf_fn(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br) { /* TCH/F may include FACCH on every 4th burst */ - return rts_tch_common(l1t, tn, fn, chan, 1); + return rts_tch_common(l1ts, br, true); } /* RTS for half rate traffic frame */ -static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan) +static int rts_tchh_fn(const struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br) { /* the FN 4/5, 13/14, 21/22 defines that FACCH may be included. */ - return rts_tch_common(l1t, tn, fn, chan, ((fn % 26) >> 2) & 1); + return rts_tch_common(l1ts, br, ((br->fn % 26) >> 2) & 1); } /* set multiframe scheduler to given pchan */ -int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn, - enum gsm_phys_chan_config pchan) +int trx_sched_set_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pchan) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - int i; - - i = find_sched_mframe_idx(pchan, tn); + struct l1sched_ts *l1ts = ts->priv; + int i = find_sched_mframe_idx(pchan, ts->nr); if (i < 0) { - LOGP(DL1C, LOGL_NOTICE, "Failed to configure multiframe " - "trx=%d ts=%d\n", l1t->trx->nr, tn); + LOGP(DL1C, LOGL_NOTICE, "%s Failed to configure multiframe\n", + gsm_ts_name(ts)); return -ENOTSUP; } l1ts->mf_index = i; l1ts->mf_period = trx_sched_multiframes[i].period; l1ts->mf_frames = trx_sched_multiframes[i].frames; - LOGP(DL1C, LOGL_NOTICE, "Configuring multiframe with %s trx=%d ts=%d\n", - trx_sched_multiframes[i].name, l1t->trx->nr, tn); + LOGP(DL1C, LOGL_NOTICE, "%s Configured multiframe with '%s'\n", + gsm_ts_name(ts), trx_sched_multiframes[i].name); return 0; } @@ -1006,10 +986,10 @@ static void trx_sched_queue_filter(struct llist_head *q, uint8_t chan_nr, uint8_ } /* setting all logical channels given attributes to active/inactive */ -int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id, bool active) +int trx_sched_set_lchan(struct gsm_lchan *lchan, uint8_t chan_nr, uint8_t link_id, bool active) { + struct l1sched_ts *l1ts = lchan->ts->priv; uint8_t tn = L1SAP_CHAN2TS(chan_nr); - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); uint8_t ss = l1sap_chan2ss(chan_nr); bool found = false; int i; @@ -1026,9 +1006,9 @@ int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_i continue; found = true; - LOGP(DL1C, LOGL_NOTICE, "%s %s on trx=%d ts=%d\n", - (active) ? "Activating" : "Deactivating", - trx_chan_desc[i].name, l1t->trx->nr, tn); + LOGPLCHAN(lchan, DL1C, LOGL_NOTICE, "%s %s\n", + (active) ? "Activating" : "Deactivating", + trx_chan_desc[i].name); /* free burst memory, to cleanly start with burst 0 */ if (chan_state->dl_bursts) { talloc_free(chan_state->dl_bursts); @@ -1044,8 +1024,7 @@ int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_i memset(chan_state, 0, sizeof(*chan_state)); /* Bind to generic 'struct gsm_lchan' */ - chan_state->lchan = get_lchan_by_chan_nr(l1t->trx, chan_nr); - OSMO_ASSERT(chan_state->lchan != NULL); + chan_state->lchan = lchan; } else { chan_state->ho_rach_detect = 0; @@ -1058,36 +1037,37 @@ int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_i /* disable handover detection (on deactivation) */ if (!active) - _sched_act_rach_det(l1t, tn, ss, 0); + _sched_act_rach_det(lchan->ts->trx, tn, ss, 0); return found ? 0 : -EINVAL; } /* setting all logical channels given attributes to active/inactive */ -int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode, +int trx_sched_set_mode(struct gsm_bts_trx_ts *ts, uint8_t chan_nr, uint8_t rsl_cmode, uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1, uint8_t codec2, uint8_t codec3, uint8_t initial_id, uint8_t handover) { + struct l1sched_ts *l1ts = ts->priv; uint8_t tn = L1SAP_CHAN2TS(chan_nr); - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); uint8_t ss = l1sap_chan2ss(chan_nr); int i; int rc = -EINVAL; - struct l1sched_chan_state *chan_state; /* no mode for PDCH */ - if (trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH) + if (ts->pchan == GSM_PCHAN_PDCH) return 0; /* look for all matching chan_nr/link_id */ for (i = 0; i < _TRX_CHAN_MAX; i++) { if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8) && trx_chan_desc[i].link_id == 0x00) { - chan_state = &l1ts->chan_state[i]; - LOGP(DL1C, LOGL_NOTICE, "Set mode %u, %u, handover %u " - "on %s of trx=%d ts=%d\n", rsl_cmode, tch_mode, - handover, trx_chan_desc[i].name, l1t->trx->nr, - tn); + struct l1sched_chan_state *chan_state = &l1ts->chan_state[i]; + + LOGP(DL1C, LOGL_NOTICE, + "%s Set mode for %s (rsl_cmode=%u, tch_mode=%u, handover=%u)\n", + gsm_ts_name(ts), trx_chan_desc[i].name, + rsl_cmode, tch_mode, handover); + chan_state->rsl_cmode = rsl_cmode; chan_state->tch_mode = tch_mode; chan_state->ho_rach_detect = handover; @@ -1114,50 +1094,49 @@ int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmo * of transceiver link). * disable handover, if state is still set, since we might not know * the actual state of transceiver (due to loss of link) */ - _sched_act_rach_det(l1t, tn, ss, handover); + _sched_act_rach_det(ts->trx, tn, ss, handover); return rc; } /* setting cipher on logical channels */ -int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink, - int algo, uint8_t *key, int key_len) +int trx_sched_set_cipher(struct gsm_lchan *lchan, uint8_t chan_nr, bool downlink) { - uint8_t tn = L1SAP_CHAN2TS(chan_nr); - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - int i; - int rc = -EINVAL; - struct l1sched_chan_state *chan_state; + int algo = lchan->encr.alg_id - 1; + int i, rc = -EINVAL; /* no cipher for PDCH */ - if (trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH) + if (lchan->ts->pchan == GSM_PCHAN_PDCH) return 0; /* no algorithm given means a5/0 */ if (algo <= 0) algo = 0; - else if (key_len != 8) { - LOGP(DL1C, LOGL_ERROR, "Algo A5/%d not supported with given " - "key len=%d\n", algo, key_len); + else if (lchan->encr.key_len != 8) { + LOGPLCHAN(lchan, DL1C, LOGL_ERROR, + "Algo A5/%d not supported with given key_len=%u\n", + algo, lchan->encr.key_len); return -ENOTSUP; } /* look for all matching chan_nr */ for (i = 0; i < _TRX_CHAN_MAX; i++) { if (trx_chan_desc[i].chan_nr == (chan_nr & RSL_CHAN_NR_MASK)) { - chan_state = &l1ts->chan_state[i]; - LOGP(DL1C, LOGL_NOTICE, "Set a5/%d %s for %s on trx=%d " - "ts=%d\n", algo, - (downlink) ? "downlink" : "uplink", - trx_chan_desc[i].name, l1t->trx->nr, tn); + struct l1sched_ts *l1ts = lchan->ts->priv; + struct l1sched_chan_state *l1cs = &l1ts->chan_state[i]; + + LOGPLCHAN(lchan, DL1C, LOGL_NOTICE, "Set A5/%d %s for %s\n", + algo, (downlink) ? "downlink" : "uplink", + trx_chan_desc[i].name); + if (downlink) { - chan_state->dl_encr_algo = algo; - memcpy(chan_state->dl_encr_key, key, key_len); - chan_state->dl_encr_key_len = key_len; + l1cs->dl_encr_algo = algo; + memcpy(l1cs->dl_encr_key, lchan->encr.key, lchan->encr.key_len); + l1cs->dl_encr_key_len = lchan->encr.key_len; } else { - chan_state->ul_encr_algo = algo; - memcpy(chan_state->ul_encr_key, key, key_len); - chan_state->ul_encr_key_len = key_len; + l1cs->ul_encr_algo = algo; + memcpy(l1cs->ul_encr_key, lchan->encr.key, lchan->encr.key_len); + l1cs->ul_encr_key_len = lchan->encr.key_len; } rc = 0; } @@ -1167,9 +1146,8 @@ int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink, } /* process ready-to-send */ -int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) +int _sched_rts(const struct l1sched_ts *l1ts, uint32_t fn) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); const struct trx_sched_frame *frame; uint8_t offset, period, bid; trx_sched_rts_func *func; @@ -1200,14 +1178,21 @@ int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) if (!TRX_CHAN_IS_ACTIVE(&l1ts->chan_state[chan], chan)) return -EINVAL; - return func(l1t, tn, fn, frame->dl_chan); + /* There is no burst, just for logging */ + struct trx_dl_burst_req dbr = { + .fn = fn, + .tn = l1ts->ts->nr, + .bid = bid, + .chan = chan, + }; + + return func(l1ts, &dbr); } /* process downlink burst */ -void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +void _sched_dl_burst(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); - struct l1sched_chan_state *l1cs; + const struct l1sched_chan_state *l1cs; const struct trx_sched_frame *frame; uint8_t offset, period; trx_sched_dl_func *func; @@ -1231,7 +1216,7 @@ void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) return; /* get burst from function */ - if (func(l1t, br) != 0) + if (func(l1ts, br) != 0) return; /* BS Power reduction (in dB) per logical channel */ @@ -1251,12 +1236,11 @@ void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) } } -static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t, +static int trx_sched_calc_frame_loss(struct l1sched_ts *l1ts, struct l1sched_chan_state *l1cs, const struct trx_ul_burst_ind *bi) { const struct trx_sched_frame *frame; - struct l1sched_ts *l1ts; uint32_t elapsed_fs; uint8_t offset, i; uint32_t fn_i; @@ -1269,9 +1253,6 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t, if (l1cs->proc_tdma_fs == 0) return 0; - /* Get current TDMA frame info */ - l1ts = l1sched_trx_get_ts(l1t, bi->tn); - /* Not applicable for some logical channels */ switch (bi->chan) { case TRXC_IDLE: @@ -1288,7 +1269,7 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t, /* How many frames elapsed since the last one? */ elapsed_fs = GSM_TDMA_FN_SUB(bi->fn, l1cs->last_tdma_fn); if (elapsed_fs > l1ts->mf_period) { /* Too many! */ - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "Too many (>%u) contiguous TDMA frames=%u elapsed " "since the last processed fn=%u\n", l1ts->mf_period, elapsed_fs, l1cs->last_tdma_fn); @@ -1314,7 +1295,7 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t, } if (l1cs->lost_tdma_fs > 0) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "At least %u TDMA frames were lost since the last " "processed fn=%u\n", l1cs->lost_tdma_fs, l1cs->last_tdma_fn); @@ -1350,10 +1331,10 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t, dbi.bid = frame->ul_bid; dbi.fn = fn_i; - LOGL1SB(DL1P, LOGL_NOTICE, l1t, &dbi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, &dbi, "Substituting lost burst with NOPE.ind\n"); - func(l1t, &dbi); + func(l1ts, &dbi); l1cs->lost_tdma_fs--; } @@ -1363,9 +1344,8 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t, } /* Process an Uplink burst indication */ -int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi) +int trx_sched_ul_burst(struct l1sched_ts *l1ts, struct trx_ul_burst_ind *bi) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn); struct l1sched_chan_state *l1cs; const struct trx_sched_frame *frame; uint8_t offset, period; @@ -1386,7 +1366,7 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi) /* TODO: handle noise measurements */ if (bi->chan == TRXC_IDLE && bi->flags & TRX_BI_F_NOPE_IND) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Rx noise measurement (%d)\n", bi->rssi); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Rx noise measurement (%d)\n", bi->rssi); return -ENOTSUP; } @@ -1399,7 +1379,7 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi) return -EINVAL; /* calculate how many TDMA frames were potentially lost */ - trx_sched_calc_frame_loss(l1t, l1cs, bi); + trx_sched_calc_frame_loss(l1ts, l1cs, bi); /* update TDMA frame counters */ l1cs->last_tdma_fn = bi->fn; @@ -1415,7 +1395,7 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi) default: /* NOTE: Uplink burst handler must check bi->burst_len before * accessing bi->burst to avoid uninitialized memory access. */ - return func(l1t, bi); + return func(l1ts, bi); } } @@ -1434,13 +1414,7 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi) } /* Invoke the logical channel handler */ - func(l1t, bi); + func(l1ts, bi); return 0; } - -struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn) -{ - OSMO_ASSERT(tn < ARRAY_SIZE(l1t->ts)); - return &l1t->ts[tn]; -} diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c index fc8ef7609..3f95a6962 100644 --- a/src/osmo-bts-trx/l1_if.c +++ b/src/osmo-bts-trx/l1_if.c @@ -109,9 +109,6 @@ static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail) int bts_model_lchan_deactivate(struct gsm_lchan *lchan) { - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - if (lchan->rel_act_kind == LCHAN_REL_ACT_REACT) { lchan->rel_act_kind = LCHAN_REL_ACT_RSL; /* FIXME: perform whatever is needed (if any) to set proper PCH/AGCH allocation according to @@ -121,14 +118,12 @@ int bts_model_lchan_deactivate(struct gsm_lchan *lchan) /* set lchan inactive */ lchan_set_state(lchan, LCHAN_S_NONE); - return trx_sched_set_lchan(&l1h->l1s, gsm_lchan2chan_nr(lchan), LID_DEDIC, false); + return trx_sched_set_lchan(lchan, gsm_lchan2chan_nr(lchan), LID_DEDIC, false); } int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) { - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - return trx_sched_set_lchan(&l1h->l1s, gsm_lchan2chan_nr(lchan), LID_SACCH, false); + return trx_sched_set_lchan(lchan, gsm_lchan2chan_nr(lchan), LID_SACCH, false); } int l1if_trx_start_power_ramp(struct gsm_bts_trx *trx, ramp_compl_cb_t ramp_compl_cb) @@ -293,7 +288,7 @@ static uint8_t trx_set_ts_as_pchan(struct gsm_bts_trx_ts *ts, * decided on a more specific PCHAN type already. */ OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - rc = trx_sched_set_pchan(&l1h->l1s, tn, pchan); + rc = trx_sched_set_pchan(ts, pchan); if (rc) return NM_NACK_RES_NOTAVAIL; @@ -344,8 +339,7 @@ static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts) */ /* enable ciphering */ -static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan, - uint8_t chan_nr, int downlink) +static int l1if_set_ciphering(struct gsm_lchan *lchan, uint8_t chan_nr, int downlink) { /* ciphering already enabled in both directions */ if (lchan->ciph_state == LCHAN_CIPH_RXTX_CONF) @@ -353,28 +347,22 @@ static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan, if (!downlink) { /* set uplink */ - trx_sched_set_cipher(&l1h->l1s, chan_nr, 0, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); + trx_sched_set_cipher(lchan, chan_nr, false); lchan->ciph_state = LCHAN_CIPH_RX_CONF; } else { /* set downlink and also set uplink, if not already */ - if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) { - trx_sched_set_cipher(&l1h->l1s, chan_nr, 0, - lchan->encr.alg_id - 1, lchan->encr.key, - lchan->encr.key_len); - } - trx_sched_set_cipher(&l1h->l1s, chan_nr, 1, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); + if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) + trx_sched_set_cipher(lchan, chan_nr, false); + trx_sched_set_cipher(lchan, chan_nr, true); lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; } return 0; } -static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr, - enum osmo_mph_info_type type, uint8_t cause) +static int mph_info_chan_confirm(struct gsm_bts_trx *trx, uint8_t chan_nr, + enum osmo_mph_info_type type, uint8_t cause) { - struct phy_instance *pinst = l1h->phy_inst; struct osmo_phsap_prim l1sap; memset(&l1sap, 0, sizeof(l1sap)); @@ -384,7 +372,7 @@ static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr, l1sap.u.info.u.act_cnf.chan_nr = chan_nr; l1sap.u.info.u.act_cnf.cause = cause; - return l1sap_up(pinst->trx, &l1sap); + return l1sap_up(trx, &l1sap); } int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn) @@ -406,8 +394,6 @@ int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn) /* primitive from common part */ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; struct msgb *msg = l1sap->oph.msg; uint8_t chan_nr; int rc = 0; @@ -418,21 +404,21 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) if (!msg) break; /* put data into scheduler's queue */ - return trx_sched_ph_data_req(&l1h->l1s, l1sap); + return trx_sched_ph_data_req(trx, l1sap); case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): if (!msg) break; /* put data into scheduler's queue */ - return trx_sched_tch_req(&l1h->l1s, l1sap); + return trx_sched_tch_req(trx, l1sap); case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): switch (l1sap->u.info.type) { case PRIM_INFO_ACT_CIPH: chan_nr = l1sap->u.info.u.ciph_req.chan_nr; lchan = get_lchan_by_chan_nr(trx, chan_nr); if (l1sap->u.info.u.ciph_req.uplink) - l1if_set_ciphering(l1h, lchan, chan_nr, 0); + l1if_set_ciphering(lchan, chan_nr, 0); if (l1sap->u.info.u.ciph_req.downlink) - l1if_set_ciphering(l1h, lchan, chan_nr, 1); + l1if_set_ciphering(lchan, chan_nr, 1); break; case PRIM_INFO_ACTIVATE: case PRIM_INFO_DEACTIVATE: @@ -463,11 +449,11 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) chan_nr = RSL_CHAN_OSMO_PDCH | (chan_nr & ~RSL_CHAN_NR_MASK); /* activate dedicated channel */ - trx_sched_set_lchan(&l1h->l1s, chan_nr, LID_DEDIC, true); + trx_sched_set_lchan(lchan, chan_nr, LID_DEDIC, true); /* activate associated channel */ - trx_sched_set_lchan(&l1h->l1s, chan_nr, LID_SACCH, true); + trx_sched_set_lchan(lchan, chan_nr, LID_SACCH, true); /* set mode */ - trx_sched_set_mode(&l1h->l1s, chan_nr, + trx_sched_set_mode(lchan->ts, chan_nr, lchan->rsl_cmode, lchan->tch_mode, lchan->tch.amr_mr.num_modes, lchan->tch.amr_mr.bts_mode[0].mode, @@ -481,16 +467,15 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) /* set lchan active */ lchan_set_state(lchan, LCHAN_S_ACTIVE); /* set initial ciphering */ - l1if_set_ciphering(l1h, lchan, chan_nr, 0); - l1if_set_ciphering(l1h, lchan, chan_nr, 1); + l1if_set_ciphering(lchan, chan_nr, 0); + l1if_set_ciphering(lchan, chan_nr, 1); if (lchan->encr.alg_id) lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; else lchan->ciph_state = LCHAN_CIPH_NONE; /* confirm */ - mph_info_chan_confirm(l1h, chan_nr, - PRIM_INFO_ACTIVATE, 0); + mph_info_chan_confirm(trx, chan_nr, PRIM_INFO_ACTIVATE, 0); break; } if (l1sap->u.info.type == PRIM_INFO_MODIFY) { @@ -499,7 +484,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) osmo_ecu_destroy(lchan->ecu_state); lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan)); /* change mode */ - trx_sched_set_mode(&l1h->l1s, chan_nr, + trx_sched_set_mode(lchan->ts, chan_nr, lchan->rsl_cmode, lchan->tch_mode, lchan->tch.amr_mr.num_modes, lchan->tch.amr_mr.bts_mode[0].mode, @@ -527,8 +512,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) /* deactivate dedicated channel */ lchan_deactivate(lchan); /* confirm only on dedicated channel */ - mph_info_chan_confirm(l1h, chan_nr, - PRIM_INFO_DEACTIVATE, 0); + mph_info_chan_confirm(trx, chan_nr, PRIM_INFO_DEACTIVATE, 0); } break; default: diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h index 491f7cd7e..864bb6915 100644 --- a/src/osmo-bts-trx/l1_if.h +++ b/src/osmo-bts-trx/l1_if.h @@ -125,8 +125,6 @@ struct trx_l1h { /* transceiver config */ struct trx_config config; struct osmo_fsm_inst *provision_fi; - - struct l1sched_trx l1s; }; struct trx_l1h *trx_l1h_alloc(void *tall_ctx, struct phy_instance *pinst); @@ -136,10 +134,4 @@ void l1if_trx_set_nominal_power(struct gsm_bts_trx *trx, int nominal_power); int l1if_trx_start_power_ramp(struct gsm_bts_trx *trx, ramp_compl_cb_t ramp_compl_cb); enum gsm_phys_chan_config transceiver_chan_type_2_pchan(uint8_t type); -static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx) -{ - struct trx_l1h *l1h = trx->pinst->u.osmotrx.hdl; - return &l1h->l1s; -} - #endif /* L1_IF_H_TRX */ diff --git a/src/osmo-bts-trx/loops.c b/src/osmo-bts-trx/loops.c index 823c2d7da..4c70e8d1c 100644 --- a/src/osmo-bts-trx/loops.c +++ b/src/osmo-bts-trx/loops.c @@ -35,13 +35,10 @@ #include "l1_if.h" #include "loops.h" -void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, - int n_errors, int n_bits_total) +void trx_loop_amr_input(struct l1sched_chan_state *chan_state, + int n_errors, int n_bits_total) { - struct gsm_bts_trx *trx = l1t->trx; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)] - .lchan[l1sap_chan2ss(chan_nr)]; + struct gsm_lchan *lchan = chan_state->lchan; float ber; /* calculate BER (Bit Error Ratio) */ @@ -59,7 +56,7 @@ void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr, return; /* count bit errors */ - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { + if (lchan->type == GSM_LCHAN_TCH_H) { chan_state->ber_num += 2; chan_state->ber_sum += (ber + ber); } else { diff --git a/src/osmo-bts-trx/loops.h b/src/osmo-bts-trx/loops.h index 138496037..4aa05c4c4 100644 --- a/src/osmo-bts-trx/loops.h +++ b/src/osmo-bts-trx/loops.h @@ -11,9 +11,8 @@ * loops api */ -void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, - int n_errors, int n_bits_total); +void trx_loop_amr_input(struct l1sched_chan_state *chan_state, + int n_errors, int n_bits_total); void trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop); diff --git a/src/osmo-bts-trx/sched_lchan_fcch_sch.c b/src/osmo-bts-trx/sched_lchan_fcch_sch.c index 4aac60177..eaf140f93 100644 --- a/src/osmo-bts-trx/sched_lchan_fcch_sch.c +++ b/src/osmo-bts-trx/sched_lchan_fcch_sch.c @@ -36,9 +36,9 @@ #include /* obtain a to-be-transmitted FCCH (frequency correction channel) burst */ -int tx_fcch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_fcch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting FCCH\n"); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting FCCH\n"); /* A frequency correction burst is basically a sequence of zeros. * Since br->burst is already zero-initialized, just set the length. */ @@ -48,21 +48,21 @@ int tx_fcch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) } /* obtain a to-be-transmitted SCH (synchronization channel) burst */ -int tx_sch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_sch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { ubit_t burst[78]; uint8_t sb_info[4]; struct gsm_time t; uint8_t t3p, bsic; - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting SCH\n"); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting SCH\n"); /* BURST BYPASS */ /* create SB info from GSM time and BSIC */ gsm_fn2gsmtime(&t, br->fn); t3p = t.t3 / 10; - bsic = l1t->trx->bts->bsic; + bsic = l1ts->ts->trx->bts->bsic; sb_info[0] = ((bsic & 0x3f) << 2) | ((t.t1 & 0x600) >> 9); diff --git a/src/osmo-bts-trx/sched_lchan_pdtch.c b/src/osmo-bts-trx/sched_lchan_pdtch.c index 7ccc77a4f..8648cb8bc 100644 --- a/src/osmo-bts-trx/sched_lchan_pdtch.c +++ b/src/osmo-bts-trx/sched_lchan_pdtch.c @@ -39,9 +39,8 @@ #define EGPRS_0503_MAX_BYTES 155 /*! \brief a single PDTCH burst was received by the PHY, process it */ -int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_pdtch_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn); struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; sbit_t *burst, **bursts_p = &chan_state->ul_bursts; uint32_t first_fn; @@ -55,7 +54,7 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) int rc; enum osmo_ph_pres_info_type presence_info; - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received PDTCH bid=%u\n", bi->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received PDTCH bid=%u\n", bi->bid); /* allocate burst memory, if not already */ if (!*bursts_p) { @@ -107,7 +106,7 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* check for complete set of bursts */ if ((*mask & 0xf) != 0xf) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received incomplete frame (%u/%u)\n", + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received incomplete frame (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); } *mask = 0x0; @@ -129,7 +128,7 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) if (rc > 0) { presence_info = PRES_INFO_BOTH; } else { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received bad PDTCH (%u/%u)\n", + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received bad PDTCH (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); rc = 0; presence_info = PRES_INFO_INVALID; @@ -138,7 +137,7 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) ber10k = compute_ber10k(n_bits_total, n_errors); first_fn = GSM_TDMA_FN_SUB(bi->fn, 3); - return _sched_compose_ph_data_ind(l1t, bi->tn, + return _sched_compose_ph_data_ind(l1ts, first_fn, bi->chan, l2, rc, meas_avg.rssi, meas_avg.toa256, meas_avg.ci_cb, ber10k, @@ -146,10 +145,8 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) } /* obtain a to-be-transmitted PDTCH (packet data) burst */ -int tx_pdtch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_pdtch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn]; struct msgb *msg = NULL; /* make GCC happy */ ubit_t *burst, **bursts_p = &l1ts->chan_state[br->chan].dl_bursts; enum trx_mod_type *mod = &l1ts->chan_state[br->chan].dl_mod_type; @@ -163,11 +160,11 @@ int tx_pdtch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) } /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, br); + msg = _sched_dequeue_prim(l1ts, br); if (msg) goto got_msg; - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "No prim for transmit.\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No prim for transmit.\n"); no_msg: /* free burst memory */ @@ -195,7 +192,7 @@ got_msg: /* check validity of message */ if (rc < 0) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "Prim invalid length, please FIX! " + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim invalid length, please FIX! " "(len=%ld)\n", (long)(msg->tail - msg->l2h)); /* free message */ msgb_free(msg); @@ -215,7 +212,7 @@ send_burst: burst = *bursts_p + br->bid * 348; memset(br->burst, 1, 9); memcpy(br->burst + 9, burst, 174); - memcpy(br->burst + 183, _sched_egprs_tsc[gsm_ts_tsc(ts)], 78); + memcpy(br->burst + 183, _sched_egprs_tsc[gsm_ts_tsc(l1ts->ts)], 78); memcpy(br->burst + 261, burst + 174, 174); memset(br->burst + 435, 1, 9); @@ -223,13 +220,13 @@ send_burst: } else { burst = *bursts_p + br->bid * 116; memcpy(br->burst + 3, burst, 58); - memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(l1ts->ts)], 26); memcpy(br->burst + 87, burst + 58, 58); br->burst_len = GSM_BURST_LEN; } - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting burst=%u.\n", br->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting burst=%u.\n", br->bid); return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_rach.c b/src/osmo-bts-trx/sched_lchan_rach.c index ce9a46b16..c3abf321f 100644 --- a/src/osmo-bts-trx/sched_lchan_rach.c +++ b/src/osmo-bts-trx/sched_lchan_rach.c @@ -102,8 +102,9 @@ static enum rach_synch_seq_t rach_get_synch_seq(sbit_t *bits, int *best_score) return seq; } -int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_rach_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { + struct gsm_bts_trx *trx = l1ts->ts->trx; struct osmo_phsap_prim l1sap; int n_errors = 0; int n_bits_total = 0; @@ -130,7 +131,7 @@ int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) synch_seq = rach_get_synch_seq((sbit_t *) bi->burst, &best_score); } - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received%s RACH (%s): rssi=%d toa256=%d", (bi->chan != TRXC_RACH) ? " handover" : "", get_value_string(rach_synch_seq_names, synch_seq), @@ -157,16 +158,16 @@ int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) if (bi->flags & TRX_BI_F_CI_CB) l1sap.u.rach_ind.lqual_cb = bi->ci_cb; else - l1sap.u.rach_ind.lqual_cb = l1t->trx->bts->min_qual_rach; + l1sap.u.rach_ind.lqual_cb = trx->bts->min_qual_rach; /* Decode RACH depending on its synch. sequence */ switch (synch_seq) { case RACH_SYNCH_SEQ_TS1: case RACH_SYNCH_SEQ_TS2: rc = gsm0503_rach_ext_decode_ber(&ra11, bi->burst + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN, - l1t->trx->bts->bsic, &n_errors, &n_bits_total); + trx->bts->bsic, &n_errors, &n_bits_total); if (rc) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received bad Access Burst\n"); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received bad Access Burst\n"); return 0; } @@ -183,14 +184,14 @@ int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) default: /* Fall-back to the default TS0 if needed */ if (synch_seq != RACH_SYNCH_SEQ_TS0) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Falling-back to the default TS0\n"); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Falling-back to the default TS0\n"); synch_seq = RACH_SYNCH_SEQ_TS0; } rc = gsm0503_rach_decode_ber(&ra, bi->burst + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN, - l1t->trx->bts->bsic, &n_errors, &n_bits_total); + trx->bts->bsic, &n_errors, &n_bits_total); if (rc) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received bad Access Burst\n"); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received bad Access Burst\n"); return 0; } @@ -203,7 +204,7 @@ int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors); /* forward primitive */ - l1sap_up(l1t->trx, &l1sap); + l1sap_up(trx, &l1sap); return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c index 8ace49e87..0961758a8 100644 --- a/src/osmo-bts-trx/sched_lchan_tchf.c +++ b/src/osmo-bts-trx/sched_lchan_tchf.c @@ -46,9 +46,8 @@ #include /*! \brief a single TCH/F burst was received by the PHY, process it */ -int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn); struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; struct gsm_lchan *lchan = chan_state->lchan; sbit_t *burst, **bursts_p = &chan_state->ul_bursts; @@ -70,9 +69,9 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* If handover RACH detection is turned on, treat this burst as an Access Burst. * Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */ if (chan_state->ho_rach_detect == 1 && ~bi->flags & TRX_BI_F_NOPE_IND) - return rx_rach_fn(l1t, bi); + return rx_rach_fn(l1ts, bi); - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received TCH/F, bid=%u\n", bi->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received TCH/F, bid=%u\n", bi->bid); /* allocate burst memory, if not already */ if (!*bursts_p) { @@ -107,7 +106,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* check for complete set of bursts */ if ((*mask & 0xf) != 0xf) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received incomplete frame (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); } @@ -152,7 +151,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* Tag all frames that are not regular AMR voice frames as * SUB-Frames */ if (chan_state->amr_last_dtx != AMR_OTHER) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received AMR SID frame: %s\n", + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received AMR SID frame: %s\n", gsm0503_amr_dtx_frame_name(chan_state->amr_last_dtx)); is_sub = 1; } @@ -183,9 +182,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) } if (rc) - trx_loop_amr_input(l1t, - trx_chan_desc[bi->chan].chan_nr | bi->tn, chan_state, - n_errors, n_bits_total); + trx_loop_amr_input(chan_state, n_errors, n_bits_total); /* only good speech frames get rtp header */ if (rc != GSM_MACBLOCK_LEN && rc >= 4) { if (chan_state->amr_last_dtx == AMR_OTHER) { @@ -201,7 +198,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) break; default: - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "TCH mode %u invalid, please fix!\n", tch_mode); return -EINVAL; @@ -213,11 +210,11 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* Check if the frame is bad */ if (rc < 0) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, "Received bad data (%u/%u)\n", + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); bfi_flag = true; } else if (rc < 4) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u) with invalid codec mode %d\n", bi->fn % l1ts->mf_period, l1ts->mf_period, rc); bfi_flag = true; @@ -233,7 +230,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* FACCH */ if (rc == GSM_MACBLOCK_LEN) { fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_F); - _sched_compose_ph_data_ind(l1t, bi->tn, fn_begin, bi->chan, + _sched_compose_ph_data_ind(l1ts, fn_begin, bi->chan, tch_data + amr, GSM_MACBLOCK_LEN, meas_avg.rssi, meas_avg.toa256, meas_avg.ci_cb, ber10k, @@ -281,7 +278,7 @@ bfi: chan_state->codec[chan_state->dl_ft], AMR_BAD); if (rc < 2) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "Failed to encode AMR_BAD frame (rc=%d), " "not sending BFI\n", rc); return -EINVAL; @@ -289,7 +286,7 @@ bfi: memset(tch_data + 2, 0, rc - 2); break; default: - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "TCH mode %u invalid, please fix!\n", tch_mode); return -EINVAL; } @@ -302,7 +299,7 @@ bfi: /* TCH or BFI */ compose_l1sap: fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F); - return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, bi->chan, tch_data, rc, + return _sched_compose_tch_ind(l1ts, fn_begin, bi->chan, tch_data, rc, /* FIXME: what should we use for BFI here? */ bfi_flag ? bi->toa256 : meas_avg.toa256, ber10k, bfi_flag ? bi->rssi : meas_avg.rssi, is_sub); @@ -310,10 +307,9 @@ compose_l1sap: /* common section for generation of TCH bursts (TCH/H and TCH/F). * FIXME: this function is over-complicated, refactor / get rid of it. */ -void tx_tch_common(struct l1sched_trx *l1t, struct trx_dl_burst_req *br, +void tx_tch_common(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br, struct msgb **_msg_tch, struct msgb **_msg_facch) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL; struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan]; uint8_t rsl_cmode = chan_state->rsl_cmode; @@ -326,7 +322,7 @@ void tx_tch_common(struct l1sched_trx *l1t, struct trx_dl_burst_req *br, uint8_t tch_data[GSM_FR_BYTES]; int len; - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, "Missing TCH bursts detected, sending BFI\n"); + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Missing TCH bursts detected, sending BFI\n"); /* indicate bad frame */ switch (tch_mode) { @@ -351,7 +347,7 @@ void tx_tch_common(struct l1sched_trx *l1t, struct trx_dl_burst_req *br, chan_state->codec[chan_state->dl_cmr], chan_state->codec[chan_state->dl_ft], AMR_BAD); if (len < 2) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Failed to encode AMR_BAD frame (rc=%d), " "not sending BFI\n", len); return; @@ -360,21 +356,21 @@ void tx_tch_common(struct l1sched_trx *l1t, struct trx_dl_burst_req *br, break; default: inval_mode1: - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "TCH mode invalid, please fix!\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, please fix!\n"); len = 0; } if (len) { /* Note: RSSI/ToA256 is set to 0 to indicate to the higher * layers that this is a faked tch_ind */ - _sched_compose_tch_ind(l1t, br->tn, br->fn, br->chan, + _sched_compose_tch_ind(l1ts, br->fn, br->chan, tch_data, len, 0, 10000, 0, 0); } } /* get frame and unlink from queue */ - msg1 = _sched_dequeue_prim(l1t, br); - msg2 = _sched_dequeue_prim(l1t, br); + msg1 = _sched_dequeue_prim(l1ts, br); + msg2 = _sched_dequeue_prim(l1ts, br); if (msg1) { l1sap = msgb_l1sap_prim(msg1); if (l1sap->oph.primitive == PRIM_TCH) { @@ -382,7 +378,7 @@ inval_mode1: if (msg2) { l1sap = msgb_l1sap_prim(msg2); if (l1sap->oph.primitive == PRIM_TCH) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "TCH twice, please FIX!\n"); + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "TCH twice, please FIX!\n"); msgb_free(msg2); } else msg_facch = msg2; @@ -392,7 +388,7 @@ inval_mode1: if (msg2) { l1sap = msgb_l1sap_prim(msg2); if (l1sap->oph.primitive != PRIM_TCH) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "FACCH twice, please FIX!\n"); + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "FACCH twice, please FIX!\n"); msgb_free(msg2); } else msg_tch = msg2; @@ -408,7 +404,7 @@ inval_mode1: /* check validity of message */ if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "Prim has odd len=%u != %u\n", + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != %u\n", msgb_l2len(msg_facch), GSM_MACBLOCK_LEN); /* free message */ msgb_free(msg_facch); @@ -425,7 +421,7 @@ inval_mode1: int8_t sti, cmi; if (rsl_cmode != RSL_CMOD_SPD_SPEECH) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, "Dropping speech frame, " + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Dropping speech frame, " "because we are not in speech mode\n"); goto free_bad_msg; } @@ -463,32 +459,32 @@ inval_mode1: trx_loop_amr_set(chan_state, 1); } if (ft < 0) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Codec (FT = %d) of RTP frame not in list\n", ft_codec); goto free_bad_msg; } if (fn_is_codec_mode_request(br->fn) && chan_state->dl_ft != ft) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, "Codec (FT = %d) " + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Codec (FT = %d) " " of RTP cannot be changed now, but in next frame\n", ft_codec); goto free_bad_msg; } chan_state->dl_ft = ft; if (bfi == AMR_BAD) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, "Transmitting 'bad AMR frame'\n"); + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Transmitting 'bad AMR frame'\n"); goto free_bad_msg; } break; default: inval_mode2: - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "TCH mode invalid, please fix!\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, please fix!\n"); goto free_bad_msg; } if (len < 0) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Cannot send invalid AMR payload\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send invalid AMR payload\n"); goto free_bad_msg; } if (msgb_l2len(msg_tch) != len) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Cannot send payload with " + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send payload with " "invalid length! (expecting %d, received %d)\n", len, msgb_l2len(msg_tch)); free_bad_msg: @@ -505,11 +501,9 @@ send_frame: } /* obtain a to-be-transmitted TCH/F (Full Traffic Channel) burst */ -int tx_tchf_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_tchf_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn]; struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan]; uint8_t tch_mode = chan_state->tch_mode; ubit_t *burst, **bursts_p = &chan_state->dl_bursts; @@ -521,7 +515,7 @@ int tx_tchf_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) goto send_burst; } - tx_tch_common(l1t, br, &msg_tch, &msg_facch); + tx_tch_common(l1ts, br, &msg_tch, &msg_facch); /* BURST BYPASS */ @@ -538,7 +532,7 @@ int tx_tchf_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) /* no message at all */ if (!msg_tch && !msg_facch) { - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "No TCH or FACCH prim for transmit.\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No TCH or FACCH prim for transmit.\n"); goto send_burst; } @@ -568,12 +562,12 @@ send_burst: /* compose burst */ burst = *bursts_p + br->bid * 116; memcpy(br->burst + 3, burst, 58); - memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(l1ts->ts)], 26); memcpy(br->burst + 87, burst + 58, 58); br->burst_len = GSM_BURST_LEN; - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting burst=%u.\n", br->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting burst=%u.\n", br->bid); return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c index ca05844fa..e526e48da 100644 --- a/src/osmo-bts-trx/sched_lchan_tchh.c +++ b/src/osmo-bts-trx/sched_lchan_tchh.c @@ -46,9 +46,8 @@ #include /*! \brief a single TCH/H burst was received by the PHY, process it */ -int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn); struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; struct gsm_lchan *lchan = chan_state->lchan; sbit_t *burst, **bursts_p = &chan_state->ul_bursts; @@ -77,9 +76,9 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* If handover RACH detection is turned on, treat this burst as an Access Burst. * Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */ if (chan_state->ho_rach_detect == 1 && ~bi->flags & TRX_BI_F_NOPE_IND) - return rx_rach_fn(l1t, bi); + return rx_rach_fn(l1ts, bi); - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received TCH/H, bid=%u\n", bi->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received TCH/H, bid=%u\n", bi->bid); /* allocate burst memory, if not already */ if (!*bursts_p) { @@ -114,7 +113,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* check for complete set of bursts */ if ((*mask & 0x3) != 0x3) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received incomplete frame (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); } @@ -175,7 +174,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* Tag all frames that are not regular AMR voice frames as SUB-Frames */ if (chan_state->amr_last_dtx != AMR_OTHER) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received AMR SID frame: %s\n", + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received AMR SID frame: %s\n", gsm0503_amr_dtx_frame_name(chan_state->amr_last_dtx)); is_sub = 1; } @@ -206,9 +205,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) } if (rc) - trx_loop_amr_input(l1t, - trx_chan_desc[bi->chan].chan_nr | bi->tn, chan_state, - n_errors, n_bits_total); + trx_loop_amr_input(chan_state, n_errors, n_bits_total); /* only good speech frames get rtp header */ if (rc != GSM_MACBLOCK_LEN && rc >= 4) { @@ -225,7 +222,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) break; default: - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "TCH mode %u invalid, please fix!\n", tch_mode); return -EINVAL; @@ -241,11 +238,11 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* Check if the frame is bad */ if (rc < 0) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, "Received bad data (%u/%u)\n", + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); bfi_flag = true; } else if (rc < 4) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u) with invalid codec mode %d\n", bi->fn % l1ts->mf_period, l1ts->mf_period, rc); bfi_flag = true; @@ -265,7 +262,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H0); else fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H1); - _sched_compose_ph_data_ind(l1t, bi->tn, fn_begin, bi->chan, + _sched_compose_ph_data_ind(l1ts, fn_begin, bi->chan, tch_data + amr, GSM_MACBLOCK_LEN, meas_avg.rssi, meas_avg.toa256, meas_avg.ci_cb, ber10k, @@ -312,7 +309,7 @@ bfi: chan_state->codec[chan_state->dl_ft], AMR_BAD); if (rc < 2) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "Failed to encode AMR_BAD frame (rc=%d), " "not sending BFI\n", rc); return -EINVAL; @@ -320,7 +317,7 @@ bfi: memset(tch_data + 2, 0, rc - 2); break; default: - LOGL1SB(DL1P, LOGL_ERROR, l1t, bi, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "TCH mode %u invalid, please fix!\n", tch_mode); return -EINVAL; } @@ -364,7 +361,7 @@ compose_l1sap: chan_state->ber10k_facch = 0; } - return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, bi->chan, tch_data, rc, + return _sched_compose_tch_ind(l1ts, fn_begin, bi->chan, tch_data, rc, /* FIXME: what should we use for BFI here? */ bfi_flag ? bi->toa256 : meas_avg.toa256, ber10k, bfi_flag ? bi->rssi : meas_avg.rssi, is_sub); @@ -372,16 +369,14 @@ compose_l1sap: /* common section for generation of TCH bursts (TCH/H and TCH/F). * FIXME: this function is over-complicated, refactor / get rid of it. */ -extern void tx_tch_common(struct l1sched_trx *l1t, +extern void tx_tch_common(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br, struct msgb **_msg_tch, struct msgb **_msg_facch); /* obtain a to-be-transmitted TCH/H (Half Traffic Channel) burst */ -int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_tchh_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn]; struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan]; uint8_t tch_mode = chan_state->tch_mode; ubit_t *burst, **bursts_p = &chan_state->dl_bursts; @@ -394,11 +389,11 @@ int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) } /* get TCH and/or FACCH */ - tx_tch_common(l1t, br, &msg_tch, &msg_facch); + tx_tch_common(l1ts, br, &msg_tch, &msg_facch); /* check for FACCH alignment */ if (msg_facch && ((((br->fn + 4) % 26) >> 2) & 1)) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot transmit FACCH starting on even frames, please fix RTS!\n"); msgb_free(msg_facch); msg_facch = NULL; @@ -424,7 +419,7 @@ int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) /* no message at all */ if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) { - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "No TCH or FACCH prim for transmit.\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No TCH or FACCH prim for transmit.\n"); goto send_burst; } @@ -456,12 +451,12 @@ send_burst: /* compose burst */ burst = *bursts_p + br->bid * 116; memcpy(br->burst + 3, burst, 58); - memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(l1ts->ts)], 26); memcpy(br->burst + 87, burst + 58, 58); br->burst_len = GSM_BURST_LEN; - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting burst=%u.\n", br->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting burst=%u.\n", br->bid); return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c b/src/osmo-bts-trx/sched_lchan_xcch.c index ba0d612dd..62b511cdc 100644 --- a/src/osmo-bts-trx/sched_lchan_xcch.c +++ b/src/osmo-bts-trx/sched_lchan_xcch.c @@ -47,9 +47,8 @@ static void add_sbits(sbit_t * current, const sbit_t * previous) } /*! \brief a single (SDCCH/SACCH) burst was received by the PHY, process it */ -int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn); struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; sbit_t *burst, **bursts_p = &chan_state->ul_bursts; uint32_t *first_fn = &chan_state->ul_first_fn; @@ -66,9 +65,9 @@ int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* If handover RACH detection is turned on, treat this burst as an Access Burst. * Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */ if (chan_state->ho_rach_detect == 1 && ~bi->flags & TRX_BI_F_NOPE_IND) - return rx_rach_fn(l1t, bi); + return rx_rach_fn(l1ts, bi); - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, "Received Data, bid=%u\n", bi->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received Data, bid=%u\n", bi->bid); /* allocate burst memory, if not already */ if (!*bursts_p) { @@ -116,7 +115,7 @@ int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* check for complete set of bursts */ if ((*mask & 0xf) != 0xf) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, "Received incomplete data (%u/%u)\n", + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received incomplete data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); /* we require first burst to have correct FN */ @@ -130,7 +129,7 @@ int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) /* decode */ rc = gsm0503_xcch_decode(l2, *bursts_p, &n_errors, &n_bits_total); if (rc) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, "Received bad data (%u/%u)\n", + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); l2_len = 0; @@ -142,11 +141,11 @@ int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) add_sbits(*bursts_p, chan_state->ul_bursts_prev); rc = gsm0503_xcch_decode(l2, *bursts_p, &n_errors, &n_bits_total); if (rc) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, bi, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Combining current SACCH block with previous SACCH block also yields bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); } else { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, bi, + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Combining current SACCH block with previous SACCH block yields good data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); l2_len = GSM_MACBLOCK_LEN; @@ -161,7 +160,7 @@ int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) if (rep_sacch) memcpy(chan_state->ul_bursts_prev, *bursts_p, 464); - return _sched_compose_ph_data_ind(l1t, bi->tn, *first_fn, + return _sched_compose_ph_data_ind(l1ts, *first_fn, bi->chan, l2, l2_len, meas_avg.rssi, meas_avg.toa256, meas_avg.ci_cb, ber10k, @@ -169,10 +168,8 @@ int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) } /* obtain a to-be-transmitted xCCH (e.g SACCH or SDCCH) burst */ -int tx_data_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_data_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[br->tn]; struct msgb *msg = NULL; /* make GCC happy */ ubit_t *burst, **bursts_p = &l1ts->chan_state[br->chan].dl_bursts; @@ -184,11 +181,11 @@ int tx_data_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) } /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, br); + msg = _sched_dequeue_prim(l1ts, br); if (msg) goto got_msg; - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "No prim for transmit.\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No prim for transmit.\n"); no_msg: /* free burst memory */ @@ -201,7 +198,7 @@ no_msg: got_msg: /* check validity of message */ if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "Prim has odd len=%u != %u\n", + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != %u\n", msgb_l2len(msg), GSM_MACBLOCK_LEN); /* free message */ msgb_free(msg); @@ -219,7 +216,7 @@ got_msg: /* Note: RSSI is set to 0 to indicate to the higher * layers that this is a faked ph_data_ind */ - _sched_compose_ph_data_ind(l1t, br->tn, 0, br->chan, NULL, 0, + _sched_compose_ph_data_ind(l1ts, 0, br->chan, NULL, 0, 0, 0, 0, 10000, PRES_INFO_INVALID); } @@ -242,12 +239,12 @@ send_burst: /* compose burst */ burst = *bursts_p + br->bid * 116; memcpy(br->burst + 3, burst, 58); - memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(l1ts->ts)], 26); memcpy(br->burst + 87, burst + 58, 58); br->burst_len = GSM_BURST_LEN; - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting burst=%u.\n", br->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting burst=%u.\n", br->bid); return 0; } diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index 3c29fcb70..c90a0a30e 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -53,9 +53,9 @@ (ts)->hopping.hsn, (ts)->hopping.maio, (ts)->hopping.arfcn_num /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */ -int tx_idle_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_idle_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, "Transmitting IDLE\n"); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting IDLE\n"); return 0; } @@ -108,7 +108,6 @@ static void bts_sched_fn(struct gsm_bts *bts, const uint32_t fn) llist_for_each_entry(trx, &bts->trx_list, list) { const struct phy_link *plink = trx->pinst->phy_link; struct trx_l1h *l1h = trx->pinst->u.osmotrx.hdl; - struct l1sched_trx *l1t = &l1h->l1s; /* we don't schedule, if power is off */ if (!trx_if_powered(l1h)) @@ -119,11 +118,12 @@ static void bts_sched_fn(struct gsm_bts *bts, const uint32_t fn) sched_fn = GSM_TDMA_FN_SUM(fn, plink->u.osmotrx.clock_advance); /* process every TS of TRX */ - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { + for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { const struct phy_instance *pinst = trx->pinst; + struct l1sched_ts *l1ts = trx->ts[tn].priv; /* ready-to-send */ - _sched_rts(l1t, tn, GSM_TDMA_FN_SUM(sched_fn, plink->u.osmotrx.rts_advance)); + _sched_rts(l1ts, GSM_TDMA_FN_SUM(sched_fn, plink->u.osmotrx.rts_advance)); /* All other parameters to be set by _sched_dl_burst() */ br = (struct trx_dl_burst_req) { @@ -132,7 +132,7 @@ static void bts_sched_fn(struct gsm_bts *bts, const uint32_t fn) }; /* get burst for FN */ - _sched_dl_burst(l1t, &br); + _sched_dl_burst(l1ts, &br); if (br.burst_len == 0) { /* if no bits, send no burst */ continue; @@ -206,24 +206,17 @@ static struct gsm_bts_trx *ulfh_route_bi(const struct trx_ul_burst_ind *bi, } /* Route a given Uplink burst indication to the scheduler depending on freq. hopping state */ -int trx_sched_route_burst_ind(struct trx_ul_burst_ind *bi, struct l1sched_trx *l1t) +int trx_sched_route_burst_ind(const struct gsm_bts_trx *trx, struct trx_ul_burst_ind *bi) { - const struct phy_instance *pinst; - const struct gsm_bts_trx *trx; - struct trx_l1h *l1h; - /* no frequency hopping => nothing to do */ - if (!l1t->trx->ts[bi->tn].hopping.enabled) - return trx_sched_ul_burst(l1t, bi); + if (!trx->ts[bi->tn].hopping.enabled) + return trx_sched_ul_burst(trx->ts[bi->tn].priv, bi); - trx = ulfh_route_bi(bi, l1t->trx); + trx = ulfh_route_bi(bi, trx); if (trx == NULL) return -ENODEV; - pinst = trx_phy_instance(trx); - l1h = pinst->u.osmotrx.hdl; - - return trx_sched_ul_burst(&l1h->l1s, bi); + return trx_sched_ul_burst(trx->ts[bi->tn].priv, bi); } /*! maximum number of 'missed' frame periods we can tolerate of OS doesn't schedule us*/ @@ -462,9 +455,9 @@ int trx_sched_clock(struct gsm_bts *bts, uint32_t fn) return 0; } -void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate) +void _sched_act_rach_det(struct gsm_bts_trx *trx, uint8_t tn, uint8_t ss, int activate) { - struct phy_instance *pinst = trx_phy_instance(l1t->trx); + struct phy_instance *pinst = trx_phy_instance(trx); struct trx_l1h *l1h = pinst->u.osmotrx.hdl; if (activate) diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c index 93bbf1977..8479d4c76 100644 --- a/src/osmo-bts-trx/trx_if.c +++ b/src/osmo-bts-trx/trx_if.c @@ -1057,7 +1057,7 @@ static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what) bi._num_pdus++; /* feed received burst into scheduler code */ - trx_sched_route_burst_ind(&bi, &l1h->l1s); + trx_sched_route_burst_ind(l1h->phy_inst->trx, &bi); } while (bi.flags & TRX_BI_F_BATCH_IND); return 0; @@ -1222,7 +1222,7 @@ static void trx_phy_inst_close(struct phy_instance *pinst) struct trx_l1h *l1h = pinst->u.osmotrx.hdl; trx_if_close(l1h); - trx_sched_exit(&l1h->l1s); + trx_sched_clean(pinst->trx); } /*! open the control + burst data sockets for one phy_instance */ @@ -1235,11 +1235,7 @@ static int trx_phy_inst_open(struct phy_instance *pinst) if (!l1h) return -EINVAL; - rc = trx_sched_init(&l1h->l1s, pinst->trx); - if (rc < 0) { - LOGPPHI(l1h->phy_inst, DL1C, LOGL_FATAL, "Cannot initialize scheduler\n"); - return -EIO; - } + trx_sched_init(pinst->trx); rc = trx_if_open(l1h); if (rc < 0) { diff --git a/src/osmo-bts-virtual/bts_model.c b/src/osmo-bts-virtual/bts_model.c index e7b0f81b4..af8a6f2a1 100644 --- a/src/osmo-bts-virtual/bts_model.c +++ b/src/osmo-bts-virtual/bts_model.c @@ -100,11 +100,7 @@ static uint8_t vbts_set_trx(struct gsm_bts_trx *trx) static uint8_t vbts_set_ts(struct gsm_bts_trx_ts *ts) { - struct phy_instance *pinst = trx_phy_instance(ts->trx); - int rc; - - rc = trx_sched_set_pchan(&pinst->u.virt.sched, ts->nr, ts->pchan); - if (rc) + if (trx_sched_set_pchan(ts, ts->pchan) != 0) return NM_NACK_RES_NOTAVAIL; return 0; diff --git a/src/osmo-bts-virtual/l1_if.c b/src/osmo-bts-virtual/l1_if.c index 78da639a7..0fbc35dc1 100644 --- a/src/osmo-bts-virtual/l1_if.c +++ b/src/osmo-bts-virtual/l1_if.c @@ -214,7 +214,7 @@ int bts_model_phy_link_open(struct phy_link *plink) /* iterate over list of PHY instances and initialize the scheduler */ llist_for_each_entry(pinst, &plink->instances, list) { - trx_sched_init(&pinst->u.virt.sched, pinst->trx); + trx_sched_init(pinst->trx); /* Only start the scheduler for the transceiver on C0. * If we have multiple transceivers, CCCH is always on C0 * and has to be auto active */ @@ -244,28 +244,19 @@ int bts_model_phy_link_open(struct phy_link *plink) /* enable ciphering */ static int l1if_set_ciphering(struct gsm_lchan *lchan, uint8_t chan_nr, int downlink) { - struct gsm_bts_trx *trx = lchan->ts->trx; - struct phy_instance *pinst = trx_phy_instance(trx); - struct l1sched_trx *sched = &pinst->u.virt.sched; - /* ciphering already enabled in both directions */ if (lchan->ciph_state == LCHAN_CIPH_RXTX_CONF) return -EINVAL; if (!downlink) { /* set uplink */ - trx_sched_set_cipher(sched, chan_nr, 0, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); + trx_sched_set_cipher(lchan, chan_nr, false); lchan->ciph_state = LCHAN_CIPH_RX_CONF; } else { /* set downlink and also set uplink, if not already */ - if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) { - trx_sched_set_cipher(sched, chan_nr, 0, - lchan->encr.alg_id - 1, lchan->encr.key, - lchan->encr.key_len); - } - trx_sched_set_cipher(sched, chan_nr, 1, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); + if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) + trx_sched_set_cipher(lchan, chan_nr, false); + trx_sched_set_cipher(lchan, chan_nr, true); lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; } @@ -341,8 +332,6 @@ static int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t f /* primitive from common part */ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct l1sched_trx *sched = &pinst->u.virt.sched; struct msgb *msg = l1sap->oph.msg; uint8_t chan_nr; uint8_t tn, ss; @@ -354,12 +343,12 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) if (!msg) break; /* put data into scheduler's queue */ - return trx_sched_ph_data_req(sched, l1sap); + return trx_sched_ph_data_req(trx, l1sap); case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): if (!msg) break; /* put data into scheduler's queue */ - return trx_sched_tch_req(sched, l1sap); + return trx_sched_tch_req(trx, l1sap); case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): switch (l1sap->u.info.type) { case PRIM_INFO_ACT_CIPH: @@ -388,11 +377,11 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) break; } /* activate dedicated channel */ - trx_sched_set_lchan(sched, chan_nr, LID_DEDIC, true); + trx_sched_set_lchan(lchan, chan_nr, LID_DEDIC, true); /* activate associated channel */ - trx_sched_set_lchan(sched, chan_nr, LID_SACCH, true); + trx_sched_set_lchan(lchan, chan_nr, LID_SACCH, true); /* set mode */ - trx_sched_set_mode(sched, chan_nr, + trx_sched_set_mode(lchan->ts, chan_nr, lchan->rsl_cmode, lchan->tch_mode, lchan->tch.amr_mr.num_modes, lchan->tch.amr_mr.bts_mode[0].mode, @@ -420,7 +409,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) } if (l1sap->u.info.type == PRIM_INFO_MODIFY) { /* change mode */ - trx_sched_set_mode(sched, chan_nr, + trx_sched_set_mode(lchan->ts, chan_nr, lchan->rsl_cmode, lchan->tch_mode, lchan->tch.amr_mr.num_modes, lchan->tch.amr_mr.bts_mode[0].mode, @@ -437,12 +426,12 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) break; } /* deactivate associated channel */ - trx_sched_set_lchan(sched, chan_nr, LID_SACCH, false); + trx_sched_set_lchan(lchan, chan_nr, LID_SACCH, false); if (!l1sap->u.info.u.act_req.sacch_only) { /* set lchan inactive */ lchan_set_state(lchan, LCHAN_S_NONE); /* deactivate dedicated channel */ - trx_sched_set_lchan(sched, chan_nr, LID_DEDIC, false); + trx_sched_set_lchan(lchan, chan_nr, LID_DEDIC, false); /* confirm only on dedicated channel */ mph_info_chan_confirm(trx, chan_nr, PRIM_INFO_DEACTIVATE, 0); diff --git a/src/osmo-bts-virtual/l1_if.h b/src/osmo-bts-virtual/l1_if.h index 075856f12..c55e2d383 100644 --- a/src/osmo-bts-virtual/l1_if.h +++ b/src/osmo-bts-virtual/l1_if.h @@ -14,7 +14,6 @@ struct bts_virt_priv { struct vbts_l1h { struct gsm_bts_trx *trx; - struct l1sched_trx l1s; struct virt_um_inst *virt_um; }; diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c index bbc2c4e97..4beb96665 100644 --- a/src/osmo-bts-virtual/scheduler_virtbts.c +++ b/src/osmo-bts-virtual/scheduler_virtbts.c @@ -2,6 +2,7 @@ /* (C) 2015-2017 by Harald Welte * (C) 2017 Sebastian Stumpf + * Contributions by sysmocom - s.f.m.c. GmbH * * All Rights Reserved * @@ -51,13 +52,14 @@ * Send a message over the virtual um interface. * This will at first wrap the msg with a GSMTAP header and then write it to the declared multicast socket. */ -static void _tx_to_virt_um(struct l1sched_trx *l1t, +static void _tx_to_virt_um(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br, struct msgb *msg, bool is_voice_frame) { const struct trx_chan_desc *chdesc = &trx_chan_desc[br->chan]; + const struct gsm_bts_trx *trx = l1ts->ts->trx; struct msgb *outmsg; /* msg to send with gsmtap header prepended */ - uint16_t arfcn = l1t->trx->arfcn; /* ARFCN of the transceiver the message is send with */ + uint16_t arfcn = trx->arfcn; /* ARFCN of the transceiver the message is send with */ uint8_t signal_dbm = 63; /* signal strength, 63 is best */ uint8_t snr = 63; /* signal noise ratio, 63 is best */ uint8_t *data = msgb_l2(msg); /* data to transmit (whole message without l1 header) */ @@ -73,13 +75,13 @@ static void _tx_to_virt_um(struct l1sched_trx *l1t, /* in Osmocom, AGCH is only sent on ccch block 0. no idea why. this seems to cause false GSMTAP channel * types for agch and pch. */ if (rsl_chantype == RSL_CHAN_PCH_AGCH && - l1sap_fn2ccch_block(br->fn) >= num_agch(l1t->trx, "PH-DATA-REQ")) + l1sap_fn2ccch_block(br->fn) >= num_agch(trx, "PH-DATA-REQ")) gsmtap_chantype = GSMTAP_CHANNEL_PCH; else gsmtap_chantype = chantype_rsl2gsmtap2(rsl_chantype, chdesc->link_id, is_voice_frame); /* the logical channel type */ if (gsmtap_chantype == GSMTAP_CHANNEL_UNKNOWN) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Tx GSMTAP for RSL channel type 0x%02x: cannot send, this" + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Tx GSMTAP for RSL channel type 0x%02x: cannot send, this" " channel type is unknown in GSMTAP\n", rsl_chantype); msgb_free(msg); return; @@ -93,44 +95,42 @@ static void _tx_to_virt_um(struct l1sched_trx *l1t, outmsg = gsmtap_makemsg(arfcn, timeslot, gsmtap_chantype, subslot, br->fn, signal_dbm, snr, data, data_len); if (outmsg) { - struct phy_instance *pinst = trx_phy_instance(l1t->trx); + struct phy_instance *pinst = trx_phy_instance(trx); int rc; rc = virt_um_write_msg(pinst->phy_link->u.virt.virt_um, outmsg); if (rc < 0) - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "GSMTAP msg could not send to virtual Um: %s\n", strerror(-rc)); else if (rc == 0) - bts_shutdown(l1t->trx->bts, "VirtPHY write socket died\n"); + bts_shutdown(trx->bts, "VirtPHY write socket died\n"); else - LOGL1SB(DL1P, LOGL_DEBUG, l1t, br, + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Sending GSMTAP message to virtual Um\n"); } else - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "GSMTAP msg could not be created!\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "GSMTAP msg could not be created!\n"); /* free incoming message */ msgb_free(msg); } -static void tx_to_virt_um(struct l1sched_trx *l1t, +static void tx_to_virt_um(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br, struct msgb *msg) { - _tx_to_virt_um(l1t, br, msg, false); + _tx_to_virt_um(l1ts, br, msg, false); } -static struct gsm_lchan *lchan_from_l1t(struct l1sched_trx *l1t, uint8_t tn, enum trx_chan_type chan) +static struct gsm_lchan *lchan_from_l1t(const struct l1sched_ts *l1ts, + const enum trx_chan_type chan) { - struct gsm_bts_trx_ts *ts; + struct gsm_bts_trx_ts *ts = l1ts->ts; uint8_t subslot = 0; - OSMO_ASSERT(l1t && l1t->trx); - if (chan == TRXC_TCHH_1) subslot = 1; - ts = &l1t->trx->ts[tn]; return &ts->lchan[subslot]; } @@ -152,11 +152,11 @@ static int get_um_voice_type(const struct gsm_lchan *lchan) } } -static void tx_to_virt_um_voice_frame(struct l1sched_trx *l1t, +static void tx_to_virt_um_voice_frame(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br, struct msgb *msg) { - struct gsm_lchan *lchan = lchan_from_l1t(l1t, br->tn, br->chan); + struct gsm_lchan *lchan = lchan_from_l1t(l1ts, br->chan); int um_voice_type; OSMO_ASSERT(lchan); @@ -170,7 +170,7 @@ static void tx_to_virt_um_voice_frame(struct l1sched_trx *l1t, msgb_pull_to_l2(msg); msgb_push_u8(msg, um_voice_type); msg->l2h = msg->data; - _tx_to_virt_um(l1t, br, msg, true); + _tx_to_virt_um(l1ts, br, msg, true); } /* @@ -178,22 +178,22 @@ static void tx_to_virt_um_voice_frame(struct l1sched_trx *l1t, */ /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */ -int tx_idle_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_idle_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { return 0; } -int tx_fcch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_fcch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { return 0; } -int tx_sch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_sch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { return 0; } -int tx_data_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_data_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg; @@ -201,15 +201,15 @@ int tx_data_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) return 0; /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, br); + msg = _sched_dequeue_prim(l1ts, br); if (!msg) { - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "has not been served !! No prim\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "has not been served !! No prim\n"); return -ENODEV; } /* check validity of message */ if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "Prim not 23 bytes, please FIX! (len=%d)\n", + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim not 23 bytes, please FIX! (len=%d)\n", msgb_l2len(msg)); /* free message */ msgb_free(msg); @@ -217,12 +217,12 @@ int tx_data_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) } /* transmit the msg received on dl from bsc to layer1 (virt Um) */ - tx_to_virt_um(l1t, br, msg); + tx_to_virt_um(l1ts, br, msg); return 0; } -int tx_pdtch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_pdtch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg = NULL; /* make GCC happy */ @@ -230,23 +230,22 @@ int tx_pdtch_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) return 0; /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, br); + msg = _sched_dequeue_prim(l1ts, br); if (!msg) { - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "has not been served !! No prim\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "has not been served !! No prim\n"); return -ENODEV; } - tx_to_virt_um(l1t, br, msg); + tx_to_virt_um(l1ts, br, msg); return 0; } -static void tx_tch_common(struct l1sched_trx *l1t, +static void tx_tch_common(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br, struct msgb **_msg_tch, struct msgb **_msg_facch, int codec_mode_request) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL; struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan]; uint8_t rsl_cmode = chan_state->rsl_cmode; @@ -259,7 +258,7 @@ static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tch_data[GSM_FR_BYTES]; int len; - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, "Missing TCH bursts detected, sending " + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Missing TCH bursts detected, sending " "BFI for %s\n", trx_chan_desc[br->chan].name); /* indicate bad frame */ @@ -287,7 +286,7 @@ static void tx_tch_common(struct l1sched_trx *l1t, if (len < 2) break; memset(tch_data + 2, 0, len - 2); - _sched_compose_tch_ind(l1t, br->tn, 0, br->chan, tch_data, len); + _sched_compose_tch_ind(l1ts, 0, br->chan, tch_data, len); break; default: inval_mode1: @@ -296,13 +295,13 @@ inval_mode1: len = 0; } if (len) - _sched_compose_tch_ind(l1t, br->tn, 0, br->chan, tch_data, len); + _sched_compose_tch_ind(l1ts, 0, br->chan, tch_data, len); } #endif /* get frame and unlink from queue */ - msg1 = _sched_dequeue_prim(l1t, br); - msg2 = _sched_dequeue_prim(l1t, br); + msg1 = _sched_dequeue_prim(l1ts, br); + msg2 = _sched_dequeue_prim(l1ts, br); if (msg1) { l1sap = msgb_l1sap_prim(msg1); if (l1sap->oph.primitive == PRIM_TCH) { @@ -310,7 +309,7 @@ inval_mode1: if (msg2) { l1sap = msgb_l1sap_prim(msg2); if (l1sap->oph.primitive == PRIM_TCH) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "TCH twice, please FIX!\n"); msgb_free(msg2); } else @@ -321,7 +320,7 @@ inval_mode1: if (msg2) { l1sap = msgb_l1sap_prim(msg2); if (l1sap->oph.primitive != PRIM_TCH) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "FACCH twice, please FIX!\n"); msgb_free(msg2); } else @@ -338,7 +337,7 @@ inval_mode1: /* check validity of message */ if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) { - LOGL1SB(DL1P, LOGL_FATAL, l1t, br, "Prim has odd len=%u != %u\n", + LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != %u\n", msgb_l2len(msg_facch), GSM_MACBLOCK_LEN); /* free message */ msgb_free(msg_facch); @@ -354,7 +353,7 @@ inval_mode1: #endif if (rsl_cmode != RSL_CMOD_SPD_SPEECH) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, "Dropping speech frame, " + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Dropping speech frame, " "because we are not in speech mode\n"); goto free_bad_msg; } @@ -365,7 +364,7 @@ inval_mode1: len = 15; if (msgb_l2len(msg_tch) >= 1 && (msg_tch->l2h[0] & 0xf0) != 0x00) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Transmitting 'bad HR frame'\n"); goto free_bad_msg; } @@ -374,7 +373,7 @@ inval_mode1: len = GSM_FR_BYTES; if (msgb_l2len(msg_tch) >= 1 && (msg_tch->l2h[0] >> 4) != 0xd) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Transmitting 'bad FR frame'\n"); goto free_bad_msg; } @@ -385,7 +384,7 @@ inval_mode1: len = GSM_EFR_BYTES; if (msgb_l2len(msg_tch) >= 1 && (msg_tch->l2h[0] >> 4) != 0xc) { - LOGL1SB(DL1P, LOGL_NOTICE, l1t, br, + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Transmitting 'bad EFR frame'\n"); goto free_bad_msg; } @@ -396,15 +395,15 @@ inval_mode1: break; default: inval_mode2: - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "TCH mode invalid, please fix!\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, please fix!\n"); goto free_bad_msg; } if (len < 0) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Cannot send invalid AMR payload\n"); + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send invalid AMR payload\n"); goto free_bad_msg; } if (msgb_l2len(msg_tch) != len) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Cannot send payload with " + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send payload with " "invalid length! (expecing %d, received %d)\n", len, msgb_l2len(msg_tch)); free_bad_msg: /* free message */ @@ -419,34 +418,33 @@ send_frame: *_msg_facch = msg_facch; } -int tx_tchf_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_tchf_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; if (br->bid > 0) return 0; - tx_tch_common(l1t, br, &msg_tch, &msg_facch, (((br->fn + 4) % 26) >> 2) & 1); + tx_tch_common(l1ts, br, &msg_tch, &msg_facch, (((br->fn + 4) % 26) >> 2) & 1); /* no message at all */ if (!msg_tch && !msg_facch) { - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "has not been served !! No prim\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "has not been served !! No prim\n"); return -ENODEV; } if (msg_facch) { - tx_to_virt_um(l1t, br, msg_facch); + tx_to_virt_um(l1ts, br, msg_facch); msgb_free(msg_tch); } else if (msg_tch) - tx_to_virt_um_voice_frame(l1t, br, msg_tch); + tx_to_virt_um_voice_frame(l1ts, br, msg_tch); return 0; } -int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) +int tx_tchh_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan]; //uint8_t tch_mode = chan_state->tch_mode; @@ -455,11 +453,11 @@ int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) return 0; /* get TCH and/or FACCH */ - tx_tch_common(l1t, br, &msg_tch, &msg_facch, (((br->fn + 4) % 26) >> 2) & 1); + tx_tch_common(l1ts, br, &msg_tch, &msg_facch, (((br->fn + 4) % 26) >> 2) & 1); /* check for FACCH alignment */ if (msg_facch && ((((br->fn + 4) % 26) >> 2) & 1)) { - LOGL1SB(DL1P, LOGL_ERROR, l1t, br, "Cannot transmit FACCH starting on " + LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot transmit FACCH starting on " "even frames, please fix RTS!\n"); msgb_free(msg_facch); msg_facch = NULL; @@ -467,15 +465,15 @@ int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) /* no message at all */ if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) { - LOGL1SB(DL1P, LOGL_INFO, l1t, br, "has not been served !! No prim\n"); + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "has not been served !! No prim\n"); return -ENODEV; } if (msg_facch) { - tx_to_virt_um(l1t, br, msg_facch); + tx_to_virt_um(l1ts, br, msg_facch); msgb_free(msg_tch); } else if (msg_tch) - tx_to_virt_um_voice_frame(l1t, br, msg_tch); + tx_to_virt_um_voice_frame(l1ts, br, msg_tch); return 0; } @@ -489,33 +487,33 @@ int tx_tchh_fn(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) * directly into the L1SAP, bypassing the TDMA multiplex logic oriented * towards receiving bursts */ -int rx_rach_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_rach_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { return 0; } /*! \brief a single burst was received by the PHY, process it */ -int rx_data_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { return 0; } -int rx_pdtch_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_pdtch_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { return 0; } -int rx_tchf_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { return 0; } -int rx_tchh_fn(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi) +int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { return 0; } -void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate) +void _sched_act_rach_det(struct gsm_bts_trx *trx, uint8_t tn, uint8_t ss, int activate) { } @@ -536,12 +534,11 @@ static int vbts_sched_fn(struct gsm_bts *bts, uint32_t fn) /* advance the frame number? */ llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct l1sched_trx *l1t = &pinst->u.virt.sched; struct trx_dl_burst_req br = { .fn = fn }; /* do for each of the 8 timeslots */ - for (br.tn = 0; br.tn < ARRAY_SIZE(l1t->ts); br.tn++) { + for (br.tn = 0; br.tn < ARRAY_SIZE(trx->ts); br.tn++) { + struct l1sched_ts *l1ts = trx->ts[br.tn].priv; /* Generate RTS indication to higher layers */ /* This will basically do 2 things (check l1_if:bts_model_l1sap_down): * 1) Get pending messages from layer 2 (from the lapdm queue) @@ -549,13 +546,13 @@ static int vbts_sched_fn(struct gsm_bts *bts, uint32_t fn) * --> Handle and process non-transparent RSL-Messages (activate channel, ) * --> Forward transparent RSL-DATA-Messages to the ms by appending them to * the l1-dl-queue */ - _sched_rts(l1t, br.tn, GSM_TDMA_FN_SUM(fn, RTS_ADVANCE)); + _sched_rts(l1ts, GSM_TDMA_FN_SUM(fn, RTS_ADVANCE)); /* schedule transmit backend functions */ /* Process data in the l1-dlqueue and forward it * to MS */ /* the returned bits are not used here, the routines called will directly forward their * bits to the virt Um */ - _sched_dl_burst(l1t, &br); + _sched_dl_burst(l1ts, &br); } }