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-12-04 16:57:52 +0000
commitc606103d9f6dd406c59c4927f703281d7817f5c9 (patch)
tree6c7ab5bba049dfa0a7775c8d64417dc1ea6c1668
parent19ff607e99b3a8c7c5b6428b4346ed7375ea3bc3 (diff)
bts-trx: (n)ack PDCH DEACT only after TRX answered SETSLOT
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 rsl.c:2523 (bts=0,trx=0,ts=0,ss=0) Rx RLL DATA_REQ Abis -> LAPDm 20181123044720700 DRSL rsl.c:2805 (bts=0,trx=0,ts=6,pchan=TCH/F_PDCH as PDCH) ss=0 Rx RSL IPAC_PDCH_DEACT 20181123044720700 DRSL 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 rsl.c:2131 (bts=0,trx=0,ts=6,ss=0) Tx PDCH DEACT NACK (cause = 0x0f) 20181123044720700 DPCU pcu_sock.c:124 Sending info 20181123044720700 DPCU pcu_sock.c:139 BTS is up 20181123044720700 DPCU pcu_sock.c:232 trx=0 ts=7: available (tsc=7 arfcn=868) 20181123044720703 DPCU pcu_sock.c:608 Deactivate request received: TRX=0 TX=6 20181123044720703 DL1C l1sap.c:1519 deactivating channel chan_nr=TCH/F on TS6 trx=0 20181123044720703 DTRX trx_if.c:242 Enqueuing TRX control command 'CMD NOHANDOVER 6 0' 20181123044720703 DL1C l1sap.c:648 deactivate confirm chan_nr=TCH/F on TS6 trx=0 20181123044720703 DRSL rsl.c:714 (bts=0,trx=0,ts=6,ss=0) not sending REL ACK 20181123044720703 DRSL rsl.c:2264 (bts=0,trx=0,ts=6,ss=0) PDCH DEACT operation: channel disconnected, will reconnect as TCH 20181123044720703 DL1C scheduler.c:593 Configuring multiframe with TCH/F+SACCH trx=0 ts=6 20181123044720703 DTRX trx_if.c:242 Enqueuing TRX control command 'CMD SETSLOT 6 1' 20181123044720703 DL1C 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 rsl.c:2339 (bts=0,trx=0,ts=6,ss=0) PDCH DEACT operation: timeslot connected as TCH/F 20181123044720703 DRSL rsl.c:2440 (bts=0,trx=0,ts=6,ss=0) TCH/F_PDCH switched to TCH/F mode (ts->flags == 0) 20181123044720703 DRSL rsl.c:2103 (bts=0,trx=0,ts=6,ss=0) Tx PDCH DEACT ACK 20181123044720704 DTRX trx_if.c:492 Response message: 'RSP NOHANDOVER 0 6' 20181123044720705 DTRX trx_if.c:492 Response message: 'RSP SETSLOT 0 6 1' Change-Id: I888de761b65c3ea8bfe623fcf009f3b2b57c926c
-rw-r--r--src/osmo-bts-trx/l1_if.c46
-rw-r--r--src/osmo-bts-trx/trx_if.c39
-rw-r--r--src/osmo-bts-trx/trx_if.h5
3 files changed, 81 insertions, 9 deletions
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index da1b554f..290ceeeb 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
+#include <inttypes.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/bits.h>
@@ -58,6 +59,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 +151,34 @@ 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 (%" PRIu8 ")\n",
+ phy_instance_name(pinst), tn);
+ return;
+ }
+
+ pchan = transceiver_chan_type_2_pchan(type);
+ if (pchan == GSM_PCHAN_UNKNOWN) {
+ LOGP(DL1C, LOGL_ERROR, "transceiver (%s) SETSLOT invalid param TS_TYPE (%" PRIu8 ")\n",
+ phy_instance_name(pinst), type);
+ return;
+ }
+
+ 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 +235,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 +814,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 abe6846d..89145576 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -189,6 +189,8 @@ void trx_if_init(struct trx_l1h *l1h)
/*! Send a new TRX control command.
* \param[inout] l1h TRX Layer1 handle to which to send command
* \param[in] criticial
+ * \param[in] cb callback function to be called when valid response is
+ * received. Type of cb depends on type of message.
* \param[in] cmd zero-terminated string containing command
* \param[in] fmt Format string (+ variable list of arguments)
* \returns 0 on success; negative on error
@@ -196,7 +198,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_cb(struct trx_l1h *l1h, int critical, void *cb, const char *cmd,
const char *fmt, ...)
{
struct trx_ctrl_msg *tcm;
@@ -231,6 +233,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)
@@ -249,6 +252,7 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
return 0;
}
+#define trx_ctrl_cmd(l1h, critical, cmd, fmt, ...) trx_ctrl_cmd_cb(l1h, critical, NULL, cmd, fmt, ##__VA_ARGS__)
/*! Send "POWEROFF" command to TRX */
int trx_if_cmd_poweroff(struct trx_l1h *l1h)
@@ -315,9 +319,9 @@ int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int 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_cb(l1h, 1, cb, "SETSLOT", "%d %d", tn, type);
}
/*! Send "RXTUNE" command to TRX: Tune Receiver to given ARFCN */
@@ -374,6 +378,7 @@ 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 +442,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 +488,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 +557,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 206f5e54..cdfbd41c 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);