diff --git a/include/osmo-bts/pcu_if.h b/include/osmo-bts/pcu_if.h index 12a8abc93..bc30f3411 100644 --- a/include/osmo-bts/pcu_if.h +++ b/include/osmo-bts/pcu_if.h @@ -19,8 +19,7 @@ int pcu_tx_rach_ind(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit, enum ph_burst_type burst_type, uint8_t sapi); int pcu_tx_time_ind(uint32_t fn); -int pcu_tx_interf_ind(uint8_t bts_nr, uint8_t trx_nr, uint32_t fn, - const uint8_t *pdch_interf); +int pcu_tx_interf_ind(const struct gsm_bts_trx *trx, uint32_t fn); int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed); int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len); int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause); diff --git a/src/common/l1sap.c b/src/common/l1sap.c index 5c58aff7b..2b539d757 100644 --- a/src/common/l1sap.c +++ b/src/common/l1sap.c @@ -629,6 +629,8 @@ static void l1sap_interf_meas_report(struct gsm_bts *bts) 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); } } diff --git a/src/common/pcu_sock.c b/src/common/pcu_sock.c index 03f1a05d1..f8a0f55e1 100644 --- a/src/common/pcu_sock.c +++ b/src/common/pcu_sock.c @@ -559,23 +559,31 @@ int pcu_tx_time_ind(uint32_t fn) return pcu_sock_send(&bts_gsmnet, msg); } -int pcu_tx_interf_ind(uint8_t bts_nr, uint8_t trx_nr, uint32_t fn, - const uint8_t *pdch_interf) +int pcu_tx_interf_ind(const struct gsm_bts_trx *trx, uint32_t fn) { struct gsm_pcu_if_interf_ind *interf_ind; struct gsm_pcu_if *pcu_prim; struct msgb *msg; + unsigned int tn; - msg = pcu_msgb_alloc(PCU_IF_MSG_INTERF_IND, bts_nr); + msg = pcu_msgb_alloc(PCU_IF_MSG_INTERF_IND, trx->bts->nr); if (!msg) return -ENOMEM; pcu_prim = (struct gsm_pcu_if *) msg->data; interf_ind = &pcu_prim->u.interf_ind; - interf_ind->trx_nr = trx_nr; + interf_ind->trx_nr = trx->nr; interf_ind->fn = fn; - memcpy(&interf_ind->interf[0], &pdch_interf[0], - sizeof(interf_ind->interf)); + + for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { + const struct gsm_bts_trx_ts *ts = &trx->ts[tn]; + const struct gsm_lchan *lchan = &ts->lchan[0]; + + if (ts_pchan(ts) != GSM_PCHAN_PDCH) + continue; + + interf_ind->interf[tn] = -1 * lchan->meas.interf_meas_avg_dbm; + } return pcu_sock_send(&bts_gsmnet, msg); } diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index 0a907fba7..6136b1411 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -54,84 +54,69 @@ #define SCHED_FH_PARAMS_VALS(ts) \ (ts)->hopping.hsn, (ts)->hopping.maio, (ts)->hopping.arfcn_num -static void ts_report_interf_meas(const struct gsm_bts_trx_ts *ts) +static void lchan_report_interf_meas(const struct gsm_lchan *lchan) { + const struct gsm_bts_trx_ts *ts = lchan->ts; const struct l1sched_ts *l1ts = ts->priv; - unsigned int ln; + enum trx_chan_type dcch, acch; + int interf_avg; - for (ln = 0; ln < ARRAY_SIZE(ts->lchan); ln++) { - const struct gsm_lchan *lchan = &ts->lchan[ln]; - enum trx_chan_type dcch, acch; - int interf_avg; - - /* We're not interested in active channels */ - if (lchan->state == LCHAN_S_ACTIVE) - continue; - - switch (lchan->type) { - case GSM_LCHAN_SDCCH: - if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4 || - ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH) { - dcch = TRXC_SDCCH4_0 + ln; - acch = TRXC_SACCH4_0 + ln; - } else { /* SDCCH/8 otherwise */ - dcch = TRXC_SDCCH8_0 + ln; - acch = TRXC_SACCH8_0 + ln; - } - break; - case GSM_LCHAN_TCH_F: - dcch = TRXC_TCHF; - acch = TRXC_SACCHTF; - break; - case GSM_LCHAN_TCH_H: - dcch = TRXC_TCHH_0 + ln; - acch = TRXC_SACCHTH_0 + ln; - break; - default: - /* Skip other lchan types */ - continue; - } - - OSMO_ASSERT(dcch < ARRAY_SIZE(l1ts->chan_state)); - OSMO_ASSERT(acch < ARRAY_SIZE(l1ts->chan_state)); - - interf_avg = (l1ts->chan_state[dcch].meas.interf_avg + - l1ts->chan_state[acch].meas.interf_avg) / 2; - - gsm_lchan_interf_meas_push((struct gsm_lchan *) lchan, interf_avg); + /* We're not interested in active CS channels */ + if (lchan->state == LCHAN_S_ACTIVE) { + if (lchan->type != GSM_LCHAN_PDTCH) + return; } + + switch (lchan->type) { + case GSM_LCHAN_SDCCH: + if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4 || + ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH) { + dcch = TRXC_SDCCH4_0 + lchan->nr; + acch = TRXC_SACCH4_0 + lchan->nr; + } else { /* SDCCH/8 otherwise */ + dcch = TRXC_SDCCH8_0 + lchan->nr; + acch = TRXC_SACCH8_0 + lchan->nr; + } + break; + case GSM_LCHAN_TCH_F: + dcch = TRXC_TCHF; + acch = TRXC_SACCHTF; + break; + case GSM_LCHAN_TCH_H: + dcch = TRXC_TCHH_0 + lchan->nr; + acch = TRXC_SACCHTH_0 + lchan->nr; + break; + case GSM_LCHAN_PDTCH: + /* We use idle TDMA frames on PDCH */ + dcch = TRXC_IDLE; + acch = TRXC_IDLE; + break; + default: + /* Skip other lchan types */ + return; + } + + OSMO_ASSERT(dcch < ARRAY_SIZE(l1ts->chan_state)); + OSMO_ASSERT(acch < ARRAY_SIZE(l1ts->chan_state)); + + interf_avg = (l1ts->chan_state[dcch].meas.interf_avg + + l1ts->chan_state[acch].meas.interf_avg) / 2; + + gsm_lchan_interf_meas_push((struct gsm_lchan *) lchan, interf_avg); } static void bts_report_interf_meas(const struct gsm_bts *bts, const uint32_t fn) { const struct gsm_bts_trx *trx; + unsigned int tn, ln; llist_for_each_entry(trx, &bts->trx_list, list) { - uint8_t pdch_interf[8] = { 0 }; - unsigned int tn, pdch_num = 0; - for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) { const struct gsm_bts_trx_ts *ts = &trx->ts[tn]; - const struct l1sched_ts *l1ts = ts->priv; - const struct l1sched_chan_state *l1cs; - - /* PS interference reports for the PCU */ - if (ts_pchan(ts) == GSM_PCHAN_PDCH) { - l1cs = &l1ts->chan_state[TRXC_IDLE]; - /* Interference value is encoded as -x dBm */ - pdch_interf[tn] = -1 * l1cs->meas.interf_avg; - pdch_num++; - continue; - } - - /* CS interference reports for the BSC */ - ts_report_interf_meas(ts); + for (ln = 0; ln < ARRAY_SIZE(ts->lchan); ln++) + lchan_report_interf_meas(&ts->lchan[ln]); } - - /* Report interference levels on PDCH to the PCU */ - if (pdch_num > 0) - pcu_tx_interf_ind(bts->nr, trx->nr, fn, pdch_interf); } }