refactor phy configuration in the rrc to keep track of activated scells, and cells configurations

master
Francisco Paisana 4 years ago
parent cfc77118d3
commit 4ebe92f6a3

@ -26,6 +26,7 @@
#include "srslte/common/fsm.h"
#include "srslte/common/logmap.h"
#include "srslte/interfaces/ue_interfaces.h"
#include <bitset>
namespace srsue {
@ -62,7 +63,9 @@ public:
void cell_selection_completed(bool outcome);
void in_sync();
void out_sync() { trigger(out_sync_ev{}); }
bool set_config(const srslte::phy_cfg_t& config, uint32_t cc_idx = 0);
bool set_cell_config(const srslte::phy_cfg_t& config, uint32_t cc_idx = 0);
void set_phy_to_default();
void set_phy_to_default_dedicated();
void set_config_complete();
// state getters
@ -70,6 +73,10 @@ public:
bool is_in_sync() const { return is_in_state<in_sync_st>(); }
bool is_config_pending() const { return nof_pending_configs == 0; }
srslte::span<const srslte::phy_cfg_t> current_cell_config() const { return current_cells_cfg; }
srslte::span<srslte::phy_cfg_t> current_cell_config() { return current_cells_cfg; }
const std::bitset<SRSLTE_MAX_CARRIERS>& current_config_scells() const { return current_scells_cfg; }
// FSM states
struct unknown_st {};
struct in_sync_st {};
@ -118,12 +125,16 @@ public:
};
private:
phy_interface_rrc_lte* phy = nullptr;
srslte::task_sched_handle task_sched;
srslte::event_observer<bool> cell_selection_once_observer;
std::function<void(uint32_t, uint32_t, bool)> cell_selection_always_observer;
srslte::event_dispatcher<cell_srch_res> cell_search_observers;
uint32_t nof_pending_configs = 0;
phy_interface_rrc_lte* phy = nullptr;
srslte::task_sched_handle task_sched;
srslte::event_observer<bool> cell_selection_once_observer;
std::function<void(uint32_t, uint32_t, bool)> cell_selection_always_observer;
srslte::event_dispatcher<cell_srch_res> cell_search_observers;
uint32_t nof_pending_configs = 0;
std::array<srslte::phy_cfg_t, SRSLTE_MAX_CARRIERS> current_cells_cfg = {};
std::bitset<SRSLTE_MAX_CARRIERS> current_scells_cfg = {};
bool set_cell_config_common(const srslte::phy_cfg_t& cfg, uint32_t cc_idx, bool is_set);
protected:
state_list<unknown_st, in_sync_st, out_sync_st, searching_cell, selecting_cell> states{this,

@ -198,9 +198,8 @@ private:
uint32_t cell_clean_cnt = 0;
srslte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {};
srslte::phy_cfg_t previous_phy_cfg = {};
srslte::mac_cfg_t current_mac_cfg, previous_mac_cfg = {};
bool current_scell_configured[SRSLTE_MAX_CARRIERS] = {};
void generate_as_keys();
srslte::as_security_config_t sec_cfg = {};

@ -269,8 +269,6 @@ void phy::set_timeadv(uint32_t ta_cmd)
void phy::set_activation_deactivation_scell(uint32_t cmd)
{
Info("Received SCell Activation / Deactivation command: 0x%x\n", cmd);
/* Implements 3GPP 36.321 section 6.1.3.8. Activation/Deactivation MAC Control Element*/
for (uint32_t i = 1; i < SRSLTE_MAX_CARRIERS; i++) {
bool activated = ((cmd >> i) & 0x1u) == 0x1u;

@ -44,9 +44,41 @@ void phy_controller::in_sync()
trigger(in_sync_ev{});
}
bool phy_controller::set_config(const srslte::phy_cfg_t& config, uint32_t cc_idx)
bool phy_controller::set_cell_config(const srslte::phy_cfg_t& config, uint32_t cc_idx)
{
if (phy->set_config(config, cc_idx)) {
log_h->info("Setting PHY config for cc_idx=%d\n", cc_idx);
return set_cell_config_common(config, cc_idx, true);
}
void phy_controller::set_phy_to_default()
{
log_h->info("Setting default PHY config (common and dedicated)\n");
srslte::phy_cfg_t& default_cfg = current_cells_cfg[0];
default_cfg.set_defaults();
for (uint32_t i = 0; i < SRSLTE_MAX_CARRIERS; ++i) {
set_cell_config_common(default_cfg, i, false);
}
}
void phy_controller::set_phy_to_default_dedicated()
{
log_h->info("Setting default PHY config dedicated\n");
srslte::phy_cfg_t& default_cfg_ded = current_cells_cfg[0];
default_cfg_ded.set_defaults_dedicated();
for (uint32_t i = 0; i < SRSLTE_MAX_CARRIERS; ++i) {
set_cell_config_common(default_cfg_ded, i, false);
}
}
bool phy_controller::set_cell_config_common(const srslte::phy_cfg_t& cfg, uint32_t cc_idx, bool is_set)
{
if ((is_set or cc_idx == 0 or current_scells_cfg[cc_idx]) and phy->set_config(cfg)) {
current_cells_cfg[cc_idx] = cfg;
if (cc_idx > 0) {
current_scells_cfg[cc_idx] = is_set;
}
nof_pending_configs++;
return true;
}

@ -926,12 +926,11 @@ void rrc::ho_failed()
void rrc::con_reconfig_failed()
{
// Set previous PHY/MAC configuration
phy_ctrl->set_config(previous_phy_cfg);
phy_ctrl->set_cell_config(previous_phy_cfg, 0);
mac->set_config(previous_mac_cfg);
// And restore current configs
current_mac_cfg = previous_mac_cfg;
current_phy_cfg = previous_phy_cfg;
if (security_is_activated) {
// Start the Reestablishment Procedure
@ -943,7 +942,7 @@ void rrc::con_reconfig_failed()
void rrc::handle_rrc_con_reconfig(uint32_t lcid, const rrc_conn_recfg_s& reconfig)
{
previous_phy_cfg = current_phy_cfg;
previous_phy_cfg = phy_ctrl->current_cell_config()[0];
previous_mac_cfg = current_mac_cfg;
const rrc_conn_recfg_r8_ies_s& reconfig_r8 = reconfig.crit_exts.c1().rrc_conn_recfg_r8();
@ -1203,13 +1202,14 @@ void rrc::handle_sib2()
}
// Apply PHY RR Config Common
set_phy_cfg_t_common_pdsch(&current_phy_cfg, sib2->rr_cfg_common.pdsch_cfg_common);
set_phy_cfg_t_common_pusch(&current_phy_cfg, sib2->rr_cfg_common.pusch_cfg_common);
set_phy_cfg_t_common_pucch(&current_phy_cfg, sib2->rr_cfg_common.pucch_cfg_common);
set_phy_cfg_t_common_pwr_ctrl(&current_phy_cfg, sib2->rr_cfg_common.ul_pwr_ctrl_common);
srslte::phy_cfg_t& current_pcell = phy_ctrl->current_cell_config()[0];
set_phy_cfg_t_common_pdsch(&current_pcell, sib2->rr_cfg_common.pdsch_cfg_common);
set_phy_cfg_t_common_pusch(&current_pcell, sib2->rr_cfg_common.pusch_cfg_common);
set_phy_cfg_t_common_pucch(&current_pcell, sib2->rr_cfg_common.pucch_cfg_common);
set_phy_cfg_t_common_pwr_ctrl(&current_pcell, sib2->rr_cfg_common.ul_pwr_ctrl_common);
set_phy_cfg_t_common_prach(
&current_phy_cfg, &sib2->rr_cfg_common.prach_cfg.prach_cfg_info, sib2->rr_cfg_common.prach_cfg.root_seq_idx);
set_phy_cfg_t_common_srs(&current_phy_cfg, sib2->rr_cfg_common.srs_ul_cfg_common);
&current_pcell, &sib2->rr_cfg_common.prach_cfg.prach_cfg_info, sib2->rr_cfg_common.prach_cfg.root_seq_idx);
set_phy_cfg_t_common_srs(&current_pcell, sib2->rr_cfg_common.srs_ul_cfg_common);
// According to 3GPP 36.331 v12 UE-EUTRA-Capability field descriptions
// Allow 64QAM for:
@ -1217,19 +1217,19 @@ void rrc::handle_sib2()
// ue-CategoryUL 5 and 13 when enable64QAM (with suffix)
// enable64QAM-v1270 shall be ignored if enable64QAM (without suffix) is false
if (args.ue_category == 5 || (args.release >= 10 && args.ue_category == 8)) {
set_phy_cfg_t_enable_64qam(&current_phy_cfg, sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam);
set_phy_cfg_t_enable_64qam(&current_pcell, sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam);
} else if (args.release >= 12 && sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam) {
if (args.ue_category_ul == 5 || args.ue_category_ul == 13) {
// ASN1 Generator simplifies enable64QAM-v1270 because it is an enumeration that is always true
set_phy_cfg_t_enable_64qam(&current_phy_cfg, sib2->rr_cfg_common.pusch_cfg_common_v1270.is_present());
set_phy_cfg_t_enable_64qam(&current_pcell, sib2->rr_cfg_common.pusch_cfg_common_v1270.is_present());
} else {
set_phy_cfg_t_enable_64qam(&current_phy_cfg, false);
set_phy_cfg_t_enable_64qam(&current_pcell, false);
}
} else {
set_phy_cfg_t_enable_64qam(&current_phy_cfg, false);
set_phy_cfg_t_enable_64qam(&current_pcell, false);
}
phy_ctrl->set_config(current_phy_cfg);
phy_ctrl->set_cell_config(current_pcell);
log_rr_config_common();
@ -1873,30 +1873,31 @@ void rrc::log_rr_config_common()
current_mac_cfg.rach_cfg.responseWindowSize,
current_mac_cfg.rach_cfg.contentionResolutionTimer);
const srslte::phy_cfg_t& current_pcell = phy_ctrl->current_cell_config()[0];
rrc_log->info("Set PUSCH ConfigCommon: P0_pusch=%f, DMRS cs=%d, delta_ss=%d, N_sb=%d\n",
current_phy_cfg.ul_cfg.power_ctrl.p0_ue_pusch,
current_phy_cfg.ul_cfg.dmrs.cyclic_shift,
current_phy_cfg.ul_cfg.dmrs.delta_ss,
current_phy_cfg.ul_cfg.hopping.n_sb);
current_pcell.ul_cfg.power_ctrl.p0_ue_pusch,
current_pcell.ul_cfg.dmrs.cyclic_shift,
current_pcell.ul_cfg.dmrs.delta_ss,
current_pcell.ul_cfg.hopping.n_sb);
rrc_log->info("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n",
current_phy_cfg.ul_cfg.pucch.delta_pucch_shift,
current_phy_cfg.ul_cfg.pucch.N_cs,
current_phy_cfg.ul_cfg.pucch.n1_pucch_an_cs[0][0],
current_phy_cfg.ul_cfg.pucch.n_rb_2);
current_pcell.ul_cfg.pucch.delta_pucch_shift,
current_pcell.ul_cfg.pucch.N_cs,
current_pcell.ul_cfg.pucch.n1_pucch_an_cs[0][0],
current_pcell.ul_cfg.pucch.n_rb_2);
rrc_log->info("Set PRACH ConfigCommon: SeqIdx=%d, HS=%s, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n",
current_phy_cfg.prach_cfg.root_seq_idx,
current_phy_cfg.prach_cfg.hs_flag ? "yes" : "no",
current_phy_cfg.prach_cfg.freq_offset,
current_phy_cfg.prach_cfg.zero_corr_zone,
current_phy_cfg.prach_cfg.config_idx);
current_pcell.prach_cfg.root_seq_idx,
current_pcell.prach_cfg.hs_flag ? "yes" : "no",
current_pcell.prach_cfg.freq_offset,
current_pcell.prach_cfg.zero_corr_zone,
current_pcell.prach_cfg.config_idx);
if (current_phy_cfg.ul_cfg.srs.configured) {
if (current_pcell.ul_cfg.srs.configured) {
rrc_log->info("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, Simult-ACKNACK=%s\n",
current_phy_cfg.ul_cfg.srs.bw_cfg,
current_phy_cfg.ul_cfg.srs.subframe_config,
current_phy_cfg.ul_cfg.srs.simul_ack ? "yes" : "no");
current_pcell.ul_cfg.srs.bw_cfg,
current_pcell.ul_cfg.srs.subframe_config,
current_pcell.ul_cfg.srs.simul_ack ? "yes" : "no");
}
}
@ -1908,39 +1909,40 @@ void rrc::apply_rr_config_common(rr_cfg_common_s* config, bool send_lower_layers
set_mac_cfg_t_rach_cfg_common(&current_mac_cfg, config->rach_cfg_common);
}
srslte::phy_cfg_t& current_pcell = phy_ctrl->current_cell_config()[0];
if (config->prach_cfg.prach_cfg_info_present) {
set_phy_cfg_t_common_prach(&current_phy_cfg, &config->prach_cfg.prach_cfg_info, config->prach_cfg.root_seq_idx);
set_phy_cfg_t_common_prach(&current_pcell, &config->prach_cfg.prach_cfg_info, config->prach_cfg.root_seq_idx);
} else {
set_phy_cfg_t_common_prach(&current_phy_cfg, NULL, config->prach_cfg.root_seq_idx);
set_phy_cfg_t_common_prach(&current_pcell, NULL, config->prach_cfg.root_seq_idx);
}
if (config->pdsch_cfg_common_present) {
set_phy_cfg_t_common_pdsch(&current_phy_cfg, config->pdsch_cfg_common);
set_phy_cfg_t_common_pdsch(&current_pcell, config->pdsch_cfg_common);
}
set_phy_cfg_t_common_pusch(&current_phy_cfg, config->pusch_cfg_common);
set_phy_cfg_t_common_pusch(&current_pcell, config->pusch_cfg_common);
if (config->phich_cfg_present) {
// TODO
}
if (config->pucch_cfg_common_present) {
set_phy_cfg_t_common_pucch(&current_phy_cfg, config->pucch_cfg_common);
set_phy_cfg_t_common_pucch(&current_pcell, config->pucch_cfg_common);
}
if (config->srs_ul_cfg_common_present) {
set_phy_cfg_t_common_srs(&current_phy_cfg, config->srs_ul_cfg_common);
set_phy_cfg_t_common_srs(&current_pcell, config->srs_ul_cfg_common);
}
if (config->ul_pwr_ctrl_common_present) {
set_phy_cfg_t_common_pwr_ctrl(&current_phy_cfg, config->ul_pwr_ctrl_common);
set_phy_cfg_t_common_pwr_ctrl(&current_pcell, config->ul_pwr_ctrl_common);
}
log_rr_config_common();
if (send_lower_layers) {
mac->set_config(current_mac_cfg);
phy_ctrl->set_config(current_phy_cfg);
phy_ctrl->set_cell_config(current_pcell);
}
}
@ -1950,46 +1952,38 @@ void rrc::log_phy_config_dedicated()
return;
}
if (current_phy_cfg.dl_cfg.cqi_report.periodic_configured) {
srslte::phy_cfg_t& current_pcell = phy_ctrl->current_cell_config()[0];
if (current_pcell.dl_cfg.cqi_report.periodic_configured) {
rrc_log->info("Set cqi-PUCCH-ResourceIndex=%d, cqi-pmi-ConfigIndex=%d, cqi-FormatIndicatorPeriodic=%d\n",
current_phy_cfg.ul_cfg.pucch.n_pucch_2,
current_phy_cfg.dl_cfg.cqi_report.pmi_idx,
current_phy_cfg.dl_cfg.cqi_report.periodic_mode);
current_pcell.ul_cfg.pucch.n_pucch_2,
current_pcell.dl_cfg.cqi_report.pmi_idx,
current_pcell.dl_cfg.cqi_report.periodic_mode);
}
if (current_phy_cfg.dl_cfg.cqi_report.aperiodic_configured) {
rrc_log->info("Set cqi-ReportModeAperiodic=%d\n", current_phy_cfg.dl_cfg.cqi_report.aperiodic_mode);
if (current_pcell.dl_cfg.cqi_report.aperiodic_configured) {
rrc_log->info("Set cqi-ReportModeAperiodic=%d\n", current_pcell.dl_cfg.cqi_report.aperiodic_mode);
}
if (current_phy_cfg.ul_cfg.pucch.sr_configured) {
rrc_log->info("Set PHY config ded: SR-n_pucch=%d, SR-ConfigIndex=%d\n",
current_phy_cfg.ul_cfg.pucch.n_pucch_sr,
current_phy_cfg.ul_cfg.pucch.I_sr);
if (current_pcell.ul_cfg.pucch.sr_configured) {
rrc_log->info("Set PHY config ded: SR-n_pucch=%d, SR-ConfigIndex=%d",
current_pcell.ul_cfg.pucch.n_pucch_sr,
current_pcell.ul_cfg.pucch.I_sr);
}
if (current_phy_cfg.ul_cfg.srs.configured) {
if (current_pcell.ul_cfg.srs.configured) {
rrc_log->info("Set PHY config ded: SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, SRS-hop=%d, SRS-Ncs=%d\n",
current_phy_cfg.ul_cfg.srs.I_srs,
current_phy_cfg.ul_cfg.srs.B,
current_phy_cfg.ul_cfg.srs.n_rrc,
current_phy_cfg.ul_cfg.srs.b_hop,
current_phy_cfg.ul_cfg.srs.n_srs);
current_pcell.ul_cfg.srs.I_srs,
current_pcell.ul_cfg.srs.B,
current_pcell.ul_cfg.srs.n_rrc,
current_pcell.ul_cfg.srs.b_hop,
current_pcell.ul_cfg.srs.n_srs);
}
}
// Apply default physical common and dedicated configuration
void rrc::set_phy_default()
{
rrc_log->info("Setting default PHY config (common and dedicated)\n");
current_phy_cfg.set_defaults();
if (phy_ctrl != nullptr) {
for (uint32_t i = 0; i < SRSLTE_MAX_CARRIERS; i++) {
if (i == 0 or current_scell_configured[i]) {
phy_ctrl->set_config(current_phy_cfg, i);
current_scell_configured[i] = false;
}
}
phy_ctrl->set_phy_to_default();
} else {
rrc_log->info("RRC not initialized. Skipping default PHY config.\n");
}
@ -1998,17 +1992,8 @@ void rrc::set_phy_default()
// Apply default physical channel configs (9.2.4)
void rrc::set_phy_config_dedicated_default()
{
rrc_log->info("Setting default PHY config dedicated\n");
current_phy_cfg.set_defaults_dedicated();
if (phy_ctrl != nullptr) {
for (uint32_t i = 0; i < SRSLTE_MAX_CARRIERS; i++) {
if (i == 0 or current_scell_configured[i]) {
phy_ctrl->set_config(current_phy_cfg, i);
current_scell_configured[i] = false;
}
}
phy_ctrl->set_phy_to_default_dedicated();
} else {
rrc_log->info("RRC not initialized. Skipping default PHY config.\n");
}
@ -2019,20 +2004,17 @@ void rrc::apply_phy_config_dedicated(const phys_cfg_ded_s& phy_cnfg, bool is_han
{
rrc_log->info("Applying PHY config dedicated\n");
set_phy_cfg_t_dedicated_cfg(&current_phy_cfg, phy_cnfg);
srslte::phy_cfg_t& current_pcell = phy_ctrl->current_cell_config()[0];
set_phy_cfg_t_dedicated_cfg(&current_pcell, phy_cnfg);
if (is_handover) {
current_phy_cfg.ul_cfg.pucch.sr_configured = false;
current_phy_cfg.dl_cfg.cqi_report.periodic_configured = false;
current_phy_cfg.dl_cfg.cqi_report.aperiodic_configured = false;
current_pcell.ul_cfg.pucch.sr_configured = false;
current_pcell.dl_cfg.cqi_report.periodic_configured = false;
current_pcell.dl_cfg.cqi_report.aperiodic_configured = false;
}
log_phy_config_dedicated();
if (phy_ctrl != nullptr) {
phy_ctrl->set_config(current_phy_cfg);
} else {
rrc_log->info("RRC not initialized. Skipping PHY config.\n");
}
phy_ctrl->set_cell_config(current_pcell);
}
void rrc::apply_phy_scell_config(const scell_to_add_mod_r10_s& scell_config, bool enable_cqi)
@ -2086,7 +2068,7 @@ void rrc::apply_phy_scell_config(const scell_to_add_mod_r10_s& scell_config, boo
}
// Initialize scell config with pcell cfg
srslte::phy_cfg_t scell_cfg = current_phy_cfg;
srslte::phy_cfg_t scell_cfg = phy_ctrl->current_cell_config()[0];
set_phy_cfg_t_scell_config(&scell_cfg, scell_config);
if (not enable_cqi) {
@ -2096,11 +2078,9 @@ void rrc::apply_phy_scell_config(const scell_to_add_mod_r10_s& scell_config, boo
if (!phy->set_scell(scell, scell_config.scell_idx_r10, earfcn)) {
rrc_log->error("Adding SCell cc_idx=%d\n", scell_config.scell_idx_r10);
} else if (!phy_ctrl->set_config(scell_cfg, scell_config.scell_idx_r10)) {
} else if (!phy_ctrl->set_cell_config(scell_cfg, scell_config.scell_idx_r10)) {
rrc_log->error("Setting SCell configuration for cc_idx=%d\n", scell_config.scell_idx_r10);
}
current_scell_configured[scell_config.scell_idx_r10] = true;
}
void rrc::log_mac_config_dedicated()

@ -1271,6 +1271,7 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause)
// Save Current RNTI before MAC Reset
mac_interface_rrc::ue_rnti_t uernti;
rrc_ptr->mac->get_rntis(&uernti);
size_t nof_scells_active = rrc_ptr->phy_ctrl->current_config_scells().count();
// 5.3.7.1 - Conditions for Reestablishment procedure
if (not rrc_ptr->security_is_activated or rrc_ptr->state != RRC_STATE_CONNECTED or
@ -1319,7 +1320,9 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause)
rrc_ptr->mac->reset();
// configure lower layers to consider the SCell(s), if configured, to be in deactivated state;
rrc_ptr->phy->set_activation_deactivation_scell(0);
if (nof_scells_active > 0) {
rrc_ptr->phy->set_activation_deactivation_scell(0);
}
// 1> apply the default physical channel configuration as specified in 9.2.4;
// Note: this is done by the MAC Reset procedure
@ -1529,8 +1532,9 @@ rrc::ho_proc::ho_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) {}
srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf)
{
Info("Starting...\n");
recfg_r8 = rrc_reconf.crit_exts.c1().rrc_conn_recfg_r8();
asn1::rrc::mob_ctrl_info_s* mob_ctrl_info = &recfg_r8.mob_ctrl_info;
recfg_r8 = rrc_reconf.crit_exts.c1().rrc_conn_recfg_r8();
asn1::rrc::mob_ctrl_info_s* mob_ctrl_info = &recfg_r8.mob_ctrl_info;
size_t nof_scells_active = rrc_ptr->phy_ctrl->current_config_scells().count();
Info("Received HO command to target PCell=%d\n", mob_ctrl_info->target_pci);
srslte::console("Received HO command to target PCell=%d, NCC=%d\n",
@ -1580,7 +1584,9 @@ srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc
rrc_ptr->rlc->reestablish();
// configure lower layers to consider the SCell(s), if configured, to be in deactivated state;
rrc_ptr->phy->set_activation_deactivation_scell(0);
if (nof_scells_active > 0) {
rrc_ptr->phy->set_activation_deactivation_scell(0);
}
// apply the value of the newUE-Identity as the C-RNTI;
rrc_ptr->mac->set_ho_rnti(recfg_r8.mob_ctrl_info.new_ue_id.to_number(), recfg_r8.mob_ctrl_info.target_pci);

Loading…
Cancel
Save