diff options
Diffstat (limited to 'src/osmo-bts-trx/sched_lchan_xcch.c')
-rw-r--r-- | src/osmo-bts-trx/sched_lchan_xcch.c | 123 |
1 files changed, 39 insertions, 84 deletions
diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c b/src/osmo-bts-trx/sched_lchan_xcch.c index 4bfc101a..0580d33b 100644 --- a/src/osmo-bts-trx/sched_lchan_xcch.c +++ b/src/osmo-bts-trx/sched_lchan_xcch.c @@ -13,7 +13,7 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. @@ -36,23 +36,19 @@ #include <sched_utils.h> /* Add two arrays of sbits */ -static void add_sbits(sbit_t * current, const sbit_t * previous) +static void add_sbits(sbit_t *current, const sbit_t *previous) { - unsigned int i; - for (i = 0; i < 464; i++) { - *current = (*current) / 2 + (*previous) / 2; - current++; - previous++; - } + for (unsigned int i = 0; i < BPLEN * 4; i++) + current[i] = current[i] / 2 + previous[i] / 2; } /*! \brief a single (SDCCH/SACCH) burst was received by the PHY, process it */ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; - sbit_t *burst, **bursts_p = &chan_state->ul_bursts; + sbit_t *burst, *bursts_p = chan_state->ul_bursts; uint32_t *first_fn = &chan_state->ul_first_fn; - uint8_t *mask = &chan_state->ul_mask; + uint32_t *mask = &chan_state->ul_mask; uint8_t l2[GSM_MACBLOCK_LEN], l2_len; struct l1sched_meas_set meas_avg; int n_errors = 0; @@ -60,7 +56,7 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) uint16_t ber10k; int rc; struct gsm_lchan *lchan = chan_state->lchan; - bool rep_sacch = L1SAP_IS_LINK_SACCH(trx_chan_desc[bi->chan].link_id) && lchan->repeated_ul_sacch_active; + bool rep_sacch = L1SAP_IS_LINK_SACCH(trx_chan_desc[bi->chan].link_id) && lchan->rep_acch.ul_sacch_active; /* 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. */ @@ -69,24 +65,11 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received Data, bid=%u\n", bi->bid); - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 464); - if (!*bursts_p) - return -ENOMEM; - } - - /* UL-SACCH requires additional memory to keep a copy of each previous - * burst set. */ - if (L1SAP_IS_LINK_SACCH(trx_chan_desc[bi->chan].link_id) && !chan_state->ul_bursts_prev) { - chan_state->ul_bursts_prev = talloc_zero_size(tall_bts_ctx, 464); - if (!chan_state->ul_bursts_prev) - return -ENOMEM; - } - /* clear burst & store frame number of first burst */ if (bi->bid == 0) { - memset(*bursts_p, 0, 464); + if (rep_sacch) /* Keep a copy to ease decoding in the next repetition pass */ + memcpy(BUFPOS(bursts_p, 4), BUFPOS(bursts_p, 0), BPLEN * 4); + memset(BUFPOS(bursts_p, 0), 0, BPLEN * 4); *mask = 0x0; *first_fn = bi->fn; } @@ -99,19 +82,18 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) /* Copy burst to buffer of 4 bursts. If the burst indication contains * no data, ensure that the buffer does not stay uninitialized */ - burst = *bursts_p + bi->bid * 116; + burst = bursts_p + bi->bid * 116; if (bi->burst_len > 0) { memcpy(burst, bi->burst + 3, 58); memcpy(burst + 58, bi->burst + 87, 58); - } else - memset(burst, 0, 58 * 2); + } /* wait until complete set of bursts */ if (bi->bid != 3) return 0; /* average measurements of the last 4 bursts */ - trx_sched_meas_avg(chan_state, &meas_avg, SCHED_MEAS_AVG_M_QUAD); + trx_sched_meas_avg(chan_state, &meas_avg, SCHED_MEAS_AVG_M_S4N4); /* check for complete set of bursts */ if ((*mask & 0xf) != 0xf) { @@ -127,10 +109,10 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) *mask = 0x0; /* decode */ - rc = gsm0503_xcch_decode(l2, *bursts_p, &n_errors, &n_bits_total); + rc = gsm0503_xcch_decode(l2, BUFPOS(bursts_p, 0), &n_errors, &n_bits_total); if (rc) { - LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", - bi->fn % l1ts->mf_period, l1ts->mf_period); + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, + BAD_DATA_MSG_FMT "\n", BAD_DATA_MSG_ARGS); l2_len = 0; /* When SACCH Repetition is active, we may try to decode the @@ -138,8 +120,8 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) * information from the previous SACCH block. See also: * 3GPP TS 44.006, section 11.2 */ if (rep_sacch) { - add_sbits(*bursts_p, chan_state->ul_bursts_prev); - rc = gsm0503_xcch_decode(l2, *bursts_p, &n_errors, &n_bits_total); + add_sbits(BUFPOS(bursts_p, 0), BUFPOS(bursts_p, 4)); + rc = gsm0503_xcch_decode(l2, BUFPOS(bursts_p, 0), &n_errors, &n_bits_total); if (rc) { LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Combining current SACCH block with previous SACCH block also yields bad data (%u/%u)\n", @@ -156,14 +138,12 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) ber10k = compute_ber10k(n_bits_total, n_errors); - /* Keep a copy to ease decoding in the next repetition pass */ - if (rep_sacch) - memcpy(chan_state->ul_bursts_prev, *bursts_p, 464); - - 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, + return _sched_compose_ph_data_ind(l1ts, *first_fn, bi->chan, + &l2[0], l2_len, + ber10k, + meas_avg.rssi, + meas_avg.toa256, + meas_avg.ci_cb, PRES_INFO_UNKNOWN); } @@ -171,79 +151,54 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) int tx_data_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) { struct msgb *msg = NULL; /* make GCC happy */ - ubit_t *burst, **bursts_p = &l1ts->chan_state[br->chan].dl_bursts; + struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan]; + ubit_t *burst, *bursts_p = chan_state->dl_bursts; + uint8_t *mask = &chan_state->dl_mask; /* send burst, if we already got a frame */ if (br->bid > 0) { - if (!*bursts_p) - return 0; + if ((*mask & 0x01) != 0x01) + return -ENOMSG; goto send_burst; } + *mask = *mask << 4; + /* get mac block from queue */ msg = _sched_dequeue_prim(l1ts, br); - if (msg) - goto got_msg; - - LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No prim for transmit.\n"); - -no_msg: - /* free burst memory */ - if (*bursts_p) { - talloc_free(*bursts_p); - *bursts_p = NULL; + if (msg == NULL) { + LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No prim for transmit.\n"); + return -ENODEV; } - return -ENODEV; -got_msg: /* check validity of message */ if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != %u\n", msgb_l2len(msg), GSM_MACBLOCK_LEN); /* free message */ msgb_free(msg); - goto no_msg; + return -EINVAL; } /* BURST BYPASS */ - /* handle loss detection of SACCH */ - if (L1SAP_IS_LINK_SACCH(trx_chan_desc[br->chan].link_id)) { - /* count and send BFI */ - if (++(l1ts->chan_state[br->chan].lost_frames) > 1) { - /* TODO: Should we pass old TOA here? Otherwise we risk - * unnecessary decreasing TA */ - - /* 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(l1ts, 0, br->chan, NULL, 0, - 0, 0, 0, 10000, - PRES_INFO_INVALID); - } - } - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 464); - if (!*bursts_p) - return -ENOMEM; - } - /* encode bursts */ - gsm0503_xcch_encode(*bursts_p, msg->l2h); + gsm0503_xcch_encode(bursts_p, msg->l2h); /* free message */ msgb_free(msg); send_burst: /* compose burst */ - burst = *bursts_p + br->bid * 116; + burst = bursts_p + br->bid * 116; memcpy(br->burst + 3, burst, 58); memcpy(br->burst + 61, TRX_GMSK_NB_TSC(br), 26); memcpy(br->burst + 87, burst + 58, 58); br->burst_len = GSM_BURST_LEN; + *mask |= (1 << br->bid); + LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting burst=%u.\n", br->bid); return 0; |