fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/18821 )
Change subject: osmo-bts-trx: introduce and use struct trx_dl_burst_req ...................................................................... osmo-bts-trx: introduce and use struct trx_dl_burst_req This change is similar to what we did for Uplink bursts: - group all Downlink burst parameters into a single structure, - allocate it once and pass a pointer to lchan handlers, - pass a pointer to trx_if_send_burst(). Given that the structure is allocated and (zero-)initialized in trx_sched_fn(), we can get rid of some memset() calls in lchan handlers and thus improve the overall performance a bit. Change-Id: If3014e69746559963569b77561dbf7b163c68ffa --- M include/osmo-bts/scheduler.h M include/osmo-bts/scheduler_backend.h M src/common/scheduler.c M src/osmo-bts-trx/sched_lchan_fcch_sch.c M src/osmo-bts-trx/sched_lchan_pdtch.c M src/osmo-bts-trx/sched_lchan_tchf.c M src/osmo-bts-trx/sched_lchan_tchh.c M src/osmo-bts-trx/sched_lchan_xcch.c M src/osmo-bts-trx/scheduler_trx.c M src/osmo-bts-trx/trx_if.c M src/osmo-bts-trx/trx_if.h M src/osmo-bts-virtual/scheduler_virtbts.c 12 files changed, 214 insertions(+), 241 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/21/18821/1 diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index 74102f3..a7bc6c7 100644 --- a/include/osmo-bts/scheduler.h +++ b/include/osmo-bts/scheduler.h @@ -250,6 +250,17 @@ size_t burst_len; }; +/*! DL burst request with the corresponding meta info */ +struct trx_dl_burst_req { + uint32_t fn; /*!< TDMA frame number */ + uint8_t tn; /*!< TDMA timeslot number */ + uint8_t att; /*!< Tx power attenuation */ + + /*! Burst hard-bits buffer */ + ubit_t burst[EGPRS_BURST_LEN]; + size_t burst_len; +}; + /*! Handle an UL burst received by PHY */ int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi); diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h index cfbe7f2..be23c47 100644 --- a/include/osmo-bts/scheduler_backend.h +++ b/include/osmo-bts/scheduler_backend.h @@ -9,9 +9,8 @@ typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, enum trx_chan_type chan); -typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn, - uint32_t fn, enum trx_chan_type chan, - uint8_t bid, uint16_t *nbits); +typedef int trx_sched_dl_func(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); typedef int trx_sched_ul_func(struct l1sched_trx *l1t, enum trx_chan_type chan, uint8_t bid, const struct trx_ul_burst_ind *bi); @@ -56,20 +55,21 @@ int16_t ta_offs_256bits, uint16_t ber10k, float rssi, uint8_t is_sub); -ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); -ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); -ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); -ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); -ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); -ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); -ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits); +int tx_idle_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); +int tx_fcch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); +int tx_sch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); +int tx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); +int tx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); +int tx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); +int tx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br); + int rx_rach_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, uint8_t bid, const struct trx_ul_burst_ind *bi); int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, @@ -81,7 +81,6 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, uint8_t bid, const struct trx_ul_burst_ind *bi); -const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, - uint32_t fn, uint16_t *nbits); +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); diff --git a/src/common/scheduler.c b/src/common/scheduler.c index 021a4cd..ed6c623 100644 --- a/src/common/scheduler.c +++ b/src/common/scheduler.c @@ -1154,23 +1154,21 @@ } /* process downlink burst */ -const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, - uint32_t fn, uint16_t *nbits) +void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); + struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); struct l1sched_chan_state *l1cs; const struct trx_sched_frame *frame; uint8_t offset, period, bid; trx_sched_dl_func *func; enum trx_chan_type chan; - ubit_t *bits = NULL; if (!l1ts->mf_index) goto no_data; /* get frame from multiframe */ period = l1ts->mf_period; - offset = fn % period; + offset = br->fn % period; frame = l1ts->mf_frames + offset; chan = frame->dl_chan; @@ -1180,42 +1178,37 @@ l1cs = &l1ts->chan_state[chan]; /* check if channel is active */ - if (!TRX_CHAN_IS_ACTIVE(l1cs, chan)) { - if (nbits) - *nbits = GSM_BURST_LEN; + if (!TRX_CHAN_IS_ACTIVE(l1cs, chan)) goto no_data; - } /* get burst from function */ - bits = func(l1t, tn, fn, chan, bid, nbits); + if (func(l1t, chan, bid, br) != 0) + goto no_data; /* encrypt */ - if (bits && l1cs->dl_encr_algo) { + if (br->burst_len && l1cs->dl_encr_algo) { ubit_t ks[114]; int i; - osmo_a5(l1cs->dl_encr_algo, l1cs->dl_encr_key, fn, ks, NULL); + osmo_a5(l1cs->dl_encr_algo, l1cs->dl_encr_key, br->fn, ks, NULL); for (i = 0; i < 57; i++) { - bits[i + 3] ^= ks[i]; - bits[i + 88] ^= ks[i + 57]; + br->burst[i + 3] ^= ks[i]; + br->burst[i + 88] ^= ks[i + 57]; } } no_data: /* in case of C0, we need a dummy burst to maintain RF power */ - if (bits == NULL && l1t->trx == l1t->trx->bts->c0) { + if (!br->burst_len && l1t->trx == l1t->trx->bts->c0) { #if 0 if (chan != TRXC_IDLE) // hack LOGP(DL1C, LOGL_DEBUG, "No burst data for %s fn=%u ts=%u " "burst=%d on C0, so filling with dummy burst\n", trx_chan_desc[chan].name, fn, tn, bid); #endif - bits = (ubit_t *) dummy_burst; - if (nbits) - *nbits = ARRAY_SIZE(dummy_burst); + memcpy(br->burst, dummy_burst, ARRAY_SIZE(dummy_burst)); + br->burst_len = ARRAY_SIZE(dummy_burst); } - - return bits; } #define TDMA_FN_SUM(a, b) \ diff --git a/src/osmo-bts-trx/sched_lchan_fcch_sch.c b/src/osmo-bts-trx/sched_lchan_fcch_sch.c index 63dd468..bc03f81 100644 --- a/src/osmo-bts-trx/sched_lchan_fcch_sch.c +++ b/src/osmo-bts-trx/sched_lchan_fcch_sch.c @@ -35,34 +35,32 @@ #include <sched_utils.h> /* obtain a to-be-transmitted FCCH (frequency correction channel) burst */ -ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_fcch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting FCCH\n"); + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting FCCH\n"); - if (nbits) - *nbits = GSM_BURST_LEN; + memcpy(br->burst, _sched_fcch_burst, GSM_BURST_LEN); + br->burst_len = GSM_BURST_LEN; - /* BURST BYPASS */ - - return (ubit_t *) _sched_fcch_burst; + return 0; } /* obtain a to-be-transmitted SCH (synchronization channel) burst */ -ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_sch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - static ubit_t bits[GSM_BURST_LEN], burst[78]; + ubit_t burst[78]; uint8_t sb_info[4]; struct gsm_time t; uint8_t t3p, bsic; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting SCH\n"); + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting SCH\n"); /* BURST BYPASS */ /* create SB info from GSM time and BSIC */ - gsm_fn2gsmtime(&t, fn); + gsm_fn2gsmtime(&t, br->fn); t3p = t.t3 / 10; bsic = l1t->trx->bts->bsic; sb_info[0] = @@ -81,14 +79,11 @@ gsm0503_sch_encode(burst, sb_info); /* compose burst */ - memset(bits, 0, 3); - memcpy(bits + 3, burst, 39); - memcpy(bits + 42, _sched_sch_train, 64); - memcpy(bits + 106, burst + 39, 39); - memset(bits + 145, 0, 3); + memcpy(br->burst + 3, burst, 39); + memcpy(br->burst + 42, _sched_sch_train, 64); + memcpy(br->burst + 106, burst + 39, 39); - if (nbits) - *nbits = GSM_BURST_LEN; + br->burst_len = GSM_BURST_LEN; - return bits; + return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_pdtch.c b/src/osmo-bts-trx/sched_lchan_pdtch.c index 8b39797..259d336 100644 --- a/src/osmo-bts-trx/sched_lchan_pdtch.c +++ b/src/osmo-bts-trx/sched_lchan_pdtch.c @@ -154,30 +154,29 @@ } /* obtain a to-be-transmitted PDTCH (packet data) burst */ -ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; + 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[chan].dl_bursts; enum trx_burst_type *burst_type = &l1ts->chan_state[chan].dl_burst_type; - static ubit_t bits[EGPRS_BURST_LEN]; int rc = 0; /* send burst, if we already got a frame */ if (bid > 0) { if (!*bursts_p) - return NULL; + return 0; goto send_burst; } /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); + msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan); if (msg) goto got_msg; - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No prim for transmit.\n"); + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No prim for transmit.\n"); no_msg: /* free burst memory */ @@ -185,7 +184,7 @@ talloc_free(*bursts_p); *bursts_p = NULL; } - return NULL; + return -ENODEV; got_msg: /* BURST BYPASS */ @@ -195,7 +194,7 @@ *bursts_p = talloc_zero_size(tall_bts_ctx, GSM0503_EGPRS_BURSTS_NBITS); if (!*bursts_p) - return NULL; + return -ENOMEM; } /* encode bursts */ @@ -205,7 +204,7 @@ /* check validity of message */ if (rc < 0) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim invalid length, please FIX! " + LOGL1S(DL1P, LOGL_FATAL, l1t, br->tn, chan, br->fn, "Prim invalid length, please FIX! " "(len=%ld)\n", (long)(msg->tail - msg->l2h)); /* free message */ msgb_free(msg); @@ -223,27 +222,23 @@ /* compose burst */ if (*burst_type == TRX_BURST_8PSK) { burst = *bursts_p + bid * 348; - memset(bits, 1, 9); - memcpy(bits + 9, burst, 174); - memcpy(bits + 183, _sched_egprs_tsc[gsm_ts_tsc(ts)], 78); - memcpy(bits + 261, burst + 174, 174); - memset(bits + 435, 1, 9); + 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 + 261, burst + 174, 174); + memset(br->burst + 435, 1, 9); - if (nbits) - *nbits = EGPRS_BURST_LEN; + br->burst_len = EGPRS_BURST_LEN; } else { burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); + memcpy(br->burst + 3, burst, 58); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 87, burst + 58, 58); - if (nbits) - *nbits = GSM_BURST_LEN; + br->burst_len = GSM_BURST_LEN; } - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid); - return bits; + return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c index fb11f45..80115a9 100644 --- a/src/osmo-bts-trx/sched_lchan_tchf.c +++ b/src/osmo-bts-trx/sched_lchan_tchf.c @@ -491,25 +491,24 @@ } /* obtain a to-be-transmitted TCH/F (Full Traffic Channel) burst */ -ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; + 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[chan]; uint8_t tch_mode = chan_state->tch_mode; ubit_t *burst, **bursts_p = &chan_state->dl_bursts; - static ubit_t bits[GSM_BURST_LEN]; /* send burst, if we already got a frame */ if (bid > 0) { if (!*bursts_p) - return NULL; + return 0; goto send_burst; } - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch); + tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch); /* BURST BYPASS */ @@ -518,7 +517,7 @@ if (!*bursts_p) { *bursts_p = talloc_zero_size(tall_bts_ctx, 928); if (!*bursts_p) - return NULL; + return -ENOMEM; } else { memcpy(*bursts_p, *bursts_p + 464, 464); memset(*bursts_p + 464, 0, 464); @@ -526,7 +525,7 @@ /* no message at all */ if (!msg_tch && !msg_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No TCH or FACCH prim for transmit.\n"); + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No TCH or FACCH prim for transmit.\n"); goto send_burst; } @@ -539,7 +538,7 @@ * the first FN 0,8,17 defines that CMR is included in frame. */ gsm0503_tch_afs_encode(*bursts_p, msg_tch->l2h + 2, - msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(fn), + msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn), chan_state->codec, chan_state->codecs, chan_state->dl_ft, chan_state->dl_cmr); @@ -555,16 +554,13 @@ send_burst: /* compose burst */ burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); + memcpy(br->burst + 3, burst, 58); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 87, burst + 58, 58); - if (nbits) - *nbits = GSM_BURST_LEN; + br->burst_len = GSM_BURST_LEN; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid); - return bits; + return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c index 1895038..8adaec3 100644 --- a/src/osmo-bts-trx/sched_lchan_tchh.c +++ b/src/osmo-bts-trx/sched_lchan_tchh.c @@ -313,30 +313,29 @@ struct msgb **_msg_tch, struct msgb **_msg_facch); /* obtain a to-be-transmitted TCH/H (Half Traffic Channel) burst */ -ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; + 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[chan]; uint8_t tch_mode = chan_state->tch_mode; ubit_t *burst, **bursts_p = &chan_state->dl_bursts; - static ubit_t bits[GSM_BURST_LEN]; /* send burst, if we already got a frame */ if (bid > 0) { if (!*bursts_p) - return NULL; + return 0; goto send_burst; } /* get TCH and/or FACCH */ - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch); + tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch); /* check for FACCH alignment */ - if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot transmit FACCH starting on " + if (msg_facch && ((((br->fn + 4) % 26) >> 2) & 1)) { + LOGL1S(DL1P, LOGL_ERROR, l1t, br->tn, chan, br->fn, "Cannot transmit FACCH starting on " "even frames, please fix RTS!\n"); msgb_free(msg_facch); msg_facch = NULL; @@ -349,7 +348,7 @@ if (!*bursts_p) { *bursts_p = talloc_zero_size(tall_bts_ctx, 696); if (!*bursts_p) - return NULL; + return -ENOMEM; } else { memcpy(*bursts_p, *bursts_p + 232, 232); if (chan_state->dl_ongoing_facch) { @@ -362,7 +361,7 @@ /* no message at all */ if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No TCH or FACCH prim for transmit.\n"); + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No TCH or FACCH prim for transmit.\n"); goto send_burst; } @@ -377,7 +376,7 @@ * in frame, the first FN 0,8,17 or 1,9,18 defines that CMR is * included in frame. */ gsm0503_tch_ahs_encode(*bursts_p, msg_tch->l2h + 2, - msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(fn), + msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn), chan_state->codec, chan_state->codecs, chan_state->dl_ft, chan_state->dl_cmr); @@ -393,16 +392,13 @@ send_burst: /* compose burst */ burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); + memcpy(br->burst + 3, burst, 58); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 87, burst + 58, 58); - if (nbits) - *nbits = GSM_BURST_LEN; + br->burst_len = GSM_BURST_LEN; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid); - return bits; + return 0; } diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c b/src/osmo-bts-trx/sched_lchan_xcch.c index a16553f..e2670d8 100644 --- a/src/osmo-bts-trx/sched_lchan_xcch.c +++ b/src/osmo-bts-trx/sched_lchan_xcch.c @@ -145,28 +145,27 @@ } /* obtain a to-be-transmitted xCCH (e.g SACCH or SDCCH) burst */ -ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; + 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[chan].dl_bursts; - static ubit_t bits[GSM_BURST_LEN]; /* send burst, if we already got a frame */ if (bid > 0) { if (!*bursts_p) - return NULL; + return 0; goto send_burst; } /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); + msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan); if (msg) goto got_msg; - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No prim for transmit.\n"); + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "No prim for transmit.\n"); no_msg: /* free burst memory */ @@ -174,12 +173,12 @@ talloc_free(*bursts_p); *bursts_p = NULL; } - return NULL; + return -ENODEV; got_msg: /* check validity of message */ if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! " + LOGL1S(DL1P, LOGL_FATAL, l1t, br->tn, chan, br->fn, "Prim not 23 bytes, please FIX! " "(len=%d)\n", msgb_l2len(msg)); /* free message */ msgb_free(msg); @@ -197,7 +196,7 @@ /* 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, tn, 0, chan, NULL, 0, + _sched_compose_ph_data_ind(l1t, br->tn, 0, chan, NULL, 0, 0, 0, 0, 10000, PRES_INFO_INVALID); } @@ -207,7 +206,7 @@ if (!*bursts_p) { *bursts_p = talloc_zero_size(tall_bts_ctx, 464); if (!*bursts_p) - return NULL; + return -ENOMEM; } /* encode bursts */ @@ -219,16 +218,13 @@ send_burst: /* compose burst */ burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); + memcpy(br->burst + 3, burst, 58); + memcpy(br->burst + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); + memcpy(br->burst + 87, burst + 58, 58); - if (nbits) - *nbits = GSM_BURST_LEN; + br->burst_len = GSM_BURST_LEN; - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting burst=%u.\n", bid); - return bits; + return 0; } diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index 4fb0e23..6996593 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -48,25 +48,19 @@ #include "trx_if.h" /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */ -ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_idle_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting IDLE\n"); - - if (nbits) - *nbits = GSM_BURST_LEN; - - return NULL; + LOGL1S(DL1P, LOGL_DEBUG, l1t, br->tn, chan, br->fn, "Transmitting IDLE\n"); + return 0; } /* schedule all frames of all TRX for given FN */ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn) { + struct trx_dl_burst_req br; struct gsm_bts_trx *trx; uint8_t tn; - const ubit_t *bits; - uint8_t gain; - uint16_t nbits = 0; /* send time indication */ l1if_mph_time_ind(bts, fn); @@ -91,15 +85,21 @@ /* ready-to-send */ _sched_rts(l1t, tn, (fn + plink->u.osmotrx.rts_advance) % GSM_HYPERFRAME); + + /* TODO: Tx attenuation is always 0? */ + br = (struct trx_dl_burst_req) { + .fn = fn, .tn = tn, + .att = 0, + }; + /* get burst for FN */ - bits = _sched_dl_burst(l1t, tn, fn, &nbits); - if (!bits) { + _sched_dl_burst(l1t, &br); + if (br.burst_len == 0) { /* if no bits, send no burst */ continue; - } else - gain = 0; - if (nbits) - trx_if_send_burst(l1h, tn, fn, gain, bits, nbits); + } + + trx_if_send_burst(l1h, &br); } } diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c index ccbcd2f..1953f71 100644 --- a/src/osmo-bts-trx/trx_if.c +++ b/src/osmo-bts-trx/trx_if.c @@ -1101,27 +1101,23 @@ /*! Send burst data for given FN/timeslot to TRX * \param[inout] l1h TRX Layer1 handle referring to TX - * \param[in] tn Timeslot Number (0..7) - * \param[in] fn GSM Frame Number - * \param[in] pwr Transmit Power to use - * \param[in] bits Unpacked bits to be transmitted - * \param[in] nbits Number of \a bits + * \param[in] br Downlink burst request structure * \returns 0 on success; negative on error */ -int trx_if_send_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr, - const ubit_t *bits, uint16_t nbits) +int trx_if_send_burst(struct trx_l1h *l1h, const struct trx_dl_burst_req *br) { ssize_t snd_len; uint8_t hdr_ver = l1h->config.trxd_hdr_ver_use; uint8_t buf[TRX_DATA_MSG_MAX_LEN]; - if ((nbits != GSM_BURST_LEN) && (nbits != EGPRS_BURST_LEN)) { - LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, "Tx burst length %u invalid\n", nbits); + if ((br->burst_len != GSM_BURST_LEN) && (br->burst_len != EGPRS_BURST_LEN)) { + LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, "Tx burst length %zu invalid\n", + br->burst_len); return -1; } LOGPPHI(l1h->phy_inst, DTRX, LOGL_DEBUG, - "Tx burst (hdr_ver=%u): tn=%u fn=%u pwr=%u\n", - hdr_ver, tn, fn, pwr); + "Tx burst (hdr_ver=%u): tn=%u fn=%u att=%u\n", + hdr_ver, br->tn, br->fn, br->att); switch (hdr_ver) { case 0: @@ -1135,16 +1131,16 @@ return -ENOTSUP; } - buf[0] = ((hdr_ver & 0x0f) << 4) | tn; - osmo_store32be(fn, buf + 1); - buf[5] = pwr; + buf[0] = ((hdr_ver & 0x0f) << 4) | br->tn; + osmo_store32be(br->fn, buf + 1); + buf[5] = br->att; /* copy ubits {0,1} */ - memcpy(buf + 6, bits, nbits); + memcpy(buf + 6, br->burst, br->burst_len); /* we must be sure that TRX is on */ if (trx_if_powered(l1h)) { - snd_len = send(l1h->trx_ofd_data.fd, buf, nbits + 6, 0); + snd_len = send(l1h->trx_ofd_data.fd, buf, br->burst_len + 6, 0); if (snd_len <= 0) { strerror_r(errno, (char *)buf, sizeof(buf)); LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h index 34335f8..16b6c76 100644 --- a/src/osmo-bts-trx/trx_if.h +++ b/src/osmo-bts-trx/trx_if.h @@ -1,6 +1,7 @@ #ifndef TRX_IF_H #define TRX_IF_H +struct trx_dl_burst_req; struct trx_l1h; struct trx_ctrl_msg { @@ -33,8 +34,7 @@ int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn); int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss); int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss); -int trx_if_send_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr, - const ubit_t *bits, uint16_t nbits); +int trx_if_send_burst(struct trx_l1h *l1h, const struct trx_dl_burst_req *br); int trx_if_powered(struct trx_l1h *l1h); /* The latest supported TRXD header format version */ diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c index eabd23b..d3fdf1a 100644 --- a/src/osmo-bts-virtual/scheduler_virtbts.c +++ b/src/osmo-bts-virtual/scheduler_virtbts.c @@ -173,72 +173,72 @@ */ /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */ -ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_idle_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - return NULL; + return 0; } -ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_fcch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - return NULL; + return 0; } -ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_sch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { - return NULL; + return 0; } -ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { struct msgb *msg; if (bid > 0) - return NULL; + return 0; /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); + msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan); if (!msg) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - return NULL; + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n"); + return -ENODEV; } /* check validity of message */ if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! (len=%d)\n", + LOGL1S(DL1P, LOGL_FATAL, l1t, br->tn, chan, br->fn, "Prim not 23 bytes, please FIX! (len=%d)\n", msgb_l2len(msg)); /* free message */ msgb_free(msg); - return NULL; + return -EINVAL; } /* transmit the msg received on dl from bsc to layer1 (virt Um) */ - tx_to_virt_um(l1t, tn, fn, chan, msg); + tx_to_virt_um(l1t, br->tn, br->fn, chan, msg); - return NULL; + return 0; } -ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { struct msgb *msg = NULL; /* make GCC happy */ if (bid > 0) - return NULL; + return 0; /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); + msg = _sched_dequeue_prim(l1t, br->tn, br->fn, chan); if (!msg) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - return NULL; + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n"); + return -ENODEV; } - tx_to_virt_um(l1t, tn, fn, chan, msg); + tx_to_virt_um(l1t, br->tn, br->fn, chan, msg); - return NULL; + return 0; } static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, @@ -418,53 +418,51 @@ *_msg_facch = msg_facch; } -ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; if (bid > 0) - return NULL; + return 0; - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch, - (((fn + 4) % 26) >> 2) & 1); + tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch, + (((br->fn + 4) % 26) >> 2) & 1); /* no message at all */ if (!msg_tch && !msg_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - goto send_burst; + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n"); + return -ENODEV; } if (msg_facch) { - tx_to_virt_um(l1t, tn, fn, chan, msg_facch); + tx_to_virt_um(l1t, br->tn, br->fn, chan, msg_facch); msgb_free(msg_tch); } else if (msg_tch) - tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch); + tx_to_virt_um_voice_frame(l1t, br->tn, br->fn, chan, msg_tch); -send_burst: - - return NULL; + return 0; } -ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, uint16_t *nbits) +int tx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, + uint8_t bid, struct trx_dl_burst_req *br) { struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); + struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, br->tn); struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; //uint8_t tch_mode = chan_state->tch_mode; /* send burst, if we already got a frame */ if (bid > 0) - return NULL; + return 0; /* get TCH and/or FACCH */ - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch, - (((fn + 4) % 26) >> 2) & 1); + tx_tch_common(l1t, br->tn, br->fn, chan, bid, &msg_tch, &msg_facch, + (((br->fn + 4) % 26) >> 2) & 1); /* check for FACCH alignment */ - if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot transmit FACCH starting on " + if (msg_facch && ((((br->fn + 4) % 26) >> 2) & 1)) { + LOGL1S(DL1P, LOGL_ERROR, l1t, br->tn, chan, br->fn, "Cannot transmit FACCH starting on " "even frames, please fix RTS!\n"); msgb_free(msg_facch); msg_facch = NULL; @@ -472,18 +470,17 @@ /* no message at all */ if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - goto send_burst; + LOGL1S(DL1P, LOGL_INFO, l1t, br->tn, chan, br->fn, "has not been served !! No prim\n"); + return -ENODEV; } if (msg_facch) { - tx_to_virt_um(l1t, tn, fn, chan, msg_facch); + tx_to_virt_um(l1t, br->tn, br->fn, chan, msg_facch); msgb_free(msg_tch); } else if (msg_tch) - tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch); + tx_to_virt_um_voice_frame(l1t, br->tn, br->fn, chan, msg_tch); -send_burst: - return NULL; + return 0; } @@ -550,11 +547,10 @@ 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; - int tn; - uint16_t nbits; + struct trx_dl_burst_req br = { .fn = fn }; /* do for each of the 8 timeslots */ - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { + for (br.tn = 0; br.tn < ARRAY_SIZE(l1t->ts); br.tn++) { /* 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) @@ -562,13 +558,13 @@ * --> 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, tn, (fn + RTS_ADVANCE) % GSM_HYPERFRAME); + _sched_rts(l1t, br.tn, (fn + RTS_ADVANCE) % GSM_HYPERFRAME); /* 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, tn, fn, &nbits); + _sched_dl_burst(l1t, &br); } } -- To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/18821 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bts Gerrit-Branch: master Gerrit-Change-Id: If3014e69746559963569b77561dbf7b163c68ffa Gerrit-Change-Number: 18821 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanits...@sysmocom.de> Gerrit-MessageType: newchange