bts_model: Allow TS connect to be processed asynchronously

This commit doesn't change internal logic of any model, only the API to
be able to return result of connect TS asyncrhonously since some models
(like osmo-bts-trx) require some time to process the result. This way
PDCH ACT/DEACT (N)ACK can be sent once the result of this long process
is known. For instance, nowadays in osmo-bts-trx we PDCH (DE)ACT ACK
before getting the result from SETSLOT on the TRX iface.

With this new API, bts_model_ts_connect doesn't return any value
synchronously. Instead, it is expected to always end up calling
cb_ts_connected with the return code from the TS activation process. 0
is considered a successs, while any other value is considered an error.

Change-Id: Ie073a4397dd2f1a691968d12b15b8b42f1e1b0cf
This commit is contained in:
Pau Espin 2018-11-26 13:53:52 +01:00
parent 47c8f37c9f
commit e3cb8715f5
13 changed files with 63 additions and 39 deletions

View File

@ -60,6 +60,6 @@ void bts_model_phy_link_set_defaults(struct phy_link *plink);
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst);
int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts);
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan);
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan);
#endif

View File

@ -40,7 +40,7 @@ int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total,
int rsl_tx_delete_ind(struct gsm_bts *bts, const uint8_t *ia, uint8_t ia_len);
void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
void cb_ts_connected(struct gsm_bts_trx_ts *ts);
void cb_ts_connected(struct gsm_bts_trx_ts *ts, int rc);
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
#endif // _RSL_H */

View File

@ -2157,7 +2157,7 @@ static int rsl_tx_dyn_pdch_nack(struct gsm_lchan *lchan, bool pdch_act,
* 1. call bts_model_ts_disconnect() to disconnect TCH/F;
* 2. cb_ts_disconnected() is called when done;
* 3. call bts_model_ts_connect() to connect as PDTCH;
* 4. cb_ts_connected() is called when done;
* 4. cb_ts_connected(rc) is called when done;
* 5. instruct the PCU to enable PDTCH;
* 6. the PCU will call back with an activation request;
* 7. l1sap_info_act_cnf() will call ipacc_dyn_pdch_complete() when SAPI
@ -2171,7 +2171,7 @@ static int rsl_tx_dyn_pdch_nack(struct gsm_lchan *lchan, bool pdch_act,
* deactivations are done;
* 4. cb_ts_disconnected() is called when done;
* 5. call bts_model_ts_connect() to connect as TCH/F;
* 6. cb_ts_connected() is called when done;
* 6. cb_ts_connected(rc) is called when done;
* 7. directly call ipacc_dyn_pdch_complete(), since no further action required
* for TCH/F;
* 8. send a PDCH DEACT ACK.
@ -2276,7 +2276,8 @@ static void ipacc_dyn_pdch_ts_disconnected(struct gsm_bts_trx_ts *ts)
if (rc)
goto error_nack;
rc = bts_model_ts_connect(ts, as_pchan);
bts_model_ts_connect(ts, as_pchan);
return;
error_nack:
/* Error? then NACK right now. */
@ -2322,9 +2323,14 @@ void cb_ts_disconnected(struct gsm_bts_trx_ts *ts)
}
}
static void ipacc_dyn_pdch_ts_connected(struct gsm_bts_trx_ts *ts)
static void ipacc_dyn_pdch_ts_connected(struct gsm_bts_trx_ts *ts, int rc)
{
int rc;
if (rc) {
LOGP(DRSL, LOGL_NOTICE, "%s PDCH ACT IPA operation failed (%d) in bts model\n",
gsm_lchan_name(ts->lchan), rc);
ipacc_dyn_pdch_complete(ts, rc);
return;
}
if (ts->flags & TS_F_PDCH_DEACT_PENDING) {
if (ts->lchan[0].type != GSM_LCHAN_TCH_F)
@ -2373,12 +2379,18 @@ static void ipacc_dyn_pdch_ts_connected(struct gsm_bts_trx_ts *ts)
}
}
static void osmo_dyn_ts_connected(struct gsm_bts_trx_ts *ts)
static void osmo_dyn_ts_connected(struct gsm_bts_trx_ts *ts, int rc)
{
int rc;
struct msgb *msg = ts->dyn.pending_chan_activ;
ts->dyn.pending_chan_activ = NULL;
if (rc) {
LOGP(DRSL, LOGL_NOTICE, "%s PDCH ACT OSMO operation failed (%d) in bts model\n",
gsm_lchan_name(ts->lchan), rc);
ipacc_dyn_pdch_complete(ts, rc);
return;
}
if (!msg) {
LOGP(DRSL, LOGL_ERROR,
"%s TS re-connected, but no chan activ msg pending\n",
@ -2395,15 +2407,15 @@ static void osmo_dyn_ts_connected(struct gsm_bts_trx_ts *ts)
msgb_free(msg);
}
void cb_ts_connected(struct gsm_bts_trx_ts *ts)
void cb_ts_connected(struct gsm_bts_trx_ts *ts, int rc)
{
OSMO_ASSERT(ts);
switch (ts->pchan) {
case GSM_PCHAN_TCH_F_PDCH:
return ipacc_dyn_pdch_ts_connected(ts);
return ipacc_dyn_pdch_ts_connected(ts, rc);
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
return osmo_dyn_ts_connected(ts);
return osmo_dyn_ts_connected(ts, rc);
default:
return;
}

View File

@ -1925,13 +1925,17 @@ static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "",
ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : "");
cb_ts_connected(ts);
cb_ts_connected(ts, 0);
return 0;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
enum gsm_phys_chan_config as_pchan)
{
return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
int rc;
rc = ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
if (rc)
cb_ts_connected(ts, rc);
}

View File

@ -2070,15 +2070,19 @@ static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "",
ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : "");
cb_ts_connected(ts);
cb_ts_connected(ts, 0);
msgb_free(l1_msg);
return 0;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
enum gsm_phys_chan_config as_pchan)
{
return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
int rc;
rc = ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
if (rc)
cb_ts_connected(ts, rc);
}

