From 0e40c97a76ffcf071e918e1b906cdee41cb9d48e Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 11 Oct 2013 13:32:30 +0200 Subject: dyn PDCH: Automatically deactivate/activate PDCH on TCH/F+PDCH channel Shared TCH/F+PDCH channels are handled as regular TCH/F channels. If they are activated, the PDCH mode is deactivated prior activation. After deactivation, PDCH mode is restored. --- openbsc/include/openbsc/gsm_data_shared.h | 4 +++ openbsc/src/libbsc/abis_rsl.c | 50 +++++++++++++++++++++++++++---- openbsc/src/libbsc/bsc_init.c | 4 ++- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 36cf6f7b0..44efefa39 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -254,6 +254,10 @@ struct gsm_lchan { struct gsm48_req_ref *rqd_ref; struct gsm_subscriber_connection *conn; + + /* channel activation type and handover ref */ + uint8_t act_type; + uint8_t ho_ref; #else /* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23. * Currently we don't share these headers so this is a magic number. */ diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 1aa1e5552..bb65734d3 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -42,6 +42,7 @@ #include #include #include +#include #define RSL_ALLOC_SIZE 1024 #define RSL_ALLOC_HEADROOM 128 @@ -64,10 +65,13 @@ static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan, static void do_lchan_free(struct gsm_lchan *lchan) { - /* we have an error timer pending to release that */ - if (lchan->state != LCHAN_S_REL_ERR) - rsl_lchan_set_state(lchan, LCHAN_S_NONE); lchan_free(lchan); + if (lchan->state != LCHAN_S_REL_ERR) { + /* we don't have an error timer pending to release that */ + rsl_lchan_set_state(lchan, LCHAN_S_NONE); + /* defragment TCH/F+PDCH shared channels */ + do_pdch_defrag(lchan->ts->trx->bts); + } } static uint8_t mdisc_by_msgtype(uint8_t msg_type) @@ -485,6 +489,15 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type, if (rc < 0) return rc; + /* if channel is in PDCH mode, deactivate PDCH first */ + if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH + && (lchan->ts->flags & TS_F_PDCH_MODE)) { + /* store activation type and handover reference */ + lchan->act_type = act_type; + lchan->ho_ref = ho_ref; + return rsl_ipacc_pdch_activate(lchan->ts, 0); + } + ta = lchan->rqd_ta; /* BS11 requires TA shifted by 2 bits */ @@ -655,6 +668,8 @@ static void error_timeout_cb(void *data) /* go back to the none state */ LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan)); rsl_lchan_set_state(lchan, LCHAN_S_NONE); + /* defragment TCH/F+PDCH shared channels */ + do_pdch_defrag(lchan->ts->trx->bts); } static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan); @@ -753,6 +768,11 @@ static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan) LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n", gsm_lchan_name(lchan), gsm_lchans_name(lchan->state)); + + /* Put PDCH channel back into PDCH mode first */ + if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH) + return rsl_ipacc_pdch_activate(lchan->ts, 1); + do_lchan_free(lchan); return 0; @@ -1161,6 +1181,26 @@ static int rsl_rx_hando_det(struct msgb *msg) return 0; } +static int rsl_rx_pdch_act_ack(struct msgb *msg) +{ + msg->lchan->ts->flags |= TS_F_PDCH_MODE; + + /* We have activated PDCH, so now the channel is available again. */ + do_lchan_free(msg->lchan); + + return 0; +} + +static int rsl_rx_pdch_deact_ack(struct msgb *msg) +{ + msg->lchan->ts->flags &= ~TS_F_PDCH_MODE; + + rsl_chan_activate_lchan(msg->lchan, msg->lchan->act_type, + msg->lchan->ho_ref); + + return 0; +} + static int abis_rsl_rx_dchan(struct msgb *msg) { struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg); @@ -1199,14 +1239,14 @@ static int abis_rsl_rx_dchan(struct msgb *msg) break; case RSL_MT_IPAC_PDCH_ACT_ACK: DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name); - msg->lchan->ts->flags |= TS_F_PDCH_MODE; + rc = rsl_rx_pdch_act_ack(msg); break; case RSL_MT_IPAC_PDCH_ACT_NACK: LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name); break; case RSL_MT_IPAC_PDCH_DEACT_ACK: DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name); - msg->lchan->ts->flags &= ~TS_F_PDCH_MODE; + rc = rsl_rx_pdch_deact_ack(msg); break; case RSL_MT_IPAC_PDCH_DEACT_NACK: LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name); diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 55b577b54..c1fa8308d 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -307,8 +307,10 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) { int i; - for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++) + for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++) { generate_ma_for_ts(&cur_trx->ts[i]); + cur_trx->ts[i].flags |= TS_F_PDCH_MODE; + } } } if (isd->link_type == E1INP_SIGN_RSL) -- cgit v1.2.3