dexter has uploaded this change for review.
pcu_l1_if_phy: flexible phy access
At the moment we have three different platform specific PHY interfaces,
which can be selected using a compile time option. Since those three all
are intended to be used on embedded platforms this works fine. However,
in the future we plan to add E1 phy support (PHY/CCU is attached via an
E1 line), which shall not be a compiletime distinction. It might be also
thinkable that we might even add multiple E1 phys in the future, so
multiple phy implementations must be able to co-exist.
This patch adds a generic interface that allows for the creation of PHY
modules that are able to register themselves so that they can be
selected dynamically. The "legacy" PHY implementations are not intended
to co-exist next to other PHYs, so it is possible to register them as
"solitary" modules (only one at a time, via compiletime option). For the
moment only "solitary" modules. The selection mechanism will be
introduced with the first resident PHY implementation (Ericsson E1 CCU
support)
Change-Id: I8692d1bd5d137a17cf596ee2914722f419c9978d
Related: OS#5198
---
M src/Makefile.am
M src/gprs_pcu.h
M src/gprs_rlcmac_sched.cpp
M src/osmo-bts-litecell15/lc15_l1_if.c
M src/osmo-bts-oc2g/oc2g_l1_if.c
M src/osmo-bts-sysmo/sysmo_l1_if.c
M src/osmobts_sock.c
M src/pcu_l1_if.cpp
A src/pcu_l1_if_phy.c
M src/pcu_l1_if_phy.h
M src/pcu_main.cpp
11 files changed, 231 insertions(+), 58 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/41/31341/1
diff --git a/src/Makefile.am b/src/Makefile.am
index e747d74..682c4d9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,6 +54,7 @@
gprs_ms_storage.cpp \
gprs_pcu.c \
pcu_l1_if.cpp \
+ pcu_l1_if_phy.c \
pcu_vty.c \
pcu_vty_functions.cpp \
mslot_class.c \
diff --git a/src/gprs_pcu.h b/src/gprs_pcu.h
index a9e40ea..da17aae 100644
--- a/src/gprs_pcu.h
+++ b/src/gprs_pcu.h
@@ -32,6 +32,8 @@
#include "neigh_cache.h"
+#include <pcu_l1_if_phy.h>
+
#define LLC_CODEL_DISABLE 0
#define LLC_CODEL_USE_DEFAULT (-1)
@@ -134,6 +136,8 @@
struct si_cache *si_cache; /* ARFC+BSIC -> CGI PS cache */
struct osmo_timer_list update_stats_timer; /* Used to update some time_cc stats periodically */
+
+ struct l1if_phy phy;
};
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index 314fd58..4d07e06 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -487,11 +487,14 @@
const unsigned num_tbfs = pdch->num_tbfs(GPRS_RLCMAC_DL_TBF)
+ pdch->num_tbfs(GPRS_RLCMAC_UL_TBF);
bool skip_idle = (num_tbfs == 0);
-#ifdef ENABLE_DIRECT_PHY
- /* In DIRECT_PHY mode we want to always submit something to L1 in
- * TRX0, since BTS is not preparing dummy bursts on idle TS for us */
- skip_idle = skip_idle && trx != 0;
-#endif
+
+ /* Direct PHY access */
+ if (the_pcu->phy.l1if_pdch_req) {
+ /* In DIRECT_PHY mode we want to always submit something to L1 in
+ * TRX0, since BTS is not preparing dummy bursts on idle TS for us */
+ skip_idle = skip_idle && trx != 0;
+ }
+
if (!skip_idle && (msg = sched_dummy())) {
/* increase counter */
gsmtap_cat = PCU_GSMTAP_C_DL_DUMMY;
diff --git a/src/osmo-bts-litecell15/lc15_l1_if.c b/src/osmo-bts-litecell15/lc15_l1_if.c
index 053844f..4c91c17 100644
--- a/src/osmo-bts-litecell15/lc15_l1_if.c
+++ b/src/osmo-bts-litecell15/lc15_l1_if.c
@@ -132,7 +132,7 @@
}
/* connect PDTCH */
-int l1if_connect_pdch(void *obj, uint8_t ts)
+static int l1if_connect_pdch(void *obj, uint8_t ts)
{
struct lc15l1_hdl *fl1h = obj;
struct msgb *msg = l1p_msgb_alloc();
@@ -323,8 +323,8 @@
}
/* send packet data request to L1 */
-int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
- uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
+static int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
+ uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
{
struct lc15l1_hdl *fl1h = obj;
struct msgb *msg;
@@ -362,7 +362,7 @@
return 0;
}
-void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap)
+static void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap)
{
struct lc15l1_hdl *fl1h;
int rc;
@@ -391,7 +391,7 @@
return fl1h;
}
-int l1if_close_pdch(void *obj)
+static int l1if_close_pdch(void *obj)
{
struct lc15l1_hdl *fl1h = obj;
if (fl1h)
@@ -399,3 +399,22 @@
talloc_free(fl1h);
return 0;
}
+
+static void init_phy(void *ctx)
+{
+ return;
+}
+
+static void use_phy(struct l1if_phy *phy)
+{
+ phy->l1if_open_pdch = &l1if_open_pdch;
+ phy->l1if_connect_pdch = &l1if_connect_pdch;
+ phy->l1if_pdch_req = &l1if_pdch_req;
+ phy->l1if_close_pdch = &l1if_close_pdch;
+}
+
+static __attribute__((constructor)) void on_dso_load(void)
+{
+ static const uint8_t name[] = "LC15BTS";
+ pcu_l1if_phy_register(name, &er_ccu_init, &er_ccu_use, true);
+}
diff --git a/src/osmo-bts-oc2g/oc2g_l1_if.c b/src/osmo-bts-oc2g/oc2g_l1_if.c
index 1ea0b26..8d74adc 100644
--- a/src/osmo-bts-oc2g/oc2g_l1_if.c
+++ b/src/osmo-bts-oc2g/oc2g_l1_if.c
@@ -133,7 +133,7 @@
}
/* connect PDTCH */
-int l1if_connect_pdch(void *obj, uint8_t ts)
+static int l1if_connect_pdch(void *obj, uint8_t ts)
{
struct oc2gl1_hdl *fl1h = obj;
struct msgb *msg = l1p_msgb_alloc();
@@ -322,8 +322,8 @@
}
/* send packet data request to L1 */
-int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
- uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
+static int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
+ uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
{
struct oc2gl1_hdl *fl1h = obj;
struct msgb *msg;
@@ -367,7 +367,7 @@
return 0;
}
-void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap)
+static void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap)
{
struct oc2gl1_hdl *fl1h;
int rc;
@@ -396,7 +396,7 @@
return fl1h;
}
-int l1if_close_pdch(void *obj)
+static int l1if_close_pdch(void *obj)
{
struct oc2gl1_hdl *fl1h = obj;
if (fl1h)
@@ -404,3 +404,22 @@
talloc_free(fl1h);
return 0;
}
+
+static void init_phy(void *ctx)
+{
+ return;
+}
+
+static void use_phy(struct l1if_phy *phy)
+{
+ phy->l1if_open_pdch = &l1if_open_pdch;
+ phy->l1if_connect_pdch = &l1if_connect_pdch;
+ phy->l1if_pdch_req = &l1if_pdch_req;
+ phy->l1if_close_pdch = &l1if_close_pdch;
+}
+
+static __attribute__((constructor)) void on_dso_load(void)
+{
+ static const uint8_t name[] = "OC2GBTS";
+ pcu_l1if_phy_register(name, &er_ccu_init, &er_ccu_use, true);
+}
diff --git a/src/osmo-bts-sysmo/sysmo_l1_if.c b/src/osmo-bts-sysmo/sysmo_l1_if.c
index 31028f5..1172f51 100644
--- a/src/osmo-bts-sysmo/sysmo_l1_if.c
+++ b/src/osmo-bts-sysmo/sysmo_l1_if.c
@@ -115,7 +115,7 @@
}
/* connect PDTCH */
-int l1if_connect_pdch(void *obj, uint8_t ts)
+static int l1if_connect_pdch(void *obj, uint8_t ts)
{
struct femtol1_hdl *fl1h = obj;
struct msgb *msg = l1p_msgb_alloc();
@@ -308,8 +308,8 @@
}
/* send packet data request to L1 */
-int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
- uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
+static int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
+ uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
{
struct femtol1_hdl *fl1h = obj;
struct msgb *msg;
@@ -347,7 +347,7 @@
return 0;
}
-void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap)
+static void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap)
{
struct femtol1_hdl *fl1h;
int rc;
@@ -373,7 +373,7 @@
return fl1h;
}
-int l1if_close_pdch(void *obj)
+static int l1if_close_pdch(void *obj)
{
struct femtol1_hdl *fl1h = obj;
if (fl1h)
@@ -381,3 +381,23 @@
talloc_free(fl1h);
return 0;
}
+
+static void init_phy(void *ctx)
+{
+ return;
+}
+
+static void use_phy(struct l1if_phy *phy)
+{
+ phy->l1if_open_pdch = &l1if_open_pdch;
+ phy->l1if_connect_pdch = &l1if_connect_pdch;
+ phy->l1if_pdch_req = &l1if_pdch_req;
+ phy->l1if_close_pdch = &l1if_close_pdch;
+}
+
+static __attribute__((constructor)) void on_dso_load(void)
+{
+ static const uint8_t name[] = "SYSMODSP";
+ pcu_l1if_phy_register(name, &er_ccu_init, &er_ccu_use, true);
+}
+
diff --git a/src/osmobts_sock.c b/src/osmobts_sock.c
index 282e33f..eb9007b 100644
--- a/src/osmobts_sock.c
+++ b/src/osmobts_sock.c
@@ -109,12 +109,11 @@
llist_for_each_entry(bts, &the_pcu->bts_list, list) {
/* disable all slots, kick all TBFs */
for (trx = 0; trx < 8; trx++) {
-#ifdef ENABLE_DIRECT_PHY
- if (bts->trx[trx].fl1h) {
- l1if_close_pdch(bts->trx[trx].fl1h);
+ /* Direct PHY access */
+ if (the_pcu->phy.l1if_close_pdch && bts->trx[trx].fl1h) {
+ the_pcu->phy.l1if_close_pdch(bts->trx[trx].fl1h);
bts->trx[trx].fl1h = NULL;
}
-#endif
for (ts = 0; ts < 8; ts++)
if (pdch_is_enabled(&bts->trx[trx].pdch[ts]))
pdch_disable(&bts->trx[trx].pdch[ts]);
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 62f02d9..86c4fb4 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -211,16 +211,16 @@
void pcu_l1if_tx_pdtch(msgb *msg, struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts, uint16_t arfcn,
uint32_t fn, uint8_t block_nr)
{
-#ifdef ENABLE_DIRECT_PHY
- if (bts->trx[trx].fl1h) {
+ /* Direct PHY access */
+ if (the_pcu->phy.l1if_pdch_req && bts->trx[trx].fl1h) {
if (!msg) /* Simply skip sending idle frames to L1 */
return;
- l1if_pdch_req(bts->trx[trx].fl1h, ts, 0, fn, arfcn, block_nr,
+ the_pcu->phy.l1if_pdch_req(bts->trx[trx].fl1h, ts, 0, fn, arfcn, block_nr,
msg->data, msg->len);
msgb_free(msg);
return;
}
-#endif
+
if (!msg) {
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PDTCH, arfcn, fn, block_nr,
NULL, 0);
@@ -239,14 +239,15 @@
{
if (data_len && the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PTCCH))
gsmtap_send(the_pcu->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PTCCH, 0, fn, 0, 0, data, data_len);
-#ifdef ENABLE_DIRECT_PHY
- if (bts->trx[trx].fl1h) {
+
+ /* Direct PHY access */
+ if (the_pcu->phy.l1if_pdch_req && bts->trx[trx].fl1h) {
if (!data_len) /* Simply skip sending idle frames to L1 */
return;
- l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len);
+ the_pcu->phy.l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len);
return;
}
-#endif
+
if (!data_len) {
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PTCCH, arfcn, fn, block_nr, NULL, 0);
return;
@@ -564,11 +565,13 @@
const unsigned num_tbfs = pdch->num_tbfs(GPRS_RLCMAC_DL_TBF)
+ pdch->num_tbfs(GPRS_RLCMAC_UL_TBF);
bool skip_idle = (num_tbfs == 0);
-#ifdef ENABLE_DIRECT_PHY
+ /* Direct PHY access */
+ if (the_pcu->phy.l1if_pdch_req) {
/* In DIRECT_PHY mode we want to always submit something to L1 in
* TRX0, since BTS is not preparing dummy bursts on idle TS for us: */
skip_idle = skip_idle && trx != 0;
-#endif
+ }
+
if (skip_idle) {
pcu_l1if_tx_ptcch(bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr,
NULL, 0);
@@ -859,25 +862,26 @@
bts->trx[trx_nr].arfcn = info_ind->trx[trx_nr].arfcn;
if ((info_ind->flags & PCU_IF_FLAG_SYSMO)
&& info_ind->trx[trx_nr].hlayer1) {
-#ifdef ENABLE_DIRECT_PHY
- LOGP(DL1IF, LOGL_DEBUG, " TRX %d hlayer1=%x\n", trx_nr,
- info_ind->trx[trx_nr].hlayer1);
+ /* Direct PHY access */
+ if (the_pcu->phy.l1if_open_pdch) {
+ LOGP(DL1IF, LOGL_DEBUG, " TRX %d hlayer1=%x\n", trx_nr,
+ info_ind->trx[trx_nr].hlayer1);
if (!bts->trx[trx_nr].fl1h)
- bts->trx[trx_nr].fl1h = l1if_open_pdch(
+ bts->trx[trx_nr].fl1h = the_pcu->phy.l1if_open_pdch(
trx_nr,
info_ind->trx[trx_nr].hlayer1,
the_pcu->gsmtap);
- if (!bts->trx[trx_nr].fl1h) {
- LOGP(DL1IF, LOGL_FATAL, "Failed to open direct "
- "DSP access for PDCH.\n");
+ if (!bts->trx[trx_nr].fl1h) {
+ LOGP(DL1IF, LOGL_FATAL, "Failed to open direct "
+ "DSP access for PDCH.\n");
+ exit(0);
+ }
+ } else {
+ LOGP(DL1IF, LOGL_FATAL, "Compiled without direct DSP "
+ "access for PDCH, but enabled at "
+ "BTS. Please deactivate it!\n");
exit(0);
}
-#else
- LOGP(DL1IF, LOGL_FATAL, "Compiled without direct DSP "
- "access for PDCH, but enabled at "
- "BTS. Please deactivate it!\n");
- exit(0);
-#endif
}
for (ts_nr = 0; ts_nr < ARRAY_SIZE(bts->trx[0].pdch); ts_nr++) {
@@ -886,12 +890,8 @@
if ((info_ind->trx[trx_nr].pdch_mask & (1 << ts_nr))) {
/* FIXME: activate dynamically at RLCMAC */
if (!pdch->is_enabled()) {
-#ifdef ENABLE_DIRECT_PHY
- if ((info_ind->flags &
- PCU_IF_FLAG_SYSMO))
- l1if_connect_pdch(
- bts->trx[trx_nr].fl1h, ts_nr);
-#endif
+ if (the_pcu->phy.l1if_connect_pdch && (info_ind->flags & PCU_IF_FLAG_SYSMO))
+ the_pcu->phy.l1if_connect_pdch(bts->trx[trx_nr].fl1h, ts_nr);
pcu_tx_act_req(bts, pdch, 1);
pdch->enable();
}
diff --git a/src/pcu_l1_if_phy.c b/src/pcu_l1_if_phy.c
new file mode 100644
index 0000000..21f2598
--- /dev/null
+++ b/src/pcu_l1_if_phy.c
@@ -0,0 +1,97 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/logging.h>
+#include <pcu_l1_if_phy.h>
+
+LLIST_HEAD(phy_list);
+
+struct l1if_phy_entry {
+ struct llist_head list;
+
+ /* Unique name to identify the phy */
+ const uint8_t *name;
+
+ /* Callback function to populate the function pointer in struct l1if_phy */
+ void (*use_phy_cb)(struct l1if_phy * phy);
+
+ /* Callback to perform early initialization steps, such as VTY */
+ void (*init_phy_cb)(void *ctx);
+
+ /* Flag to mark the phy as "solitary". When the flag is set, the phy will be selected automatically on startup
+ * by pcu_l1if_phy_init(). It is therefore also not possible to select the PHY later. The setting is intended
+ * with PHY implementations for embedded platforms, which require a compile time option.
+ * (e.g. osmo-bts-sysmo). */
+ bool solitary;
+};
+
+/* Register PHY: This function is called by the on_dso_load constructor of the phy specific implementation. It
+ * registers two callback functions. The init_phy_cb function is executed on startup. It may contain VTY initialzations
+ * or other code that is required to be executed in the early startup phase before the config file is parsed. The use
+ * callback must populate the callbacks in struct l1if_phy and may run further initialization code. Each PHY must be
+ * registered under an unique name string so that the registration entry can be identiefied later. */
+void pcu_l1if_phy_register(const uint8_t *name, void (*init_phy_cb)(void *ctx),
+ void (*use_phy_cb)(struct l1if_phy * phy), bool solitary)
+{
+ struct l1if_phy_entry *l1if_phy_entry;
+
+ l1if_phy_entry = talloc_zero(NULL, struct l1if_phy_entry);
+ l1if_phy_entry->name = name;
+ l1if_phy_entry->init_phy_cb = init_phy_cb;
+ l1if_phy_entry->use_phy_cb = use_phy_cb;
+ l1if_phy_entry->solitary = solitary;
+ llist_add(&l1if_phy_entry->list, &phy_list);
+}
+
+static phy_show(void)
+{
+ struct l1if_phy_entry *l1if_phy_entry;
+ bool first = true;
+ LOGP(DLGLOBAL, LOGL_NOTICE, "Compiled in PHY support for:");
+
+ llist_for_each_entry(l1if_phy_entry, &phy_list, list) {
+ LOGPC(DLGLOBAL, LOGL_NOTICE, "%s%s", first ? " " : " ,", l1if_phy_entry->name);
+ first = false;
+ }
+ LOGPC(DLGLOBAL, LOGL_NOTICE, "\n");
+}
+
+/* This is executed from pcu_main.cpp in the early startup phase (see also comment above) */
+void pcu_l1if_phy_init(void *ctx, struct l1if_phy *phy)
+{
+ struct l1if_phy_entry *l1if_phy_entry;
+
+ memset(phy, 0, sizeof(*phy));
+
+ phy_show();
+ llist_for_each_entry(l1if_phy_entry, &phy_list, list) {
+ l1if_phy_entry->init_phy_cb(ctx);
+ if (l1if_phy_entry->solitary) {
+ LOGP(DLGLOBAL, LOGL_ERROR, "Using PHY: %s (solitary)\n", l1if_phy_entry->name);
+ l1if_phy_entry->use_phy_cb(phy);
+ }
+ }
+}
+
+/* Use a specific phy. This will activate a spcified PHY so that it can be used. (see also comment above) */
+int pcu_l1if_phy_use(struct l1if_phy *phy, const uint8_t *name)
+{
+ struct l1if_phy_entry *l1if_phy_entry;
+
+ llist_for_each_entry(l1if_phy_entry, &phy_list, list) {
+ if (strcmp(l1if_phy_entry->name, name) == 0) {
+ LOGP(DLGLOBAL, LOGL_ERROR, "Using PHY: %s\n", l1if_phy_entry->name);
+ l1if_phy_entry->use_phy_cb(phy);
+ return 0;
+ }
+ }
+
+ LOGP(DLGLOBAL, LOGL_ERROR, "Unknown PHY: %s", name);
+ memset(phy, 0, sizeof(*phy));
+ return -EINVAL;
+}
diff --git a/src/pcu_l1_if_phy.h b/src/pcu_l1_if_phy.h
index f25bf7b..3985386 100644
--- a/src/pcu_l1_if_phy.h
+++ b/src/pcu_l1_if_phy.h
@@ -2,8 +2,16 @@
#include <stdint.h>
-void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst *gsmtap);
-int l1if_connect_pdch(void *obj, uint8_t ts);
-int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn, uint16_t arfcn, uint8_t block_nr, uint8_t *data,
- uint8_t len);
-int l1if_close_pdch(void *obj);
+struct gsmtap_inst;
+struct l1if_phy {
+ void *(*l1if_open_pdch)(uint8_t trx_no, uint32_t hlayer1, struct gsmtap_inst * gsmtap);
+ int (*l1if_connect_pdch)(void *obj, uint8_t ts);
+ int (*l1if_pdch_req)(void *obj, uint8_t ts, int is_ptcch, uint32_t fn, uint16_t arfcn, uint8_t block_nr,
+ uint8_t *data, uint8_t len);
+ int (*l1if_close_pdch)(void *obj);
+};
+
+void pcu_l1if_phy_register(const uint8_t *name, void (*init_phy_cb)(void *ctx),
+ void (*use_phy_cb)(struct l1if_phy * phy), bool solitary);
+void pcu_l1if_phy_init(void *ctx, struct l1if_phy *phy);
+int pcu_l1if_phy_use(struct l1if_phy *phy, const uint8_t *name);
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 901ee6c..bfa40dc 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -33,6 +33,7 @@
extern "C" {
#include "pcu_vty.h"
#include "coding_scheme.h"
+#include "pcu_l1_if_phy.h"
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/vty/telnet_interface.h>
@@ -250,6 +251,8 @@
osmo_cpu_sched_vty_init(tall_pcu_ctx);
logging_vty_add_deprecated_subsys(tall_pcu_ctx, "bssgp");
+ pcu_l1if_phy_init(tall_pcu_ctx, &the_pcu->phy);
+
handle_options(argc, argv);
if ((!!spoof_mcc) + (!!spoof_mnc) == 1) {
fprintf(stderr, "--mcc and --mnc must be specified "
To view, visit change 31341. To unsubscribe, or for help writing mail filters, visit settings.