aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2013-11-04 18:13:22 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-05 15:46:30 +0100
commit08571b158835df3db09cc94686a8fe62d1845cc9 (patch)
treec7a9cae2d106504bb1efed653f77ee089a9ef4b8
parent9ef742f5e751c1d5fdfae14aa663e6056e6cac6f (diff)
sysmobts: Do a RF mute when Radio Carrier is locked
Currently a Change Administrative State Request is just applied unconditionally to the object's state object and then acknowledged. This patch implements the special handling of setting the Radio Carriers state to LOCK or UNLOCK. This is done by passing the appropriate mute command to the L1 layer. Always all radio channels are affected, it is not possible to lock single radio channels. On success, an ACK is sent back to the bsc with the new state (based on the state passed in the callback by the L1 layer). If something went wrong or the firmware doesn't support RF mute, a NACK (REQ_NOT_GRANTED) is sent instead. Note that a NACK for such a request hasn't been sent by the BTS to the BSC yet, so (albeit it's spec conformant to do so) the BSC must be prepared to handle this correctly. Ticket: OW#976 Sponsored-by: On-Waves ehf
-rw-r--r--include/osmo-bts/oml.h1
-rw-r--r--src/common/oml.c5
-rw-r--r--src/osmo-bts-sysmo/oml.c70
3 files changed, 72 insertions, 4 deletions
diff --git a/include/osmo-bts/oml.h b/include/osmo-bts/oml.h
index 92695cae..4281fd32 100644
--- a/include/osmo-bts/oml.h
+++ b/include/osmo-bts/oml.h
@@ -10,6 +10,7 @@ int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
int oml_mo_opstart_ack(struct gsm_abis_mo *mo);
int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
int oml_mo_statechg_ack(struct gsm_abis_mo *mo);
+int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
/* Change the state and send STATE CHG REP */
int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state);
diff --git a/src/common/oml.c b/src/common/oml.c
index 1c38c666..bf174b5f 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -299,6 +299,11 @@ int oml_mo_statechg_ack(struct gsm_abis_mo *mo)
return oml_mo_send_msg(mo, msg, NM_MT_CHG_ADM_STATE_ACK);
}
+int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause)
+{
+ return oml_mo_fom_ack_nack(mo, NM_MT_CHG_ADM_STATE, nack_cause);
+}
+
int oml_mo_opstart_ack(struct gsm_abis_mo *mo)
{
return oml_mo_fom_ack_nack(mo, NM_MT_OPSTART, 0);
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index 822453f5..c87acb66 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -326,10 +326,31 @@ int bts_model_trx_close(struct gsm_bts_trx *trx)
return l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb);
}
+static int trx_rf_lock(struct gsm_bts_trx *trx, int locked)
+{
+ struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
+ uint8_t mute[8];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mute); ++i)
+ mute[i] = locked ? 1 : 0;
+
+ return l1if_mute_rf(fl1h, mute);
+}
+
int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8],
int success)
{
- return 0;
+ if (success) {
+ /* assume mute_state[i] == mute_state[k] */
+ mo->nm_state.administrative =
+ mute_state[0] ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
+ mo->procedure_pending = 0;
+ return oml_mo_statechg_ack(mo);
+ } else {
+ mo->procedure_pending = 0;
+ return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT);
+ }
}
static int ts_connect(struct gsm_bts_trx_ts *ts)
@@ -1461,9 +1482,50 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
void *obj, uint8_t adm_state)
{
- /* blindly accept all state changes */
- mo->nm_state.administrative = adm_state;
- return oml_mo_statechg_ack(mo);
+ int rc = -EINVAL;
+ int granted = 0;
+
+ switch (mo->obj_class) {
+ case NM_OC_RADIO_CARRIER:
+
+ if (mo->procedure_pending) {
+ LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: "
+ "pending procedure on RC %d\n",
+ ((struct gsm_bts_trx *)obj)->nr);
+ return 0;
+ }
+ mo->procedure_pending = 1;
+ switch (adm_state) {
+ case NM_STATE_LOCKED:
+ rc = trx_rf_lock(obj, 1);
+ break;
+ case NM_STATE_UNLOCKED:
+ rc = trx_rf_lock(obj, 0);
+ break;
+ default:
+ granted = 1;
+ break;
+ }
+
+ if (!granted && rc == 0)
+ /* in progress, will send ack/nack after completion */
+ return 0;
+
+ mo->procedure_pending = 0;
+
+ break;
+ default:
+ /* blindly accept all state changes */
+ granted = 1;
+ break;
+ }
+
+ if (granted) {
+ mo->nm_state.administrative = adm_state;
+ return oml_mo_statechg_ack(mo);
+ } else
+ return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT);
+
}
int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp)
{