diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2021-05-27 21:51:44 +0200 |
---|---|---|
committer | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2021-06-05 00:34:36 +0200 |
commit | 6d20a49806d50a2ef2fbf72b9c32cd3a216cd604 (patch) | |
tree | e94986731d7e0ee626df9e68e83ff911331924f8 | |
parent | 0686ae612834c329546c2f65d04283685ec790ad (diff) |
[VAMOS] osmo-bts-trx: schedule bursts on 'shadow' timeslots
-rw-r--r-- | include/osmo-bts/scheduler.h | 2 | ||||
-rw-r--r-- | src/common/scheduler.c | 61 | ||||
-rw-r--r-- | src/osmo-bts-trx/main.c | 1 | ||||
-rw-r--r-- | src/osmo-bts-trx/scheduler_trx.c | 39 | ||||
-rw-r--r-- | src/osmo-bts-trx/trx_if.c | 8 |
5 files changed, 91 insertions, 20 deletions
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index 90932292..86bfdf91 100644 --- a/include/osmo-bts/scheduler.h +++ b/include/osmo-bts/scheduler.h @@ -71,6 +71,7 @@ enum trx_chan_type { enum trx_mod_type { TRX_MOD_T_GMSK, TRX_MOD_T_8PSK, + TRX_MOD_T_AQPSK, }; /* A set of measurements belonging to one Uplink burst */ @@ -231,6 +232,7 @@ extern const struct trx_sched_multiframe trx_sched_multiframes[]; #define TRX_BI_F_CI_CB (1 << 3) #define TRX_BI_F_TRX_NUM (1 << 4) #define TRX_BI_F_BATCH_IND (1 << 5) +#define TRX_BI_F_SHADOW_IND (1 << 6) /*! UL burst indication with the corresponding meta info */ struct trx_ul_burst_ind { diff --git a/src/common/scheduler.c b/src/common/scheduler.c index eb0aecdc..3ab94a27 100644 --- a/src/common/scheduler.c +++ b/src/common/scheduler.c @@ -606,32 +606,49 @@ static const struct rate_ctr_group_desc l1sched_ts_ctrg_desc = { * init / exit */ +static void trx_sched_init_ts(struct gsm_bts_trx_ts *ts, + const unsigned int rate_ctr_idx) +{ + struct l1sched_ts *l1ts; + unsigned int i; + + l1ts = talloc_zero(ts->trx, struct l1sched_ts); + OSMO_ASSERT(l1ts != NULL); + + /* Link both structures */ + ts->priv = l1ts; + l1ts->ts = ts; + + l1ts->ctrs = rate_ctr_group_alloc(ts->trx, + &l1sched_ts_ctrg_desc, + rate_ctr_idx); + INIT_LLIST_HEAD(&l1ts->dl_prims); + + for (i = 0; i < ARRAY_SIZE(l1ts->chan_state); i++) { + struct l1sched_chan_state *chan_state; + chan_state = &l1ts->chan_state[i]; + chan_state->active = false; + } +} + void trx_sched_init(struct gsm_bts_trx *trx) { - unsigned int tn, i; + unsigned int tn; OSMO_ASSERT(trx != NULL); LOGPTRX(trx, DL1C, LOGL_DEBUG, "Init scheduler structures\n"); - for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { - struct l1sched_ts *l1ts; + /* Allocate shadow timeslots */ + gsm_bts_trx_init_shadow_ts(trx); - l1ts = talloc_zero(trx, struct l1sched_ts); - OSMO_ASSERT(l1ts != NULL); - - 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); - INIT_LLIST_HEAD(&l1ts->dl_prims); + for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { + unsigned int rate_ctr_idx = trx->nr * 100 + tn; + struct gsm_bts_trx_ts *ts = &trx->ts[tn]; - for (i = 0; i < ARRAY_SIZE(l1ts->chan_state); i++) { - struct l1sched_chan_state *chan_state; - chan_state = &l1ts->chan_state[i]; - chan_state->active = false; - } + /* Init primary and shadow timeslots */ + trx_sched_init_ts(ts, rate_ctr_idx); + trx_sched_init_ts(ts->vamos.peer, rate_ctr_idx + 10); } } @@ -999,6 +1016,12 @@ int trx_sched_set_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pch l1ts->mf_index = i; l1ts->mf_period = trx_sched_multiframes[i].period; l1ts->mf_frames = trx_sched_multiframes[i].frames; + if (ts->vamos.peer != NULL) { + l1ts = ts->vamos.peer->priv; + l1ts->mf_index = i; + l1ts->mf_period = trx_sched_multiframes[i].period; + l1ts->mf_frames = trx_sched_multiframes[i].frames; + } LOGP(DL1C, LOGL_NOTICE, "%s Configured multiframe with '%s'\n", gsm_ts_name(ts), trx_sched_multiframes[i].name); return 0; @@ -1423,6 +1446,10 @@ int trx_sched_ul_burst(struct l1sched_ts *l1ts, struct trx_ul_burst_ind *bi) uint8_t offset, period; trx_sched_ul_func *func; + /* VAMOS: redirect to the shadow timeslot */ + if (bi->flags & TRX_BI_F_SHADOW_IND) + l1ts = l1ts->ts->vamos.peer->priv; + if (!l1ts->mf_index) return -EINVAL; diff --git a/src/osmo-bts-trx/main.c b/src/osmo-bts-trx/main.c index 6ec8dfc9..71349397 100644 --- a/src/osmo-bts-trx/main.c +++ b/src/osmo-bts-trx/main.c @@ -146,6 +146,7 @@ int bts_model_init(struct gsm_bts *bts) osmo_bts_set_feature(bts->features, BTS_FEAT_HOPPING); osmo_bts_set_feature(bts->features, BTS_FEAT_ACCH_REP); osmo_bts_set_feature(bts->features, BTS_FEAT_MULTI_TSC); + osmo_bts_set_feature(bts->features, BTS_FEAT_VAMOS); bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MEAS_PAYLOAD_COMB); diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index 4a23f117..1a4f03fa 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -149,6 +149,40 @@ static void bts_sched_flush_buffers(struct gsm_bts *bts) } } +/* schedule one frame for a shadow timeslot, merge bursts */ +static void _sched_dl_shadow_burst(const struct gsm_bts_trx_ts *ts, + struct trx_dl_burst_req *br) +{ + struct l1sched_ts *l1ts = ts->priv; + + /* For the shadow timeslots, physical channel type can be either + * GSM_PCHAN_TCH_{F,H} or GSM_PCHAN_NONE. Even if the primary + * timeslot is a dynamic timeslot, it's always a concrete value. */ + if (ts->pchan == GSM_PCHAN_NONE) + return; + + struct trx_dl_burst_req sbr = { + .trx_num = br->trx_num, + .fn = br->fn, + .tn = br->tn, + }; + + _sched_dl_burst(l1ts, &sbr); + + if (br->burst_len != 0 && sbr.burst_len != 0) { /* Both present */ + memcpy(br->burst + GSM_BURST_LEN, sbr.burst, GSM_BURST_LEN); + br->burst_len = 2 * GSM_BURST_LEN; + br->mod = TRX_MOD_T_AQPSK; + /* FIXME: SCPIR is hard-coded to 0 */ + } else if (br->burst_len == 0) { + /* No primary burst, send shadow burst alone */ + memcpy(br, &sbr, sizeof(sbr)); + } else if (sbr.burst_len == 0) { + /* No shadow burst, send primary burst alone */ + return; + } +} + /* schedule all frames of all TRX for given FN */ static void bts_sched_fn(struct gsm_bts *bts, const uint32_t fn) { @@ -193,8 +227,11 @@ static void bts_sched_fn(struct gsm_bts *bts, const uint32_t fn) br = &pinst->u.osmotrx.br[tn]; } - /* get burst for FN */ + /* get burst for the primary timeslot */ _sched_dl_burst(l1ts, br); + + /* get burst for the shadow timeslot */ + _sched_dl_shadow_burst(ts->vamos.peer, br); } } diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c index afd630f0..968c335e 100644 --- a/src/osmo-bts-trx/trx_if.c +++ b/src/osmo-bts-trx/trx_if.c @@ -755,6 +755,7 @@ static const uint8_t trx_data_rx_hdr_len[] = { static const uint8_t trx_data_mod_val[] = { [TRX_MOD_T_GMSK] = 0x00, /* .00xx... */ [TRX_MOD_T_8PSK] = 0x20, /* .010x... */ + [TRX_MOD_T_AQPSK] = 0x60, /* .11xx... */ }; /* Header dissector for TRXDv0 (and part of TRXDv1) */ @@ -863,9 +864,12 @@ static int trx_data_handle_pdu_v2(struct phy_instance *phy_inst, /* TDMA timeslot number (other bits are RFU) */ bi->tn = buf[0] & 0x07; - /* TRX (RF channel) number and BATCH.ind */ - if (buf[1] & (1 << 7)) + if (buf[1] & (1 << 7)) /* BATCH.ind */ bi->flags |= TRX_BI_F_BATCH_IND; + if (buf[1] & (1 << 6)) /* VAMOS.ind */ + bi->flags |= TRX_BI_F_SHADOW_IND; + + /* TRX (RF channel) number */ bi->trx_num = buf[1] & 0x3f; bi->flags |= TRX_BI_F_TRX_NUM; |