aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-02-07 14:09:06 +0100
committerHarald Welte <laforge@gnumonks.org>2015-09-22 16:41:25 +0200
commite0959e7929cf9c8659919f2849c54360eda95032 (patch)
tree6714cf65a35975788f0114b373993d46d0ef8395
parent2ea68e2b7be7af78fb87c42e39133a812b709d48 (diff)
TRX: Use received TRX clocks to determine availablility of tranceiver
Only if transceiver becomes available, control commands are sent. If tranceiver is gone, reset scheduler. The current availability state is sent to BSC via OML state change commands.
-rw-r--r--src/osmo-bts-trx/l1_if.c30
-rw-r--r--src/osmo-bts-trx/l1_if.h1
-rw-r--r--src/osmo-bts-trx/scheduler.c22
-rw-r--r--src/osmo-bts-trx/trx_if.c6
4 files changed, 49 insertions, 10 deletions
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index 25aa0f9..8040f4e 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -93,14 +93,14 @@ void l1if_reset(struct trx_l1h *l1h)
{
}
-void check_tranceiver_availability(struct trx_l1h *l1h)
+static void check_tranceiver_availability_trx(struct trx_l1h *l1h, int avail)
{
struct gsm_bts_trx *trx = l1h->trx;
uint8_t tn;
/* HACK, we should change state when we receive first clock from
* tranceiver */
- if (1) {
+ if (avail) {
/* signal availability */
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
oml_mo_tx_sw_act_rep(&trx->mo);
@@ -117,7 +117,23 @@ void check_tranceiver_availability(struct trx_l1h *l1h)
NM_AVSTATE_OFF_LINE);
oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED,
NM_AVSTATE_OFF_LINE);
+
+ for (tn = 0; tn < 8; tn++)
+ oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED,
+ NM_AVSTATE_OFF_LINE);
+ }
+}
+
+int check_tranceiver_availability(struct gsm_bts *bts, int avail)
+{
+ struct gsm_bts_trx *trx;
+ struct trx_l1h *l1h;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ l1h = trx_l1h_hdl(trx);
+ check_tranceiver_availability_trx(l1h, avail);
}
+ return 0;
}
@@ -128,6 +144,9 @@ int l1if_provision_tranceiver_trx(struct trx_l1h *l1h)
{
uint8_t tn;
+ if (!tranceiver_available)
+ return -EIO;
+
if (l1h->config.poweron
&& l1h->config.tsc_valid
&& l1h->config.bsic_valid
@@ -250,7 +269,7 @@ static int trx_close(struct gsm_bts_trx *trx)
}
/* Set to Operational State: Disabled */
- oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+ check_tranceiver_availability_trx(l1h, 0);
return 0;
}
@@ -268,9 +287,10 @@ static uint8_t trx_set_bts(struct gsm_bts *bts)
l1h->config.bsic = bsic;
l1h->config.bsic_valid = 1;
l1h->config.bsic_sent = 0;
+ l1if_provision_tranceiver_trx(l1h);
}
- check_tranceiver_availability(l1h);
}
+ check_tranceiver_availability(bts, tranceiver_available);
return 0;
@@ -286,6 +306,7 @@ static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
l1h->config.arfcn = arfcn;
l1h->config.arfcn_valid = 1;
l1h->config.arfcn_sent = 0;
+ l1if_provision_tranceiver_trx(l1h);
}
return 0;
@@ -308,6 +329,7 @@ static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts)
l1h->config.tsc = tsc;
l1h->config.tsc_valid = 1;
l1h->config.tsc_sent = 0;
+ l1if_provision_tranceiver_trx(l1h);
}
/* set physical channel */
diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h
index bb8407f..7a6afb2 100644
--- a/src/osmo-bts-trx/l1_if.h
+++ b/src/osmo-bts-trx/l1_if.h
@@ -116,6 +116,7 @@ struct trx_l1h {
struct trx_l1h *l1if_open(struct gsm_bts_trx *trx);
void l1if_close(struct trx_l1h *l1h);
void l1if_reset(struct trx_l1h *l1h);
+int check_tranceiver_availability(struct gsm_bts *bts, int avail);
int l1if_provision_tranceiver_trx(struct trx_l1h *l1h);
int l1if_provision_tranceiver(struct gsm_bts *bts);
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn);
diff --git a/src/osmo-bts-trx/scheduler.c b/src/osmo-bts-trx/scheduler.c
index 3224296..917cbda 100644
--- a/src/osmo-bts-trx/scheduler.c
+++ b/src/osmo-bts-trx/scheduler.c
@@ -1937,14 +1937,18 @@ static void trx_ctrl_timer_cb(void *data)
LOGP(DL1C, LOGL_NOTICE, "No more clock from traneiver\n");
+no_clock:
tranceiver_available = 0;
/* flush pending messages of transceiver */
- llist_for_each_entry(trx, &bts->trx_list, list)
+ /* 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_l1h_hdl(trx));
+ }
- /* start over provisioning tranceiver */
- l1if_provision_tranceiver(bts);
+ /* tell BSC */
+ check_tranceiver_availability(bts, 0);
return;
}
@@ -1958,10 +1962,10 @@ static void trx_ctrl_timer_cb(void *data)
if (elapsed > FRAME_DURATION_uS * MAX_FN_SKEW || elapsed < 0) {
LOGP(DL1C, LOGL_NOTICE, "PC clock skew: elapsed uS %d\n",
elapsed);
- tranceiver_available = 0;
- return;
+ 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) {
@@ -1996,7 +2000,7 @@ new_clock:
tranceiver_last_fn = fn;
trx_sched_fn(tranceiver_last_fn);
- /* schedule first FN to be transmitted */
+ /* schedule first FN clock */
memcpy(tv_clock, &tv_now, sizeof(struct timeval));
tranceiver_available = 1;
memset(&tranceiver_clock_timer, 0,
@@ -2006,6 +2010,12 @@ new_clock:
osmo_timer_schedule(&tranceiver_clock_timer, 0,
FRAME_DURATION_uS);
+ /* start provisioning tranceiver */
+ l1if_provision_tranceiver(bts);
+
+ /* tell BSC */
+ check_tranceiver_availability(bts, 1);
+
return 0;
}
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index e35b7cd..7d1be85 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -183,6 +183,12 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
va_list ap;
int l, pending = 0;
+ if (!tranceiver_available) {
+ LOGP(DTRX, LOGL_ERROR, "CTRL ignored: No clock from "
+ "tranceiver, please fix!\n");
+ return -EIO;
+ }
+
if (!llist_empty(&l1h->trx_ctrl_list))
pending = 1;