bsc: Adapt maximum MS Power Ctrl level based on band and MS Power class
Related: OS#4244 Change-Id: I6bff440b7797e710bca5af94fae546e5d55e6972
This commit is contained in:
parent
a29affda98
commit
7950e5d90c
|
@ -85,7 +85,7 @@ int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
|
|||
const uint8_t *data, int len);
|
||||
|
||||
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
|
||||
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
|
||||
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan);
|
||||
|
||||
/* SMSCB functionality */
|
||||
int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
|
||||
|
|
|
@ -309,6 +309,9 @@ struct gsm_subscriber_connection {
|
|||
/* pointer to "other" connection, if Call Leg Relocation was successful */
|
||||
struct gsm_subscriber_connection *other;
|
||||
} lcls;
|
||||
|
||||
/* MS Power Class, TS 05.05 sec 4.1.1 "Mobile station". 0 means unset. */
|
||||
uint8_t ms_power_class:3;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1374,6 +1377,9 @@ static inline struct gsm_bts *conn_get_bts(struct gsm_subscriber_connection *con
|
|||
return conn->lchan->ts->trx->bts;
|
||||
}
|
||||
|
||||
void conn_update_ms_power_class(struct gsm_subscriber_connection *conn, uint8_t power_class);
|
||||
void lchan_update_ms_power_ctrl_level(struct gsm_lchan *lchan, int ms_power_dbm);
|
||||
|
||||
enum {
|
||||
BTS_CTR_CHREQ_TOTAL,
|
||||
BTS_CTR_CHREQ_NO_CHANNEL,
|
||||
|
|
|
@ -293,26 +293,16 @@ int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
|
|||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
|
||||
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_bts_trx *trx = lchan->ts->trx;
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct abis_rsl_dchan_hdr *dh;
|
||||
struct msgb *msg;
|
||||
uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
|
||||
int ctl_lvl;
|
||||
|
||||
ctl_lvl = ms_pwr_ctl_lvl(bts->band, dbm);
|
||||
if (ctl_lvl < 0)
|
||||
return ctl_lvl;
|
||||
|
||||
msg = rsl_msgb_alloc();
|
||||
|
||||
lchan->ms_power = ctl_lvl;
|
||||
|
||||
if (fpc)
|
||||
lchan->ms_power |= 0x20;
|
||||
|
||||
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
|
||||
init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
|
||||
dh->chan_nr = chan_nr;
|
||||
|
|
|
@ -395,12 +395,16 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* TS 04.08 sec 9.2.15 "Location updating request" */
|
||||
static void handle_lu_request(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh;
|
||||
struct gsm48_loc_upd_req *lu;
|
||||
struct gsm48_loc_area_id lai;
|
||||
int8_t rc8;
|
||||
struct gsm_bts *bts = conn_get_bts(conn);
|
||||
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
|
||||
|
@ -416,6 +420,47 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn,
|
|||
LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
|
||||
conn->new_subscriber = 1;
|
||||
}
|
||||
|
||||
rc8 = osmo_gsm48_rfpowercap2powerclass(bts->band, lu->classmark1.pwr_lev);
|
||||
if (rc8 < 0) {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"Unable to decode RF power capability %x from classmark1 during LU.\n",
|
||||
lu->classmark1.pwr_lev);
|
||||
rc8 = 0;
|
||||
}
|
||||
conn_update_ms_power_class(conn, rc8);
|
||||
}
|
||||
|
||||
|
||||
/* TS 04.08 sec 9.2.15 "Location updating request" */
|
||||
static void handle_cm_serv_req(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh;
|
||||
struct gsm48_service_request *serv_req;
|
||||
struct gsm48_classmark2* cm2;
|
||||
int8_t rc8;
|
||||
struct gsm_bts *bts = conn_get_bts(conn);
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*serv_req)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "CM Serv Req too small to look at: %u\n", msgb_l3len(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
serv_req = (struct gsm48_service_request *) gh->data;
|
||||
|
||||
cm2 = (struct gsm48_classmark2*)(((uint8_t*)&serv_req->classmark)+1);
|
||||
/* FIXME: one classmark2 is available in libosmocore:
|
||||
cm2 = &serv_req->classmark2; */
|
||||
rc8 = osmo_gsm48_rfpowercap2powerclass(bts->band, cm2->pwr_lev);
|
||||
if (rc8 < 0) {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"Unable to decode RF power capability %x from classmark2 during CM Service Req.\n",
|
||||
cm2->pwr_lev);
|
||||
rc8 = 0;
|
||||
}
|
||||
conn_update_ms_power_class(conn, rc8);
|
||||
}
|
||||
|
||||
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
|
@ -427,6 +472,8 @@ int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
|||
if (pdisc == GSM48_PDISC_MM) {
|
||||
if (mtype == GSM48_MT_MM_LOC_UPD_REQUEST)
|
||||
handle_lu_request(conn, msg);
|
||||
else if(mtype == GSM48_MT_MM_CM_SERV_REQ)
|
||||
handle_cm_serv_req(conn, msg);
|
||||
} else if (pdisc == GSM48_PDISC_RR) {
|
||||
if (mtype == GSM48_MT_RR_PAG_RESP)
|
||||
handle_page_resp(conn, msg);
|
||||
|
@ -677,8 +724,20 @@ void bsc_cm_update(struct gsm_subscriber_connection *conn,
|
|||
const uint8_t *cm2, uint8_t cm2_len,
|
||||
const uint8_t *cm3, uint8_t cm3_len)
|
||||
{
|
||||
struct gsm48_classmark2 *cm2_parsed = (struct gsm48_classmark2 *)cm2;
|
||||
int8_t rc8;
|
||||
int rc;
|
||||
struct msgb *resp;
|
||||
struct gsm_bts *bts = conn_get_bts(conn);
|
||||
|
||||
rc8 = osmo_gsm48_rfpowercap2powerclass(bts->band, cm2_parsed->pwr_lev);
|
||||
if (rc8 < 0) {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"Unable to decode RF power capability %x from classmark1 during CM Update.\n",
|
||||
cm2_parsed->pwr_lev);
|
||||
rc8 = 0;
|
||||
}
|
||||
conn_update_ms_power_class(conn, rc8);
|
||||
|
||||
if (!msc_connected(conn))
|
||||
return;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include <netinet/in.h>
|
||||
#include <talloc.h>
|
||||
|
||||
|
@ -1685,6 +1686,67 @@ bool ts_is_usable(const struct gsm_bts_trx_ts *ts)
|
|||
return true;
|
||||
}
|
||||
|
||||
void conn_update_ms_power_class(struct gsm_subscriber_connection *conn, uint8_t power_class)
|
||||
{
|
||||
struct gsm_bts *bts = conn_get_bts(conn);
|
||||
LOGP(DRLL, LOGL_DEBUG, "MS Power class update: %" PRIu8 " -> %" PRIu8 "\n",
|
||||
conn->ms_power_class, power_class);
|
||||
|
||||
conn->ms_power_class = power_class;
|
||||
|
||||
/* If there's an associated lchan, attempt to update its max power to be
|
||||
on track with band maximum values */
|
||||
if (conn->lchan)
|
||||
lchan_update_ms_power_ctrl_level(conn->lchan, bts->ms_max_power);
|
||||
}
|
||||
|
||||
void lchan_update_ms_power_ctrl_level(struct gsm_lchan *lchan, int ms_power_dbm)
|
||||
{
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
struct gsm_subscriber_connection *conn = lchan->conn;
|
||||
int max_pwr_dbm_pwclass, new_pwr;
|
||||
|
||||
LOG_LCHAN(lchan, LOGL_DEBUG,
|
||||
"MS Power level update requested: %d dBm\n", ms_power_dbm);
|
||||
|
||||
if (!conn)
|
||||
goto ms_power_default;
|
||||
|
||||
if (conn->ms_power_class == 0)
|
||||
goto ms_power_default;
|
||||
|
||||
if ((max_pwr_dbm_pwclass = (int)ms_class_gmsk_dbm(bts->band, conn->ms_power_class)) < 0) {
|
||||
LOG_LCHAN(lchan, LOGL_INFO,
|
||||
"Failed getting max ms power for power class %" PRIu8
|
||||
" on band %s, providing default max ms power\n",
|
||||
conn->ms_power_class, gsm_band_name(bts->band));
|
||||
goto ms_power_default;
|
||||
}
|
||||
|
||||
/* Current configured max pwr is above maximum one allowed on
|
||||
current band + ms power class, so use that one. */
|
||||
if (ms_power_dbm > max_pwr_dbm_pwclass)
|
||||
ms_power_dbm = max_pwr_dbm_pwclass;
|
||||
|
||||
ms_power_default:
|
||||
if ((new_pwr = ms_pwr_ctl_lvl(bts->band, ms_power_dbm)) < 0) {
|
||||
LOG_LCHAN(lchan, LOGL_INFO,
|
||||
"Failed getting max ms power level %d on band %s,"
|
||||
" providing default max ms power\n",
|
||||
ms_power_dbm, gsm_band_name(bts->band));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_LCHAN(lchan, LOGL_DEBUG,
|
||||
"MS Power level update (power class %" PRIu8 "): %" PRIu8 " -> %d\n",
|
||||
conn ? conn->ms_power_class : 0, lchan->ms_power, new_pwr);
|
||||
|
||||
lchan->ms_power = new_pwr;
|
||||
/* FIXME: if chan is active and lchan->ms_power != new_pwr, consider
|
||||
sending an MS Power Control message (RSL) towards BTS to announce the
|
||||
new max ms power lvl, see rsl_chan_ms_power_ctrl() */
|
||||
}
|
||||
|
||||
const struct value_string lchan_activate_mode_names[] = {
|
||||
OSMO_VALUE_STRING(FOR_NONE),
|
||||
OSMO_VALUE_STRING(FOR_MS_CHANNEL_REQUEST),
|
||||
|
|
|
@ -511,6 +511,7 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p
|
|||
struct osmo_mgcpc_ep_ci *use_mgwep_ci;
|
||||
struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;
|
||||
struct lchan_activate_info *info = &lchan->activate.info;
|
||||
int ms_power_dbm;
|
||||
|
||||
if (lchan->release.requested) {
|
||||
lchan_fail("Release requested while activating");
|
||||
|
@ -522,11 +523,12 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p
|
|||
/* If there is a previous lchan, and the new lchan is on the same cell as previous one,
|
||||
* take over power and TA values. Otherwise, use max power and zero TA. */
|
||||
if (old_lchan && old_lchan->ts->trx->bts == bts) {
|
||||
lchan->ms_power = old_lchan->ms_power;
|
||||
ms_power_dbm = ms_pwr_dbm(bts->band, old_lchan->ms_power);
|
||||
lchan_update_ms_power_ctrl_level(lchan, ms_power_dbm >= 0 ? ms_power_dbm : bts->ms_max_power);
|
||||
lchan->bs_power = old_lchan->bs_power;
|
||||
lchan->rqd_ta = old_lchan->rqd_ta;
|
||||
} else {
|
||||
lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
|
||||
lchan_update_ms_power_ctrl_level(lchan, bts->ms_max_power);
|
||||
/* Upon last entering the UNUSED state, from lchan_reset():
|
||||
* - bs_power is still zero, 0dB reduction, output power = Pn.
|
||||
* - TA is still zero, to be determined by RACH. */
|
||||
|
|
Loading…
Reference in New Issue