summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-10-11 13:32:30 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2013-10-11 13:32:30 +0200
commit0e40c97a76ffcf071e918e1b906cdee41cb9d48e (patch)
tree94ee6637ba73495e19d1a488f59d5011a5d13ed5
parent3c38175f4f0546feeec455f5129be2be7073e495 (diff)
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.
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h4
-rw-r--r--openbsc/src/libbsc/abis_rsl.c50
-rw-r--r--openbsc/src/libbsc/bsc_init.c4
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 <osmocom/abis/e1_input.h>
#include <osmocom/gsm/rsl.h>
#include <osmocom/core/talloc.h>
+#include <openbsc/pdch_defrag.h>
#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)