aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-11-26 13:59:52 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2018-11-26 14:08:14 +0100
commite0faed47c140b946b1a19b968d3c5e819630c20a (patch)
treec0d996cf0e2946cb5de1c4683ad5fcd45edc9463
parente3cb8715f59cae342b6ecb96be4eb82c1ad00b4e (diff)
bts-trx: (n)ack PDCH DEACT only after TRX answered SETSLOTpespin/pdch-deact-ack-trx
Before this patch, PDCH DEACT was (n)acked to the BSC without taking into account if TRX succeeded or failed to set the TS: 20181123044720655 DRLL <0002> rsl.c:2523 (bts=0,trx=0,ts=0,ss=0) Rx RLL DATA_REQ Abis -> LAPDm 20181123044720700 DRSL <0000> rsl.c:2805 (bts=0,trx=0,ts=6,pchan=TCH/F_PDCH as PDCH) ss=0 Rx RSL IPAC_PDCH_DEACT 20181123044720700 DRSL <0000> rsl.c:2205 (bts=0,trx=0,ts=6,pchan=TCH/F_PDCH as PDCH) Request to PDCH DEACT, but lchan is still active 20181123044720700 DRSL <0000> rsl.c:2131 (bts=0,trx=0,ts=6,ss=0) Tx PDCH DEACT NACK (cause = 0x0f) 20181123044720700 DPCU <0009> pcu_sock.c:124 Sending info 20181123044720700 DPCU <0009> pcu_sock.c:139 BTS is up 20181123044720700 DPCU <0009> pcu_sock.c:232 trx=0 ts=7: available (tsc=7 arfcn=868) 20181123044720703 DPCU <0009> pcu_sock.c:608 Deactivate request received: TRX=0 TX=6 20181123044720703 DL1C <0006> l1sap.c:1519 deactivating channel chan_nr=TCH/F on TS6 trx=0 20181123044720703 DTRX <000b> trx_if.c:242 Enqueuing TRX control command 'CMD NOHANDOVER 6 0' 20181123044720703 DL1C <0006> l1sap.c:648 deactivate confirm chan_nr=TCH/F on TS6 trx=0 20181123044720703 DRSL <0000> rsl.c:714 (bts=0,trx=0,ts=6,ss=0) not sending REL ACK 20181123044720703 DRSL <0000> rsl.c:2264 (bts=0,trx=0,ts=6,ss=0) PDCH DEACT operation: channel disconnected, will reconnect as TCH 20181123044720703 DL1C <0006> scheduler.c:593 Configuring multiframe with TCH/F+SACCH trx=0 ts=6 20181123044720703 DTRX <000b> trx_if.c:242 Enqueuing TRX control command 'CMD SETSLOT 6 1' 20181123044720703 DL1C <0006> l1_if.c:780 (bts=0,trx=0,ts=6) bts_model_ts_connect(as_pchan=TCH/F) success, calling cb_ts_connected() 20181123044720703 DRSL <0000> rsl.c:2339 (bts=0,trx=0,ts=6,ss=0) PDCH DEACT operation: timeslot connected as TCH/F 20181123044720703 DRSL <0000> rsl.c:2440 (bts=0,trx=0,ts=6,ss=0) TCH/F_PDCH switched to TCH/F mode (ts->flags == 0) 20181123044720703 DRSL <0000> rsl.c:2103 (bts=0,trx=0,ts=6,ss=0) Tx PDCH DEACT ACK 20181123044720704 DTRX <000b> trx_if.c:492 Response message: 'RSP NOHANDOVER 0 6' 20181123044720705 DTRX <000b> trx_if.c:492 Response message: 'RSP SETSLOT 0 6 1' Change-Id: I888de761b65c3ea8bfe623fcf009f3b2b57c926c
-rw-r--r--src/osmo-bts-trx/l1_if.c47
-rw-r--r--src/osmo-bts-trx/trx_if.c60
-rw-r--r--src/osmo-bts-trx/trx_if.h5
3 files changed, 91 insertions, 21 deletions
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index da1b554..6af25a6 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -58,6 +58,16 @@ static const uint8_t transceiver_chan_types[_GSM_PCHAN_MAX] = {
[GSM_PCHAN_UNKNOWN] = 0,
};
+static enum gsm_phys_chan_config transceiver_chan_type_2_pchan(uint8_t type)
+{
+ int i;
+ for (i = 0; i < _GSM_PCHAN_MAX; i++) {
+ if (transceiver_chan_types[i] == type)
+ return (enum gsm_phys_chan_config) i;
+ }
+ return GSM_PCHAN_UNKNOWN;
+}
+
struct trx_l1h *trx_l1h_alloc(void *tall_ctx, struct phy_instance *pinst)
{
struct trx_l1h *l1h;
@@ -140,6 +150,36 @@ int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan)
LID_SACCH, 0);
}
+static void l1if_setslot_cb(struct trx_l1h *l1h, uint8_t tn, uint8_t type, int rc)
+{
+ struct phy_instance *pinst = l1h->phy_inst;
+ struct gsm_bts_trx *trx = pinst->trx;
+ struct gsm_bts_trx_ts *ts;
+ enum gsm_phys_chan_config pchan;
+
+
+ if (tn >= TRX_NR_TS) {
+ LOGP(DL1C, LOGL_ERROR, "transceiver (%s) SETSLOT invalid param TN\n",
+ phy_instance_name(pinst));
+ return;
+ }
+
+ if (type > 13) {
+ LOGP(DL1C, LOGL_ERROR, "transceiver (%s) SETSLOT invalid param TS_TYPE\n",
+ phy_instance_name(pinst));
+ return;
+ }
+
+ pchan = transceiver_chan_type_2_pchan(type);
+
+ ts = &trx->ts[tn];
+ LOGP(DL1C, LOGL_DEBUG, "%s l1if_setslot_cb(as_pchan=%s),"
+ " calling cb_ts_connected(rc=%d)\n",
+ gsm_ts_name(ts), gsm_pchan_name(pchan), rc);
+ cb_ts_connected(ts, rc);
+}
+
+
/*
* transceiver provisioning
*/
@@ -196,7 +236,7 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
if (l1h->config.slottype_valid[tn]
&& !l1h->config.slottype_sent[tn]) {
trx_if_cmd_setslot(l1h, tn,
- l1h->config.slottype[tn]);
+ l1h->config.slottype[tn], l1if_setslot_cb);
l1h->config.slottype_sent[tn] = 1;
}
}
@@ -775,8 +815,5 @@ void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
if (rc)
cb_ts_connected(ts, rc);
- LOGP(DL1C, LOGL_NOTICE, "%s bts_model_ts_connect(as_pchan=%s) success,"
- " calling cb_ts_connected()\n",
- gsm_ts_name(ts), gsm_pchan_name(as_pchan));
- cb_ts_connected(ts, 0);
+ /* cb_ts_connected will be called in l1if_setslot_cb once we receive RSP SETSLOT */
}
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index abe6846..7c9f432 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -196,7 +196,7 @@ void trx_if_init(struct trx_l1h *l1h)
* The new ocommand will be added to the end of the control command
* queue.
*/
-static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
+static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, void *cb, const char *cmd,
const char *fmt, ...)
{
struct trx_ctrl_msg *tcm;
@@ -231,6 +231,7 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
tcm->params_len = 0;
}
tcm->critical = critical;
+ tcm->cb = cb;
/* Avoid adding consecutive duplicate messages, eg: two consecutive POWEROFF */
if(pending)
@@ -255,7 +256,7 @@ int trx_if_cmd_poweroff(struct trx_l1h *l1h)
{
struct phy_instance *pinst = l1h->phy_inst;
if (pinst->num == 0)
- return trx_ctrl_cmd(l1h, 1, "POWEROFF", "");
+ return trx_ctrl_cmd(l1h, 1, NULL, "POWEROFF", "");
else
return 0;
}
@@ -265,7 +266,7 @@ int trx_if_cmd_poweron(struct trx_l1h *l1h)
{
struct phy_instance *pinst = l1h->phy_inst;
if (pinst->num == 0)
- return trx_ctrl_cmd(l1h, 1, "POWERON", "");
+ return trx_ctrl_cmd(l1h, 1, NULL, "POWERON", "");
else
return 0;
}
@@ -277,7 +278,7 @@ int trx_if_cmd_settsc(struct trx_l1h *l1h, uint8_t tsc)
if (pinst->phy_link->u.osmotrx.use_legacy_setbsic)
return 0;
- return trx_ctrl_cmd(l1h, 1, "SETTSC", "%d", tsc);
+ return trx_ctrl_cmd(l1h, 1, NULL, "SETTSC", "%d", tsc);
}
/*! Send "SETBSIC" command to TRX */
@@ -287,37 +288,37 @@ int trx_if_cmd_setbsic(struct trx_l1h *l1h, uint8_t bsic)
if (!pinst->phy_link->u.osmotrx.use_legacy_setbsic)
return 0;
- return trx_ctrl_cmd(l1h, 1, "SETBSIC", "%d", bsic);
+ return trx_ctrl_cmd(l1h, 1, NULL, "SETBSIC", "%d", bsic);
}
/*! Send "SETRXGAIN" command to TRX */
int trx_if_cmd_setrxgain(struct trx_l1h *l1h, int db)
{
- return trx_ctrl_cmd(l1h, 0, "SETRXGAIN", "%d", db);
+ return trx_ctrl_cmd(l1h, 0, NULL, "SETRXGAIN", "%d", db);
}
/*! Send "SETPOWER" command to TRX */
int trx_if_cmd_setpower(struct trx_l1h *l1h, int db)
{
- return trx_ctrl_cmd(l1h, 0, "SETPOWER", "%d", db);
+ return trx_ctrl_cmd(l1h, 0, NULL, "SETPOWER", "%d", db);
}
/*! Send "SETMAXDLY" command to TRX, i.e. maximum delay for RACH bursts */
int trx_if_cmd_setmaxdly(struct trx_l1h *l1h, int dly)
{
- return trx_ctrl_cmd(l1h, 0, "SETMAXDLY", "%d", dly);
+ return trx_ctrl_cmd(l1h, 0, NULL, "SETMAXDLY", "%d", dly);
}
/*! Send "SETMAXDLYNB" command to TRX, i.e. maximum delay for normal bursts */
int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int dly)
{
- return trx_ctrl_cmd(l1h, 0, "SETMAXDLYNB", "%d", dly);
+ return trx_ctrl_cmd(l1h, 0, NULL, "SETMAXDLYNB", "%d", dly);
}
/*! Send "SETSLOT" command to TRX: Configure Channel Combination for TS */
-int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type)
+int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type, trx_if_cmd_setslot_cb *cb)
{
- return trx_ctrl_cmd(l1h, 1, "SETSLOT", "%d %d", tn, type);
+ return trx_ctrl_cmd(l1h, 1, cb, "SETSLOT", "%d %d", tn, type);
}
/*! Send "RXTUNE" command to TRX: Tune Receiver to given ARFCN */
@@ -336,7 +337,7 @@ int trx_if_cmd_rxtune(struct trx_l1h *l1h, uint16_t arfcn)
return -ENOTSUP;
}
- return trx_ctrl_cmd(l1h, 1, "RXTUNE", "%d", freq10 * 100);
+ return trx_ctrl_cmd(l1h, 1, NULL, "RXTUNE", "%d", freq10 * 100);
}
/*! Send "TXTUNE" command to TRX: Tune Transmitter to given ARFCN */
@@ -355,25 +356,26 @@ int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn)
return -ENOTSUP;
}
- return trx_ctrl_cmd(l1h, 1, "TXTUNE", "%d", freq10 * 100);
+ return trx_ctrl_cmd(l1h, 1, NULL, "TXTUNE", "%d", freq10 * 100);
}
/*! Send "HANDOVER" command to TRX: Enable handover RACH Detection on timeslot/sub-slot */
int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
{
- return trx_ctrl_cmd(l1h, 1, "HANDOVER", "%d %d", tn, ss);
+ return trx_ctrl_cmd(l1h, 1, NULL, "HANDOVER", "%d %d", tn, ss);
}
/*! Send "NOHANDOVER" command to TRX: Disable handover RACH Detection on timeslot/sub-slot */
int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
{
- return trx_ctrl_cmd(l1h, 1, "NOHANDOVER", "%d %d", tn, ss);
+ return trx_ctrl_cmd(l1h, 1, NULL, "NOHANDOVER", "%d %d", tn, ss);
}
struct trx_ctrl_rsp {
char cmd[50];
char params[100];
int status;
+ void *cb;
};
static int parse_rsp(const char *buf_in, size_t len_in, struct trx_ctrl_rsp *rsp)
@@ -437,6 +439,30 @@ static bool cmd_matches_rsp(struct trx_ctrl_msg *tcm, struct trx_ctrl_rsp *rsp)
return true;
}
+static int trx_ctrl_rx_rsp_setslot(struct trx_l1h *l1h, struct trx_ctrl_rsp *rsp)
+{
+ trx_if_cmd_setslot_cb *cb = (trx_if_cmd_setslot_cb*) rsp->cb;
+ struct phy_instance *pinst = l1h->phy_inst;
+ unsigned int tn, ts_type;
+
+ if (rsp->status)
+ LOGP(DTRX, LOGL_ERROR, "transceiver (%s) SETSLOT failed with status %d\n",
+ phy_instance_name(pinst), rsp->status);
+
+ /* Since message was already validated against CMD we sent, we know format
+ * of params is: "<TN> <TS_TYPE>" */
+ if (sscanf(rsp->params, "%u %u", &tn, &ts_type) < 2) {
+ LOGP(DTRX, LOGL_ERROR, "transceiver (%s) SETSLOT unable to parse params\n",
+ phy_instance_name(pinst));
+ return -EINVAL;
+ }
+
+ if (cb)
+ cb(l1h, tn, ts_type, rsp->status);
+
+ return rsp->status == 0 ? 0 : -EINVAL;
+}
+
/* -EINVAL: unrecoverable error, exit BTS
* N > 0: try sending originating command again after N seconds
* 0: Done with response, get originating command out from send queue
@@ -459,6 +485,8 @@ static int trx_ctrl_rx_rsp(struct trx_l1h *l1h, struct trx_ctrl_rsp *rsp, bool c
phy_link_state_set(pinst->phy_link, PHY_LINK_SHUTDOWN);
return 5;
}
+ } else if (strcmp(rsp->cmd, "SETSLOT") == 0) {
+ return trx_ctrl_rx_rsp_setslot(l1h, rsp);
}
if (rsp->status) {
@@ -526,6 +554,8 @@ static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
goto rsp_error;
}
+ rsp.cb = tcm->cb;
+
/* check for response code */
rc = trx_ctrl_rx_rsp(l1h, &rsp, tcm->critical);
if (rc == -EINVAL)
diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h
index 206f5e5..cdfbd41 100644
--- a/src/osmo-bts-trx/trx_if.h
+++ b/src/osmo-bts-trx/trx_if.h
@@ -12,8 +12,11 @@ struct trx_ctrl_msg {
int cmd_len;
int params_len;
int critical;
+ void *cb;
};
+typedef void trx_if_cmd_setslot_cb(struct trx_l1h *l1h, uint8_t tn, uint8_t type, int rc);
+
void trx_if_init(struct trx_l1h *l1h);
int trx_if_cmd_poweroff(struct trx_l1h *l1h);
int trx_if_cmd_poweron(struct trx_l1h *l1h);
@@ -23,7 +26,7 @@ int trx_if_cmd_setrxgain(struct trx_l1h *l1h, int db);
int trx_if_cmd_setpower(struct trx_l1h *l1h, int db);
int trx_if_cmd_setmaxdly(struct trx_l1h *l1h, int dly);
int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int dly);
-int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type);
+int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type, trx_if_cmd_setslot_cb *cb);
int trx_if_cmd_rxtune(struct trx_l1h *l1h, uint16_t arfcn);
int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn);
int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);