aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/l1sap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/l1sap.c')
-rw-r--r--src/common/l1sap.c85
1 files changed, 61 insertions, 24 deletions
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index c028a2c7..f5d23646 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -52,7 +52,6 @@
#include <osmo-bts/abis.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/handover.h>
-#include <osmo-bts/power_control.h>
#include <osmo-bts/msg_utils.h>
#include <osmo-bts/pcuif_proto.h>
#include <osmo-bts/cbch.h>
@@ -474,6 +473,9 @@ static bool is_fill_frame(uint8_t chan_type, const uint8_t *data, unsigned int l
switch (chan_type) {
case GSMTAP_CHANNEL_AGCH:
+ case GSMTAP_CHANNEL_SDCCH:
+ case GSMTAP_CHANNEL_TCH_F:
+ case GSMTAP_CHANNEL_TCH_H:
if (!memcmp(data, fill_frame, GSM_MACBLOCK_LEN))
return true;
break;
@@ -481,6 +483,7 @@ static bool is_fill_frame(uint8_t chan_type, const uint8_t *data, unsigned int l
if (!memcmp(data, paging_fill, GSM_MACBLOCK_LEN))
return true;
break;
+ /* FIXME: implement the same for GSMTAP_CHANNEL_PDTCH from/to PCU */
/* don't use 'default' case here as the above only conditionally return true */
}
return false;
@@ -588,6 +591,29 @@ static unsigned int calc_exprd_rach_frames(struct gsm_bts *bts, uint32_t fn)
return rach_frames_expired;
}
+static void l1sap_interf_meas_calc_avg(struct gsm_bts_trx *trx)
+{
+ unsigned int tn, ln;
+
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[tn];
+
+ for (ln = 0; ln < ARRAY_SIZE(ts->lchan); ln++) {
+ struct gsm_lchan *lchan = &ts->lchan[ln];
+
+ lchan->meas.interf_meas_avg_dbm = 0;
+ lchan->meas.interf_band = 0;
+
+ /* There must be at least one sample */
+ if (lchan->meas.interf_meas_num == 0)
+ continue;
+
+ /* Average all collected samples */
+ gsm_lchan_interf_meas_calc_avg(lchan);
+ }
+ }
+}
+
static void l1sap_interf_meas_report(struct gsm_bts *bts)
{
const uint32_t period = bts->interference.intave * 104;
@@ -598,8 +624,14 @@ static void l1sap_interf_meas_report(struct gsm_bts *bts)
if (bts->gsm_time.fn % period != 0)
return;
- llist_for_each_entry(trx, &bts->trx_list, list)
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ /* Calculate the average of all received samples */
+ l1sap_interf_meas_calc_avg(trx);
+ /* Report to the BSC over the A-bis/RSL */
rsl_tx_rf_res(trx);
+ /* Report to the PCU over the PCUIF */
+ pcu_tx_interf_ind(trx, bts->gsm_time.fn);
+ }
}
/* time information received from bts model */
@@ -635,7 +667,8 @@ static int l1sap_info_time_ind(struct gsm_bts *bts,
}
/* Report interference levels to the BSC */
- l1sap_interf_meas_report(bts);
+ if (bts_internal_flag_get(bts, BTS_INTERNAL_FLAG_INTERF_MEAS))
+ l1sap_interf_meas_report(bts);
return 0;
}
@@ -676,6 +709,7 @@ static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
uint8_t is_sub;
int16_t ta_offs_256bits;
uint16_t ber10k;
+ int16_t ci_cb;
const char *ind_name;
switch (ind_type) {
@@ -688,6 +722,7 @@ static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
is_sub = info_meas_ind->is_sub;
ta_offs_256bits = info_meas_ind->ta_offs_256bits;
ber10k = info_meas_ind->ber10k;
+ ci_cb = info_meas_ind->c_i_cb;
ind_name = "MPH INFO";
break;
case PRIM_TCH:
@@ -700,6 +735,7 @@ static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
is_sub = ph_tch_ind->is_sub;
ta_offs_256bits = ph_tch_ind->ta_offs_256bits;
ber10k = ph_tch_ind->ber10k;
+ ci_cb = ph_tch_ind->lqual_cb;
ind_name = "TCH";
break;
case PRIM_PH_DATA:
@@ -712,6 +748,7 @@ static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
is_sub = ph_data_ind->is_sub;
ta_offs_256bits = ph_data_ind->ta_offs_256bits;
ber10k = ph_data_ind->ber10k;
+ ci_cb = ph_data_ind->lqual_cb;
ind_name = "DATA";
break;
default:
@@ -727,9 +764,9 @@ static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
}
DEBUGPFN(DL1P, fn,
- "%s %s meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
+ "%s %s meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u, C/I=%d cB\n",
gsm_lchan_name(lchan), ind_name, ta_offs_256bits, ber10k,
- inv_rssi);
+ inv_rssi, ci_cb);
/* in the GPRS case we are not interested in measurement
* processing. The PCU will take care of it */
@@ -739,6 +776,7 @@ static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
memset(&ulm, 0, sizeof(ulm));
ulm.ta_offs_256bits = ta_offs_256bits;
ulm.ber10k = ber10k;
+ ulm.c_i = ci_cb;
ulm.inv_rssi = inv_rssi;
ulm.is_sub = is_sub;
@@ -1181,7 +1219,7 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
p[0] = lchan->ms_power_ctrl.current;
if (lchan->repeated_ul_sacch_active)
p[0] |= 0x40; /* See also: 3GPP TS 44.004, section 7.1 */
- p[1] = lchan->rqd_ta;
+ p[1] = lchan->ta_ctrl.current;
le = &lchan->lapdm_ch.lapdm_acch;
if (lchan->repeated_acch_capability.dl_sacch) {
/* Check if MS requests SACCH repetition and update state accordingly */
@@ -1521,11 +1559,9 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
uint8_t chan_nr, link_id;
uint8_t tn;
uint32_t fn;
- int8_t rssi;
enum osmo_ph_pres_info_type pr_info = data_ind->pdch_presence_info;
struct gsm_sacch_l1_hdr *l1_hdr;
- rssi = data_ind->rssi;
chan_nr = data_ind->chan_nr;
link_id = data_ind->link_id;
fn = data_ind->fn;
@@ -1573,7 +1609,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
/* PDTCH / PACCH frame handling */
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PDTCH, fn, trx->arfcn,
- L1SAP_FN2MACBLOCK(fn), data, len, rssi, data_ind->ber10k,
+ L1SAP_FN2MACBLOCK(fn), data, len, data_ind->rssi, data_ind->ber10k,
data_ind->ta_offs_256bits/64, data_ind->lqual_cb);
return 0;
}
@@ -1596,11 +1632,9 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
* lack the measurement report from the MS side. See
* also rsl.c:lapdm_rll_tx_cb() */
LOGPGT(DL1P, LOGL_INFO, &g_time, "Lost SACCH block, faking meas reports and ms pwr\n");
- le = &lchan->lapdm_ch.lapdm_acch;
- rsl_tx_meas_res(lchan, NULL, 0, le);
+ handle_ms_meas_report(lchan, NULL, 0);
radio_link_timeout(lchan, true);
- lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, data_ind->rssi);
}
return -EINVAL;
}
@@ -1627,9 +1661,6 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
lchan->meas.l1_info.srr_sro = l1_hdr->srr_sro;
lchan->meas.l1_info.ta = l1_hdr->ta;
lchan->meas.flags |= LC_UL_M_F_L1_VALID;
-
- lchan_ms_pwr_ctrl(lchan, data[0] & 0x1f, data_ind->rssi);
- lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) &data[5]);
} else
le = &lchan->lapdm_ch.lapdm_dcch;
@@ -1941,8 +1972,12 @@ int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
l1sap->u.data.chan_nr = RSL_CHAN_OSMO_PDCH | ts->nr;
l1sap->u.data.link_id = 0x00;
l1sap->u.data.fn = fn;
- msg->l2h = msgb_put(msg, len);
- memcpy(msg->l2h, data, len);
+ if (len) {
+ msg->l2h = msgb_put(msg, len);
+ memcpy(msg->l2h, data, len);
+ } else {
+ msg->l2h = NULL; /* Idle block */
+ }
return l1sap_down(ts->trx, l1sap);
}
@@ -2000,7 +2035,7 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
int rc;
- LOGPLCHAN(lchan, DL1C, LOGL_INFO, "activating channel %s\n", rsl_chan_nr_str(chan_nr));
+ LOGPLCHAN(lchan, DL1C, LOGL_INFO, "Activating channel %s\n", rsl_chan_nr_str(chan_nr));
lchan->s = trx->bts->radio_link_timeout.current;
@@ -2033,8 +2068,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr)
{
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
- LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivating channel chan_nr=%s trx=%d\n",
- rsl_chan_nr_str(chan_nr), trx->nr);
+ LOGPLCHAN(lchan, DL1C, LOGL_INFO, "Deactivating channel %s\n",
+ rsl_chan_nr_str(chan_nr));
if (lchan->tch.dtx.dl_amr_fsm) {
osmo_fsm_inst_free(lchan->tch.dtx.dl_amr_fsm);
@@ -2049,8 +2084,8 @@ int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr)
{
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
- LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivating sacch chan_nr=%s trx=%d\n",
- rsl_chan_nr_str(chan_nr), trx->nr);
+ LOGPLCHAN(lchan, DL1C, LOGL_INFO, "Deactivating SACCH on channel %s\n",
+ rsl_chan_nr_str(chan_nr));
return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE,
1);
@@ -2058,8 +2093,10 @@ int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr)
int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr)
{
- LOGP(DL1C, LOGL_INFO, "modifying channel chan_nr=%s trx=%d\n",
- rsl_chan_nr_str(chan_nr), trx->nr);
+ struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
+
+ LOGPLCHAN(lchan, DL1C, LOGL_INFO, "Modifying channel %s\n",
+ rsl_chan_nr_str(chan_nr));
return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_MODIFY, 0);
}