diff --git a/common/utils/actor/actor.c b/common/utils/actor/actor.c index 68661ddb6d..de4022e40b 100644 --- a/common/utils/actor/actor.c +++ b/common/utils/actor/actor.c @@ -50,7 +50,8 @@ void *actor_thread(void *arg) break; } - elt->processingFunc(NotifiedFifoData(elt)); + if (elt->processingFunc) // processing function can be NULL + elt->processingFunc(NotifiedFifoData(elt)); if (elt->reponseFifo) { pushNotifiedFIFO(elt->reponseFifo, elt); } else @@ -85,3 +86,14 @@ void shutdown_actor(Actor_t *actor) abortNotifiedFIFO(&response_fifo); pthread_join(actor->thread, NULL); } + +void flush_actor(Actor_t *actor) +{ + notifiedFIFO_t response_fifo; + initNotifiedFIFO(&response_fifo); + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, &response_fifo, NULL); + pushNotifiedFIFO(&actor->fifo, elt); + elt = pullNotifiedFIFO(&response_fifo); + delNotifiedFIFO_elt(elt); + abortNotifiedFIFO(&response_fifo); +} diff --git a/common/utils/actor/actor.h b/common/utils/actor/actor.h index 474554c667..023533d2d7 100644 --- a/common/utils/actor/actor.h +++ b/common/utils/actor/actor.h @@ -49,4 +49,9 @@ void destroy_actor(Actor_t *actor); /// @param actor void shutdown_actor(Actor_t *actor); +/// @brief This function will return when all current jobs in the queue are finished. +/// The caller should make sure no new jobs are added to the queue between this function call and return. +/// @param actor +void flush_actor(Actor_t *actor); + #endif diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 5c869fa452..15154001ca 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -443,6 +443,7 @@ static void UE_synch(void *arg) { static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) { PHY_VARS_NR_UE *UE = rxtxD->UE; + const fapi_nr_config_request_t *cfg = &UE->nrUE_config; const UE_nr_rxtx_proc_t *proc = &rxtxD->proc; NR_DL_FRAME_PARMS *fp = &UE->frame_parms; @@ -466,10 +467,10 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) flags = TX_BURST_START_AND_END; } else { int slots_frame = fp->slots_per_frame; - int curr_slot = nr_ue_slot_select(&UE->nrUE_config, slot); + int curr_slot = nr_ue_slot_select(cfg, slot); if (curr_slot != NR_DOWNLINK_SLOT) { - int next_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + 1) % slots_frame); - int prev_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + slots_frame - 1) % slots_frame); + int next_slot = nr_ue_slot_select(cfg, (slot + 1) % slots_frame); + int prev_slot = nr_ue_slot_select(cfg, (slot + slots_frame - 1) % slots_frame); if (prev_slot == NR_DOWNLINK_SLOT) flags = TX_BURST_START; else if (next_slot == NR_DOWNLINK_SLOT) @@ -554,6 +555,52 @@ void processSlotTX(void *arg) TracyCZoneEnd(ctx); } +static uint64_t get_carrier_frequency(const int N_RB, const int mu, const uint32_t pointA_freq_khz) +{ + const uint64_t bw = (NR_NB_SC_PER_RB * N_RB) * MU_SCS(mu); + const uint64_t carrier_freq = (pointA_freq_khz + bw / 2) * 1000; + return carrier_freq; +} + +static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) +{ + NR_DL_FRAME_PARMS *fp = &UE->frame_parms; + // Start synchronization with a target gNB + if (UE->synch_request.received_synch_request == 1) { + // if upper layers signal BW scan we do as instructed by command line parameter + // if upper layers disable BW scan we set it to false + if (UE->synch_request.synch_req.ssb_bw_scan) + UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier; + else + UE->UE_scan_carrier = false; + UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; + + const fapi_nr_ue_carrier_config_t *cfg = &UE->nrUE_config.carrier_config; + uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency); + uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency); + if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { + fp->dl_CarrierFreq = dl_CarrierFreq; + fp->ul_CarrierFreq = ul_CarrierFreq; + nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); + UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]); + init_symbol_rotation(fp); + } + + /* Clearing UE harq while DL actors are active causes race condition. + So we let the current execution to complete here.*/ + for (int i = 0; i < NUM_DL_ACTORS; i++) { + flush_actor(UE->dl_actors + i); + } + /*TODO: Flush UL jobs */ + + clean_UE_harq(UE); + UE->is_synchronized = 0; + UE->synch_request.received_synch_request = 0; + return 0; + } + return 1; +} + static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, @@ -567,35 +614,6 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; if (IS_SOFTMODEM_NOS1 || IS_SA_MODE(get_softmodem_params())) { - // Start synchronization with a target gNB - if (UE->synch_request.received_synch_request == 1) { - fapi_nr_synch_request_t *synch_req = &UE->synch_request.synch_req; - UE->is_synchronized = 0; - // if upper layers signal BW scan we do as instructed by command line parameter - // if upper layers disable BW scan we set it to false - if (UE->synch_request.synch_req.ssb_bw_scan) - UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier; - else - UE->UE_scan_carrier = false; - UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; - UE->target_Nid_cell = synch_req->target_Nid_cell; - - uint64_t dl_bw = (12 * fp->N_RB_DL) * (15000 << fp->numerology_index); - uint64_t dl_CarrierFreq = (dl_bw >> 1) + (uint64_t)UE->nrUE_config.carrier_config.dl_frequency * 1000; - uint64_t ul_bw = (12 * fp->N_RB_UL) * (15000 << fp->numerology_index); - uint64_t ul_CarrierFreq = (ul_bw >> 1) + (uint64_t)UE->nrUE_config.carrier_config.uplink_frequency * 1000; - if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { - fp->dl_CarrierFreq = dl_CarrierFreq; - fp->ul_CarrierFreq = ul_CarrierFreq; - nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); - UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]); - init_symbol_rotation(fp); - } - - clean_UE_harq(UE); - UE->synch_request.received_synch_request = 0; - } - /* send tick to RLC and PDCP every ms */ if (proc->nr_slot_rx % fp->slots_per_subframe == 0) { void nr_rlc_tick(int frame, int subframe); @@ -928,6 +946,10 @@ void *UE_thread(void *arg) continue; } + /* check if MAC has sent sync request */ + if (handle_sync_req_from_mac(UE) == 0) + continue; + // start of normal case, the UE is in sync absolute_slot++; TracyCFrameMark; diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index 59df0ba959..359722a7be 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -72,7 +72,7 @@ int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_slot); * @param nr_slot : slot number @returns int : downlink, uplink or mixed slot type */ -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot); +int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot); /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c index f2541d21b3..4fbe241223 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c @@ -39,7 +39,7 @@ * *********************************************************************/ -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot) +int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot) { if (cfg->cell_config.frame_duplex_type == FDD) return NR_UPLINK_SLOT | NR_DOWNLINK_SLOT; @@ -47,7 +47,7 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot) int period = cfg->tdd_table_1.tdd_period_in_slots + (cfg->tdd_table_2 ? cfg->tdd_table_2->tdd_period_in_slots : 0); int rel_slot = nr_slot % period; - fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table_1; + const fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table_1; if (cfg->tdd_table_2 && rel_slot >= tdd_table->tdd_period_in_slots) { rel_slot -= tdd_table->tdd_period_in_slots; tdd_table = cfg->tdd_table_2; @@ -56,7 +56,7 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot) if (tdd_table->max_tdd_periodicity_list == NULL) // this happens before receiving TDD configuration return NR_DOWNLINK_SLOT; - fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; + const fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; // if the 1st symbol is UL the whole slot is UL if (current_slot->max_num_of_symbol_per_slot_list[0].slot_config == 1) @@ -109,7 +109,7 @@ uint8_t sl_determine_if_sidelink_slot(uint8_t sl_startsym, uint8_t sl_lensym, ui * Mixed Slot is a sidelink slot if the uplink symbols in Mixed slot * overlaps with Sidelink start symbol and number of symbols. */ -int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg, int slot, uint8_t frame_duplex_type) +int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int slot, uint8_t frame_duplex_type) { int ul_sym = 0, slot_type = 0; @@ -122,9 +122,9 @@ int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg, int slot, uint8_t fram int period = cfg->tdd_table.tdd_period_in_slots; int rel_slot = slot % period; - fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table; + const fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table; - fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; + const fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { if (current_slot->max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 094d1e5965..2f3acadeca 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -447,7 +447,7 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels, * @param nr_slot : slot number * @param frame duplex type : Frame type @returns int : 0 or Sidelink slot type */ -int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg, int nr_slot, uint8_t frame_duplex_type); +int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int nr_slot, uint8_t frame_duplex_type); void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac);