aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-trx
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-01-09 23:15:41 +0100
committerHarald Welte <laforge@gnumonks.org>2016-02-15 14:17:55 +0100
commit67311cc1f20c88a0ad0afe488ec136d985477b81 (patch)
treef2c03d7d4f1194e21f4464a8e118ac53de3d8ff5 /src/osmo-bts-trx
parentb6b42d150db5ef707ad17b0005d7de8f0f538390 (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')
-rw-r--r--src/osmo-bts-trx/scheduler.c230
-rw-r--r--src/osmo-bts-trx/scheduler.h2
-rw-r--r--src/osmo-bts-trx/scheduler_backend.h2
-rw-r--r--src/osmo-bts-trx/scheduler_trx.c220
-rw-r--r--src/osmo-bts-trx/trx_if.c5
5 files changed, 229 insertions, 230 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));
diff --git a/src/osmo-bts-trx/scheduler.h b/src/osmo-bts-trx/scheduler.h
index c153b9ed..13ef0511 100644
--- a/src/osmo-bts-trx/scheduler.h
+++ b/src/osmo-bts-trx/scheduler.h
@@ -145,7 +145,7 @@ int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap
int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
/*! \brief PHY informs us of new (current) GSM freme nunmber */
-int trx_sched_clock(uint32_t fn);
+int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
/*! \brief handle an UL burst received by PHY */
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
diff --git a/src/osmo-bts-trx/scheduler_backend.h b/src/osmo-bts-trx/scheduler_backend.h
index ea3e620f..b8084552 100644
--- a/src/osmo-bts-trx/scheduler_backend.h
+++ b/src/osmo-bts-trx/scheduler_backend.h
@@ -77,3 +77,5 @@ int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
+const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
+int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index a77f5a5c..0aeb8359 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -49,6 +49,18 @@
extern void *tall_bts_ctx;
+/* 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 */
+
/* Enable this to multiply TOA of RACH by 10.
* This is usefull to check tenth of timing advances with RSSI test tool.
* Note that regular phones will not work when using this test! */
@@ -1238,3 +1250,211 @@ bfi:
(fn + GSM_HYPERFRAME - 10 - ((fn%26)==19) - ((fn%26)==20)) % GSM_HYPERFRAME,
chan, tch_data, rc);
}
+
+/* schedule all frames of all TRX for given FN */
+static int trx_sched_fn(struct gsm_bts *bts, 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 */
+ _sched_rts(l1t, tn,
+ (fn + trx_rts_advance) % GSM_HYPERFRAME);
+ /* get burst for FN */
+ bits = _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(bts, 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(struct gsm_bts *bts, 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(bts, 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(bts, 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;
+}
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index 16c9fc70..c9cfaef5 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -121,6 +121,7 @@ static struct osmo_fd trx_ofd_clk;
/* get clock from clock socket */
static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
{
+ struct trx_l1h *l1h = ofd->data;
char buf[1500];
int len;
uint32_t fn;
@@ -145,7 +146,7 @@ static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
"correctly, correcting to fn=%u\n", fn);
}
- trx_sched_clock(fn);
+ trx_sched_clock(l1h->trx->bts, fn);
return 0;
}
@@ -503,7 +504,7 @@ int trx_if_open(struct trx_l1h *l1h)
/* open sockets */
if (l1h->trx->nr == 0) {
- rc = trx_udp_open(NULL, &trx_ofd_clk, base_port_local,
+ rc = trx_udp_open(l1h, &trx_ofd_clk, base_port_local,
trx_clk_read_cb);
if (rc < 0)
return rc;