diff options
Diffstat (limited to 'src/osmo-bsc/timeslot_fsm.c')
-rw-r--r-- | src/osmo-bsc/timeslot_fsm.c | 77 |
1 files changed, 73 insertions, 4 deletions
diff --git a/src/osmo-bsc/timeslot_fsm.c b/src/osmo-bsc/timeslot_fsm.c index f8adfb6c7..a72833f82 100644 --- a/src/osmo-bsc/timeslot_fsm.c +++ b/src/osmo-bsc/timeslot_fsm.c @@ -654,6 +654,39 @@ static void ts_fsm_in_use(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } +static void ts_fsm_borken_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct gsm_bts_trx_ts *ts = ts_fi_ts(fi); + enum bts_counter_id ctr; + switch (prev_state) { + case TS_ST_NOT_INITIALIZED: + ctr = BTS_CTR_TS_BORKEN_FROM_NOT_INITIALIZED; + break; + case TS_ST_UNUSED: + ctr = BTS_CTR_TS_BORKEN_FROM_UNUSED; + break; + case TS_ST_WAIT_PDCH_ACT: + ctr = BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_ACT; + break; + case TS_ST_PDCH: + ctr = BTS_CTR_TS_BORKEN_FROM_PDCH; + break; + case TS_ST_WAIT_PDCH_DEACT: + ctr = BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_DEACT; + break; + case TS_ST_IN_USE: + ctr = BTS_CTR_TS_BORKEN_FROM_IN_USE; + break; + case TS_ST_BORKEN: + ctr = BTS_CTR_TS_BORKEN_FROM_BORKEN; + break; + default: + ctr = BTS_CTR_TS_BORKEN_FROM_UNKNOWN; + } + rate_ctr_inc(&ts->trx->bts->bts_ctrs->ctr[ctr]); + osmo_stat_item_inc(ts->trx->bts->bts_statg->items[BTS_STAT_TS_BORKEN], 1); +} + static void ts_fsm_borken(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { @@ -669,10 +702,30 @@ static void ts_fsm_borken(struct osmo_fsm_inst *fi, uint32_t event, void *data) } case TS_EV_PDCH_ACT_ACK: - /* Late PDCH activation ACK is not a crime. - * Just go into the PDCH mode as normal. */ - osmo_fsm_inst_state_chg(fi, TS_ST_PDCH, 0, 0); - return; + case TS_EV_PDCH_ACT_NACK: + { + struct gsm_bts_trx_ts *ts = ts_fi_ts(fi); + struct gsm_bts *bts = ts->trx->bts; + /* Late PDCH activation ACK/NACK is not a crime. + * Just process them as normal. */ + rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_TS_BORKEN_EV_PDCH_ACT_ACK_NACK]); + osmo_stat_item_dec(bts->bts_statg->items[BTS_STAT_TS_BORKEN], 1); + ts_fsm_wait_pdch_act(fi, event, data); + return; + } + + case TS_EV_PDCH_DEACT_ACK: + case TS_EV_PDCH_DEACT_NACK: + { + struct gsm_bts_trx_ts *ts = ts_fi_ts(fi); + struct gsm_bts *bts = ts->trx->bts; + /* Late PDCH deactivation ACK/NACK is also not a crime. + * Just process them as normal. */ + rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_TS_BORKEN_EV_PDCH_DEACT_ACK_NACK]); + osmo_stat_item_dec(bts->bts_statg->items[BTS_STAT_TS_BORKEN], 1); + ts_fsm_wait_pdch_deact(fi, event, data); + return; + } default: OSMO_ASSERT(false); @@ -725,6 +778,15 @@ static void ts_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data } } +static void ts_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) +{ + struct gsm_bts_trx_ts *ts = ts_fi_ts(fi); + if (ts->fi->state == TS_ST_BORKEN) { + rate_ctr_inc(&ts->trx->bts->bts_ctrs->ctr[BTS_CTR_TS_BORKEN_EV_CLEANUP]); + osmo_stat_item_dec(ts->trx->bts->bts_statg->items[BTS_STAT_TS_BORKEN], 1); + } +} + #define S(x) (1 << (x)) static const struct osmo_fsm_state ts_fsm_states[] = { @@ -822,13 +884,19 @@ static const struct osmo_fsm_state ts_fsm_states[] = { }, [TS_ST_BORKEN] = { .name = "BORKEN", + .onenter = ts_fsm_borken_onenter, .action = ts_fsm_borken, .in_event_mask = 0 | S(TS_EV_LCHAN_REQUESTED) | S(TS_EV_LCHAN_UNUSED) | S(TS_EV_PDCH_ACT_ACK) + | S(TS_EV_PDCH_ACT_NACK) + | S(TS_EV_PDCH_DEACT_ACK) + | S(TS_EV_PDCH_DEACT_NACK) , .out_state_mask = 0 + | S(TS_ST_IN_USE) + | S(TS_ST_UNUSED) | S(TS_ST_NOT_INITIALIZED) | S(TS_ST_PDCH) , @@ -862,6 +930,7 @@ static struct osmo_fsm ts_fsm = { | S(TS_EV_RSL_DOWN) , .allstate_action = ts_fsm_allstate, + .cleanup = ts_fsm_cleanup, }; /* Return true if any lchans are waiting for this timeslot to become a specific PCHAN. If target_pchan is |