osmocom-bb/src/host/trxcon/src/trxcon_inst.c

108 lines
2.6 KiB
C
Raw Normal View History

/*
* OsmocomBB <-> SDR connection bridge
*
* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <stdint.h>
#include <osmocom/core/fsm.h>
#include <osmocom/core/talloc.h>
#include <osmocom/bb/trxcon/trxcon.h>
#include <osmocom/bb/trxcon/trxcon_fsm.h>
#include <osmocom/bb/l1sched/l1sched.h>
#include <osmocom/bb/l1sched/logging.h>
#include <osmocom/bb/l1gprs.h>
extern int g_logc_l1c;
extern int g_logc_l1d;
void trxcon_set_log_cfg(const int *logc, unsigned int logc_num)
{
int schc = DLGLOBAL;
int schd = DLGLOBAL;
for (unsigned int i = 0; i < logc_num; i++) {
switch ((enum trxcon_log_cat)i) {
case TRXCON_LOGC_FSM:
trxcon_fsm_def.log_subsys = logc[i];
break;
case TRXCON_LOGC_L1C:
g_logc_l1c = logc[i];
break;
case TRXCON_LOGC_L1D:
g_logc_l1d = logc[i];
break;
case TRXCON_LOGC_SCHC:
schc = logc[i];
break;
case TRXCON_LOGC_SCHD:
schd = logc[i];
break;
case TRXCON_LOGC_GPRS:
l1gprs_logging_init(logc[i]);
break;
}
}
l1sched_logging_init(schc, schd);
}
trxcon: get rid of the timer driven clock module trxcon was heavily inspired by osmo-bts-trx, and among with many other scheduling related parts also inherited the timer driven clock module. This clock module is driving the Uplink burst scheduling, just like it does drive the Downlink burst scheduling in osmo-bts-trx. Just like in osmo-bts-trx, the clock module relies on periodic CLCK indications from the PHY, which are needed to compensate for the clock drifting. The key difference is that trxcon is using Downlink bursts as the CLCK indications, see 'bi.fn % 51' in trx_data_rx_cb(). This is possible because the MS is a clock slave of the BTS: the MS PHY needs to sync its freq. and clock first, and only after that it can Rx and Tx. So far we've had no problems with the clock module in trxcon until we started adding GPRS support and integrated the l1gprs. While the CS domain is quite flexible in terms of timings and delays, the PS domain is a lot more sensetive to the timing issues. Sometimes it happens that the trxcon's clock module is ticking quicker than it should, resulting in Uplink PDCH blocks being scheduled earlier than the respective Downlink PDCH blocks are received: 20230502021957724 l1sched_pull_burst(): PDTCH/U Tx time (fn=56103) 20230502021957744 (PDCH-7) Rx DL BLOCK.ind (fn=56103, len=23): ... 20230502021957747 l1sched_pull_burst(): PDTCH/U Tx time (fn=56108) 20230502021957765 l1sched_pull_burst(): PDTCH/U Tx time (fn=56112) 20230502021957767 (PDCH-7) Rx DL BLOCK.ind (fn=56108, len=23): ... 20230502021957768 (PDCH-7) Rx UL BLOCK.req (fn=56112, len=54): ... 20230502021957784 l1sched_pull_burst(): PDTCH/U Tx time (fn=56116) 20230502021957784 TS7-PDTCH dropping Tx primitive (current Fn=56116, prim Fn=56112) This is impossible in reality, because Uplink is intentionally lagging behind Downlink by 3 TDMA timeslot periods. In a virtual setup this causes sporadic dropping of Uplink PDCH blocks, as can be seen from the logging snippet above, and significantly degrades the RLC/MAC performance for GPRS. Let's remove the internal clock module and trigger the Uplink burst transmission each time we receive a Downlink burst. This helps to overcome the GPRS scheduling issues and replicates the approach of osmo-trx-ms more closely. Change-Id: Ic8a5b6277c6b16392026e0557376257d71c9d230 Related: OS#5500
2022-11-26 01:07:25 +00:00
struct trxcon_inst *trxcon_inst_alloc(void *ctx, unsigned int id)
{
struct trxcon_inst *trxcon;
struct osmo_fsm_inst *fi;
fi = osmo_fsm_inst_alloc(&trxcon_fsm_def, ctx, NULL, LOGL_DEBUG, NULL);
OSMO_ASSERT(fi != NULL);
trxcon = talloc_zero(fi, struct trxcon_inst);
OSMO_ASSERT(trxcon != NULL);
fi->priv = trxcon;
trxcon->fi = fi;
osmo_fsm_inst_update_id_f(fi, "%u", id);
trxcon->id = id;
/* Logging context to be used by both l1ctl and l1sched modules */
trxcon->log_prefix = talloc_asprintf(trxcon, "%s: ", osmo_fsm_inst_name(fi));
/* Init scheduler */
const struct l1sched_cfg sched_cfg = {
.log_prefix = trxcon->log_prefix,
};
trxcon->sched = l1sched_alloc(trxcon, &sched_cfg, trxcon);
if (trxcon->sched == NULL) {
trxcon_inst_free(trxcon);
return NULL;
}
trxcon->phy_quirks.fbsb_extend_fns = 0;
return trxcon;
}
void trxcon_inst_free(struct trxcon_inst *trxcon)
{
if (trxcon == NULL || trxcon->fi == NULL)
return;
osmo_fsm_inst_term(trxcon->fi, OSMO_FSM_TERM_REQUEST, NULL);
}