View File

@ -1605,7 +1605,7 @@ static int ts_connect_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
msgb_free(resp);
cb_ts_connected(ts);
cb_ts_connected(ts, 0);
return 0;
}
@ -1805,9 +1805,10 @@ int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts)
return l1if_req_compl(fl1h, msg, ts_disconnect_cb, NULL);
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
enum gsm_phys_chan_config as_pchan)
{
int rc;
if (as_pchan == GSM_PCHAN_TCH_F_PDCH
|| as_pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
LOGP(DL1C, LOGL_ERROR,
@ -1815,8 +1816,10 @@ int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
" expected a specific pchan instead\n",
gsm_ts_and_pchan_name(ts), gsm_pchan_name(as_pchan));
exit(1);
return -EINVAL;
return;
}
return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
rc = ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
if (rc)
cb_ts_connected(ts, rc);
}

View File

@ -211,9 +211,9 @@ int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts)
return -ENOTSUP;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan)
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan)
{
return -ENOTSUP;
return;
}
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)

View File

@ -1947,13 +1947,17 @@ static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "",
ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : "");
cb_ts_connected(ts);
cb_ts_connected(ts, 0);
return 0;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
enum gsm_phys_chan_config as_pchan)
{
return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
int rc;
rc = ts_connect_as(ts, as_pchan, ts_connect_cb, NULL);
if (rc)
cb_ts_connected(ts, rc);
}

View File

@ -764,7 +764,7 @@ int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts)
return 0;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
enum gsm_phys_chan_config as_pchan)
{
int rc;
@ -773,12 +773,10 @@ int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
rc = trx_set_ts_as_pchan(ts, as_pchan);
if (rc)
return 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);
return 0;
cb_ts_connected(ts, 0);
}

View File

@ -133,10 +133,9 @@ int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts)
return -ENOTSUP;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan)
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan)
{
LOGP(DSUM, LOGL_NOTICE, "Unimplemented %s\n", __func__);
return -ENOTSUP;
}
int main(int argc, char **argv)

View File

@ -278,6 +278,6 @@ int bts_model_trx_close(struct gsm_bts_trx *trx) { return 0; }
void trx_get_hlayer1(void) {}
int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) { return 0; }
int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) { return 0; }
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) { return 0; }
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) { return; }
int bts_model_lchan_deactivate(struct gsm_lchan *lchan) { return 0; }
int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) { return 0; }

View File

@ -659,9 +659,9 @@ int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts)
return 0;
}
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan)
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan)
{
return 0;
return;
}
int bts_model_lchan_deactivate(struct gsm_lchan *lchan)

View File

@ -54,6 +54,6 @@ void bts_model_abis_close(struct gsm_bts *bts)
int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts)
{ return 0; }
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
void bts_model_ts_connect(struct gsm_bts_trx_ts *ts,
enum gsm_phys_chan_config as_pchan)
{ return 0; }
{ return; }