diff options
author | Harald Welte <laforge@gnumonks.org> | 2016-01-09 23:15:41 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2016-02-15 14:17:55 +0100 |
commit | 67311cc1f20c88a0ad0afe488ec136d985477b81 (patch) | |
tree | f2c03d7d4f1194e21f4464a8e118ac53de3d8ff5 /src/osmo-bts-trx/scheduler.c | |
parent | b6b42d150db5ef707ad17b0005d7de8f0f538390 (diff) |
TRX: scheduler: Move trx_sched_clock() to scheduler_trx.c
This funciton (and associated static functions) are TRX specific,
and scheduler.c should only contain generic code.
Diffstat (limited to 'src/osmo-bts-trx/scheduler.c')
-rw-r--r-- | src/osmo-bts-trx/scheduler.c | 230 |
1 files changed, 3 insertions, 227 deletions
diff --git a/src/osmo-bts-trx/scheduler.c b/src/osmo-bts-trx/scheduler.c index d4af2b70..10f8972e 100644 --- a/src/osmo-bts-trx/scheduler.c +++ b/src/osmo-bts-trx/scheduler.c @@ -36,27 +36,12 @@ #include <osmo-bts/rsl.h> #include <osmo-bts/l1sap.h> -#include "l1_if.h" #include "scheduler.h" #include "scheduler_backend.h" -#include "trx_if.h" +//#include "trx_if.h" extern void *tall_bts_ctx; -static struct gsm_bts *bts; - -/* clock states */ -static uint32_t transceiver_lost; -uint32_t transceiver_last_fn; -static struct timeval transceiver_clock_tv; -static struct osmo_timer_list transceiver_clock_timer; - -/* clock advance for the transceiver */ -uint32_t trx_clock_advance = 20; - -/* advance RTS to give some time for data processing. (especially PCU) */ -uint32_t trx_rts_advance = 5; /* about 20ms */ - 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, @@ -1460,7 +1445,7 @@ int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink, } /* process ready-to-send */ -static int trx_sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) +int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) { struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); const struct trx_sched_frame *frame; @@ -1498,8 +1483,7 @@ static int trx_sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) } /* process downlink burst */ -static const ubit_t *trx_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, - uint32_t fn) +const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) { struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); struct l1sched_chan_state *l1cs; @@ -1639,214 +1623,6 @@ next_frame: return 0; } -/* schedule all frames of all TRX for given FN */ -static int trx_sched_fn(uint32_t fn) -{ - struct gsm_bts_trx *trx; - uint8_t tn; - const ubit_t *bits; - uint8_t gain; - - /* send time indication */ - l1if_mph_time_ind(bts, fn); - - /* advance frame number, so the transceiver has more time until - * it must be transmitted. */ - fn = (fn + trx_clock_advance) % GSM_HYPERFRAME; - - /* process every TRX */ - llist_for_each_entry(trx, &bts->trx_list, list) { - struct trx_l1h *l1h = trx_l1h_hdl(trx); - struct l1sched_trx *l1t = trx_l1sched_hdl(trx); - - /* we don't schedule, if power is off */ - if (!trx_if_powered(l1h)) - continue; - - /* process every TS of TRX */ - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - /* ready-to-send */ - trx_sched_rts(l1t, tn, - (fn + trx_rts_advance) % GSM_HYPERFRAME); - /* get burst for FN */ - bits = trx_sched_dl_burst(l1t, tn, fn); - if (!bits) { - /* if no bits, send no burst */ - continue; - } else - gain = 0; - trx_if_data(l1h, tn, fn, gain, bits); - } - } - - return 0; -} - - -/* - * frame clock - */ - -#define FRAME_DURATION_uS 4615 -#define MAX_FN_SKEW 50 -#define TRX_LOSS_FRAMES 400 - -extern int quit; -/* this timer fires for every FN to be processed */ -static void trx_ctrl_timer_cb(void *data) -{ - struct gsm_bts *bts = data; - struct timeval tv_now, *tv_clock = &transceiver_clock_tv; - int32_t elapsed; - - /* check if transceiver is still alive */ - if (transceiver_lost++ == TRX_LOSS_FRAMES) { - struct gsm_bts_trx *trx; - - LOGP(DL1C, LOGL_NOTICE, "No more clock from transceiver\n"); - -no_clock: - transceiver_available = 0; - - /* flush pending messages of transceiver */ - /* close all logical channels and reset timeslots */ - llist_for_each_entry(trx, &bts->trx_list, list) { - trx_if_flush(trx_l1h_hdl(trx)); - trx_sched_reset(trx_l1sched_hdl(trx)); - if (trx->nr == 0) - trx_if_cmd_poweroff(trx_l1h_hdl(trx)); - } - - /* tell BSC */ - check_transceiver_availability(bts, 0); - - return; - } - - gettimeofday(&tv_now, NULL); - - elapsed = (tv_now.tv_sec - tv_clock->tv_sec) * 1000000 - + (tv_now.tv_usec - tv_clock->tv_usec); - - /* if someone played with clock, or if the process stalled */ - if (elapsed > FRAME_DURATION_uS * MAX_FN_SKEW || elapsed < 0) { - LOGP(DL1C, LOGL_NOTICE, "PC clock skew: elapsed uS %d\n", - elapsed); - goto no_clock; - } - - /* schedule next FN clock */ - while (elapsed > FRAME_DURATION_uS / 2) { - tv_clock->tv_usec += FRAME_DURATION_uS; - if (tv_clock->tv_usec >= 1000000) { - tv_clock->tv_sec++; - tv_clock->tv_usec -= 1000000; - } - transceiver_last_fn = (transceiver_last_fn + 1) % GSM_HYPERFRAME; - trx_sched_fn(transceiver_last_fn); - elapsed -= FRAME_DURATION_uS; - } - osmo_timer_schedule(&transceiver_clock_timer, 0, - FRAME_DURATION_uS - elapsed); -} - - -/* receive clock from transceiver */ -int trx_sched_clock(uint32_t fn) -{ - struct timeval tv_now, *tv_clock = &transceiver_clock_tv; - int32_t elapsed; - int32_t elapsed_fn; - - if (quit) - return 0; - - /* reset lost counter */ - transceiver_lost = 0; - - gettimeofday(&tv_now, NULL); - - /* clock becomes valid */ - if (!transceiver_available) { - LOGP(DL1C, LOGL_NOTICE, "initial GSM clock received: fn=%u\n", - fn); - - transceiver_available = 1; - - /* start provisioning transceiver */ - l1if_provision_transceiver(bts); - - /* tell BSC */ - check_transceiver_availability(bts, 1); - -new_clock: - transceiver_last_fn = fn; - trx_sched_fn(transceiver_last_fn); - - /* schedule first FN clock */ - memcpy(tv_clock, &tv_now, sizeof(struct timeval)); - memset(&transceiver_clock_timer, 0, - sizeof(transceiver_clock_timer)); - transceiver_clock_timer.cb = trx_ctrl_timer_cb; - transceiver_clock_timer.data = bts; - osmo_timer_schedule(&transceiver_clock_timer, 0, - FRAME_DURATION_uS); - - return 0; - } - - osmo_timer_del(&transceiver_clock_timer); - - /* calculate elapsed time since last_fn */ - elapsed = (tv_now.tv_sec - tv_clock->tv_sec) * 1000000 - + (tv_now.tv_usec - tv_clock->tv_usec); - - /* how much frames have been elapsed since last fn processed */ - elapsed_fn = (fn + GSM_HYPERFRAME - transceiver_last_fn) % GSM_HYPERFRAME; - if (elapsed_fn >= 135774) - elapsed_fn -= GSM_HYPERFRAME; - - /* check for max clock skew */ - if (elapsed_fn > MAX_FN_SKEW || elapsed_fn < -MAX_FN_SKEW) { - LOGP(DL1C, LOGL_NOTICE, "GSM clock skew: old fn=%u, " - "new fn=%u\n", transceiver_last_fn, fn); - goto new_clock; - } - - LOGP(DL1C, LOGL_INFO, "GSM clock jitter: %d\n", - elapsed_fn * FRAME_DURATION_uS - elapsed); - - /* too many frames have been processed already */ - if (elapsed_fn < 0) { - /* set clock to the time or last FN should have been - * transmitted. */ - tv_clock->tv_sec = tv_now.tv_sec; - tv_clock->tv_usec = tv_now.tv_usec + - (0 - elapsed_fn) * FRAME_DURATION_uS; - if (tv_clock->tv_usec >= 1000000) { - tv_clock->tv_sec++; - tv_clock->tv_usec -= 1000000; - } - /* set time to the time our next FN has to be transmitted */ - osmo_timer_schedule(&transceiver_clock_timer, 0, - FRAME_DURATION_uS * (1 - elapsed_fn)); - - return 0; - } - - /* transmit what we still need to transmit */ - while (fn != transceiver_last_fn) { - transceiver_last_fn = (transceiver_last_fn + 1) % GSM_HYPERFRAME; - trx_sched_fn(transceiver_last_fn); - } - - /* schedule next FN to be transmitted */ - memcpy(tv_clock, &tv_now, sizeof(struct timeval)); - osmo_timer_schedule(&transceiver_clock_timer, 0, FRAME_DURATION_uS); - - return 0; -} - struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn) { OSMO_ASSERT(tn < ARRAY_SIZE(l1t->ts)); |