From 1bc8e64641cfd87c2f8e79894008f9eb830040a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teodora=20Vladi=C4=87?= Date: Thu, 26 Mar 2026 11:58:43 +0100 Subject: [PATCH] Process PRACH packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move PRACH callback in the oaioran.h/c since now used in K release. * Reset the number of PRACH packets. * Handle PRACH queue in the same manner as for PUSCH (95c8fa46). Co-authored-by: Romain Beurdouche Signed-off-by: Teodora Vladić --- radio/fhi_72/README.md | 12 +- radio/fhi_72/oaioran.c | 231 ++++++++++++++++++++++++++++++++---- radio/fhi_72/oaioran.h | 6 + radio/fhi_72/oran-init.c | 75 +++++++++--- radio/fhi_72/oran-init.h | 2 +- radio/fhi_72/oran_isolate.c | 20 +++- 6 files changed, 301 insertions(+), 45 deletions(-) diff --git a/radio/fhi_72/README.md b/radio/fhi_72/README.md index e0585d22dc..48e21220fb 100644 --- a/radio/fhi_72/README.md +++ b/radio/fhi_72/README.md @@ -28,7 +28,8 @@ It calls various helper function in the same file to set up DPDK memory buffer - `oai_xran_fh_rx_prach_callback()` through `xran_5g_prach_req()`: callback for PRACH data; not currently used and implemented in PUSCH data callback. - `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used - to unblock timing in `oai_xran_fh_rx_callback()` upon first xran call. + to unblock timing in `oai_xran_fh_rx_callback()` and `oai_xran_fh_rx_prach_callback()` + upon first xran call. More detailed information about the xran callbacks can be taken from the xran documentation. @@ -40,9 +41,10 @@ PDSCH. For PDSCH, `oran_fh_if4p5_south_out()` calls `xran_fh_tx_send_slot()` that optionally compresses IQ data, then writes it into IQ buffers of xran. -For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()` that -blocks and waits for the next slot. This is done through either a message -queue, or through polling, which in both cases depends on xran calling the -callback `oai_xran_fh_rx_callback()` as installed during xran initialization. +For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()`/ +`xran_fh_rx_prach_read_slot()` that blocks and waits for the next slot. +This is done through either a message queue, or through polling, which in both +cases depends on xran calling the callbacks `oai_xran_fh_rx_callback()`/ +`oai_xran_fh_rx_prach_callback()` as installed during xran initialization. Once unblocked, it reads first PRACH data, then PUSCH data, before returning to OAI. diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 4284912c3d..f340b08dd1 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -46,8 +46,16 @@ int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id extern notifiedFIFO_t oran_sync_fifo; #define MAX_QUEUE_LENGTH_NO_JUMP 3 atomic_int xran_queue_length = 0; +atomic_int xran_queue_prach_length = 0; +#if defined K_RELEASE +extern notifiedFIFO_t oran_sync_fifo_prach; +#endif #else volatile oran_sync_info_t oran_sync_info = {0}; +#if defined K_RELEASE +volatile oran_sync_info_t oran_sync_info_prach = {0}; +volatile bool prach_rx_awaiting = false; +#endif #endif /** @details xran-specific callback, called when all packets for given CC and @@ -184,8 +192,109 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status } // rx_sym == 7 } -/** @details Only used to unblock timing in oai_xran_fh_rx_callback() on first - * call. */ +void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status +#if defined K_RELEASE + , uint8_t mu +#endif + ) +{ +#if defined K_RELEASE + struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag; + + static int32_t last_slot = -1; + // static int32_t last_frame = -1; + + const struct xran_fh_init *fh_init = get_xran_fh_init(); + int num_ports = fh_init->xran_ports; + + const int slots_in_sf = 1 << mu; + const int sf_in_frame = 10; + + static int rx_RU[XRAN_PORTS_NUM][160] = {0}; + uint32_t tti = callback_tag->slotiId; + uint32_t frame = XranGetFrameNum(tti, 0, sf_in_frame, slots_in_sf); + uint32_t subframe = XranGetSubFrameNum(tti, slots_in_sf, sf_in_frame); + uint32_t slot = XranGetSlotNum(tti, slots_in_sf); + + uint32_t rx_sym = callback_tag->symbol & 0xFF; + uint32_t ru_id = callback_tag->oXuId; + + LOG_D(HW, "prach_rx_callback at %4d.%3d (subframe %d), rx_sym %d ru_id %d\n", frame, slot, subframe, rx_sym, ru_id); + + if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7)) + // if xran did not call xran_physide_dl_tti callback, it's not ready yet. + // wait till first callback to advance counters, because otherwise users + // would see periodic output with only "0" in stats counters + if (!first_call_set) + return; + uint32_t slot2 = slot + (subframe * slots_in_sf); + rx_RU[ru_id][slot2] = 1; + // if (last_frame > 0 && frame > 0 + // && ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023)))) + // LOG_E(HW, "Jump in frame counter last_frame %d => %d, slot %d\n", last_frame, frame, slot2); + for (int i = 0; i < num_ports; i++) { + if (rx_RU[i][slot2] == 0) + return; + } + for (int i = 0; i < num_ports; i++) + rx_RU[i][slot2] = 0; + + if (last_slot == -1 || slot2 != last_slot) { +#ifndef USE_POLLING + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(oran_sync_info_t), 0, &oran_sync_fifo_prach, NULL); + oran_sync_info_t *info = NotifiedFifoData(req); + info->tti = tti; + info->sl = slot2; + info->f = frame; + info->mu = mu; +#else + LOG_D(HW, "Writing PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot); + oran_sync_info_prach.tti = tti; + oran_sync_info_prach.sl = slot2; + oran_sync_info_prach.f = frame; + oran_sync_info_prach.mu = mu; +#endif + struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag; + uint32_t tti = callback_tag->slotiId; + uint32_t ru_id = callback_tag->oXuId; + for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { + oran_buf_list_t *bufs = get_xran_buffers(ru_idx); + struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx); + for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet. + for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) { + struct xran_prb_map *pRbMap = (struct xran_prb_map *)bufs->prachdstdecomp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMapPrach == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id); + for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { + AssertFatal(pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt <= 1, "PRACH segmentation is not supported\n"); +#ifndef USE_POLLING + info->nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt; +#else + oran_sync_info_prach.nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt; +#endif + pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt = 0; + } + } + } + } +#ifndef USE_POLLING + LOG_D(HW, "Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot); + atomic_fetch_add(&xran_queue_prach_length, 1); + pushNotifiedFIFO(&oran_sync_fifo_prach, req); +#else + prach_rx_awaiting = true; +#endif + } else + LOG_E(HW, "Cannot Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot); + last_slot = slot2; + // last_frame = frame; + } // rx_sym == 7 +#elif defined F_RELEASE + rte_pause(); +#endif +} + +/** @details Only used to unblock timing in oai_xran_fh_rx_callback()/oai_xran_fh_rx_prach_callback() + * on first call. */ int oai_physide_dl_tti_call_back(void *param #if defined K_RELEASE , uint8_t mu @@ -198,17 +307,67 @@ int oai_physide_dl_tti_call_back(void *param return 0; } -/** @brief Reads PRACH data from xran buffers. +/** @details Read PRACH data from xran buffers. + * If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data + * before writing. * - * @details Reads PRACH data from xran-specific buffers and, if I/Q compression - * (bitwidth < 16 bits) is configured, uncompresses the data. Places PRACH data - * in OAI buffer. */ -static int read_prach_data(ru_info_t *ru, int frame, int slot -#if defined K_RELEASE - , uint8_t mu -#endif - ) + * Function is blocking and waits for next frame/slot combination. It is unblocked + * by oai_xran_fh_rx_prach_callback(). If K_RELEASE, it writes the current slot into parameters + * frame/slot. If F_RELEASE, it takes the frame/slot. */ +int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *frame, int *slot) { +#if defined K_RELEASE +#ifndef USE_POLLING + // pull next even from oran_sync_fifo_prach if any + notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo_prach); + atomic_fetch_sub(&xran_queue_prach_length, 1); + oran_sync_info_t *info = NotifiedFifoData(res); + + if (xran_queue_prach_length > 0 && xran_queue_prach_length < MAX_QUEUE_LENGTH_NO_JUMP) { + LOG_D(HW, "%4d.%2d TTI processing delay detected\n", info->f, info->sl); + } else if (xran_queue_prach_length >= MAX_QUEUE_LENGTH_NO_JUMP) { + uint32_t old_f = info->f; + uint32_t old_sl = info->sl; + // set the frame/slot info to what is in the last message + notifiedFIFO_elt_t *f; + while ((f = pollNotifiedFIFO(&oran_sync_fifo_prach)) != NULL) { + atomic_fetch_sub(&xran_queue_prach_length, 1); + delNotifiedFIFO_elt(res); + res = f; + } + info = NotifiedFifoData(res); + LOG_W(HW, "PRACH TTI processing delay detected, skipping %4d.%2d => %4d.%2d\n", old_f, old_sl, info->f, info->sl); + DevAssert(xran_queue_prach_length == 0); + } + + int slot = info->sl; + int frame = info->f; + uint8_t mu = info->mu; + delNotifiedFIFO_elt(res); +#else +#error "POLLING is not supported for K release unless you know how to fix the race condition on prach_rx_awaiting" + if (!prach_rx_awaiting) { + return (0); + } else { + prach_rx_awaiting = false; + } + int slot = oran_sync_info_prach.sl; + int frame = oran_sync_info_prach.f; + uint8_t mu = oran_sync_info_prach.mu; + uint32_t tti_in = oran_sync_info_prach.tti; + + static int last_slot = -1; + LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot); + int cnt = 0; + // while (*slot == last_slot) { + while (tti_in == oran_sync_info_prach.tti) { + //*slot = oran_sync_info.sl; + cnt++; + } + LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot); + last_slot = *slot; +#endif +#endif /* calculate tti and subframe_id from frame, slot num */ int sym_idx = 0; @@ -235,19 +394,49 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot #elif defined F_RELEASE int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; #endif + int tti = slots_per_frame * (frame) + (slot); int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; + /* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */ if (ru->prach_buf) { - for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) { - for (int aa = 0; aa < ru->nb_rx; aa++) { + for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. + for (int aa = 0; aa < ru->nb_rx; aa++) { + for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) { int16_t *dst, *src; int idx = 0; oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); // hardcoded to use only first prach occasion dst = (int16_t *)ru->prach_buf[aa][0]; +#if defined K_RELEASE + struct xran_prb_map * pPrbMap = (struct xran_prb_map *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_rx_packet_ctl *p_rx_packet_ctl = &pPrbMap->sFrontHaulRxPacketCtrl[sym_idx]; +#ifndef USE_POLLING + int32_t nRxPkt = info->nRxPkt[cc_id][aa][sym_idx]; +#else + int32_t nRxPkt = oran_sync_info.nRxPkt[cc_id][aa][sym_idx]; +#endif + if (nRxPkt == 0) { + LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = 0!\n", *frame, *slot, sym_idx, aa); + memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst)); + continue; + } else if (nRxPkt > 1) { // protection + LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = %d!\n", *frame, *slot, sym_idx, aa, nRxPkt); + memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst)); + continue; + } else { + src = (int16_t *)p_rx_packet_ctl->pData[0]; + if (src == NULL) { // protection + LOG_E(HW, "read_prach %d.%d.%d saa = %d: src = NULL!!\n", *frame, *slot, sym_idx, aa); + memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst)); + continue; + } + } + num_prbu = p_rx_packet_ctl->nRBSize[0]; +#elif defined F_RELEASE src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; +#endif /* convert Network order to host order */ if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { if (sym_idx == prach_start_sym) { @@ -289,9 +478,11 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot for (idx = 0; idx < (N_ZC * 2); idx++) dst[idx] += (local_dst[idx + g_kbar]); } // COMPMETHOD_BLKFLOAT - } // aa - } // symb_indx + } // sym_idx + } // aa + } // cc_id } // ru->prach_buf + return (0); } @@ -347,8 +538,8 @@ static bool is_tdd_ul_guard_slot(const struct xran_frame_config *frame_conf, int return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1); } -/** @details Read PRACH and PUSCH data from xran buffers. If - * I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data +/** @details Read PUSCH data from xran buffers. + * If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data * before writing. Prints ON TIME counters every 128 frames. * * Function is blocking and waits for next frame/slot combination. It is unblocked @@ -423,9 +614,9 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) int tti = slots_per_frame * (*frame) + (*slot); - read_prach_data(ru, *frame, *slot -#if defined K_RELEASE - , mu + read_prach_data(ru +#if defined F_RELEASE + , *frame, *slot #endif ); diff --git a/radio/fhi_72/oaioran.h b/radio/fhi_72/oaioran.h index 0a70e74eee..324fd55283 100644 --- a/radio/fhi_72/oaioran.h +++ b/radio/fhi_72/oaioran.h @@ -21,6 +21,12 @@ typedef struct { /** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status +#if defined K_RELEASE + , uint8_t mu +#endif + ); +/** @brief xran callback for fronthaul PRACH RX, see xran_5g_prach_req(). */ +void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status #if defined K_RELEASE , uint8_t mu #endif diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 0880cac1b3..c5acd26c71 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -100,6 +100,31 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons return prbmap; } +#if defined K_RELEASE +static struct xran_prb_map get_xran_prb_map_prach(const struct xran_fh_config *f) +{ + struct xran_prb_map prbmap = { + .dir = XRAN_DIR_UL, + .xran_port = 0, + .band_id = 0, + .cc_id = 0, + .ru_port_id = 0, + .tti_id = 0, + .nPrbElm = 1, + }; + struct xran_prb_elm *e = &prbmap.prbMap[0]; + e->nStartSymb = 0; + e->numSymb = 14; + e->nRBStart = 0; + e->nRBSize = 12; + e->nBeamIndex = 0; + e->compMethod = f->ru_conf.compMeth; + e->iqWidth = f->ru_conf.iqWidth; + memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl)); + return prbmap; +} +#endif + static uint32_t next_power_2(uint32_t num) { uint32_t power = 2; @@ -244,16 +269,6 @@ static void oran_allocate_cplane_buffers(void *instHandle, printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolPrb, count1); } -/* callback not actively used */ -static void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status -#if defined K_RELEASE - , uint8_t mu -#endif - ) -{ - rte_pause(); -} - static void oran_allocate_buffers(void *handle, int xran_inst, int num_sectors, @@ -287,6 +302,9 @@ static void oran_allocate_buffers(void *handle, // DL/UL PRB mapping depending on the duplex mode struct xran_prb_map dlPm = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, 14); struct xran_prb_map ulPm = get_xran_prb_map(fh_config, XRAN_DIR_UL, 0, 14); +#if defined K_RELEASE + struct xran_prb_map prachPm = get_xran_prb_map_prach(fh_config); +#endif struct xran_prb_map dlPmMixed = {0}; struct xran_prb_map ulPmMixed = {0}; uint32_t idx = 0; @@ -314,6 +332,17 @@ static void oran_allocate_buffers(void *handle, uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu); uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm); +#if defined K_RELEASE + oran_cplane_prb_config prachConf = { + .nTddPeriod = fh_config->frame_conf.nTddPeriod, + .mixed_slot_index = idx, + .slotMap = prachPm, + .mixedSlotMap = prachPm, + }; + + uint32_t numPrbElmPrach = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&prachPm, mtu); + uint32_t size_of_prb_map_prach = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElmPrach); +#endif // PDSCH #if defined K_RELEASE @@ -352,41 +381,53 @@ static void oran_allocate_buffers(void *handle, // PRACH const uint32_t prachBufSize = PRACH_PLAYBACK_BUFFER_BYTES; oran_allocate_uplane_buffers(pi->instanceHandle, bl->prachdst, bl->bufs.prach, xran_max_antenna_nr, prachBufSize); +#if defined K_RELEASE + oran_allocate_cplane_buffers(pi->instanceHandle, + bl->prachdstdecomp, + bl->bufs.prachdecomp, + xran_max_antenna_nr, + xran_max_sections_per_slot, + mtu, + fh_config, + size_of_prb_map_prach, + &prachConf); +#elif defined F_RELEASE // PRACH decomp buffer does not have separate DPDK-allocated memory pool // bufs, it points to the same pool as the prach buffer. Unclear to me why for (uint32_t a = 0; a < xran_max_antenna_nr; ++a) { for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) { - bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j][0]; + bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j]; for (uint32_t k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++k) { struct xran_flat_buffer *fb = &bl->prachdstdecomp[a][j].pBuffers[k]; fb->pData = bl->prachdst[a][j].pBuffers[k].pData; } } } +#endif struct xran_buffer_list *src[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *srccp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *dst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *dstcp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; - struct xran_buffer_list *prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; - struct xran_buffer_list *prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; + struct xran_buffer_list *prachdst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; + struct xran_buffer_list *prachdstdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; for (uint32_t a = 0; a < XRAN_MAX_ANTENNA_NR; ++a) { for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) { src[a][j] = &bl->src[a][j]; srccp[a][j] = &bl->srccp[a][j]; dst[a][j] = &bl->dst[a][j]; dstcp[a][j] = &bl->dstcp[a][j]; - prach[a][j] = &bl->prachdst[a][j]; - prachdecomp[a][j] = &bl->prachdstdecomp[a][j]; + prachdst[a][j] = &bl->prachdst[a][j]; + prachdstdecomp[a][j] = &bl->prachdstdecomp[a][j]; } } #if defined K_RELEASE xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag, fh_config->nNumerology[0]); - xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]); + xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]); #elif defined F_RELEASE xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag); - xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag); + xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag); #endif } diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index 135e2cf307..d1d4d43ee9 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -15,7 +15,7 @@ typedef struct oran_bufs { struct xran_flat_buffer rx_prbmap[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_flat_buffer prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT]; - struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; } oran_bufs_t; typedef struct oran_buf_list { diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index fd6ba98232..b2eb9f576d 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -39,6 +39,9 @@ typedef struct { } oran_eth_state_t; notifiedFIFO_t oran_sync_fifo; +#if defined K_RELEASE +notifiedFIFO_t oran_sync_fifo_prach; +#endif int trx_oran_start(openair0_device_t *device) { @@ -279,12 +282,22 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index}; if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; +#if defined F_RELEASE + uint8_t mu = fh_cfg->frame_conf.nNumerology; +#elif defined K_RELEASE + uint8_t mu = fh_cfg->nNumerology[0]; +#endif + int slots_per_subframe = 1 << mu; uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received // PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4 nr_prach_info_t prach_info = get_prach_info(0); bool is_prach_frame = (*frame % prach_info.x == prach_info.y); - bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)); // `p.slot` = slot in which PRACH is scheduled + bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe) +#if defined K_RELEASE + , mu +#endif + ); // `p.slot` = slot in which PRACH is scheduled + bool is_prach_slot = is_prach_frame && check_xran_prach_slot; if (is_prach_slot) { ru_info.prach_buf = p.prach_buf; } else { @@ -458,6 +471,9 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device_t // create message queues for ORAN sync initNotifiedFIFO(&oran_sync_fifo); +#if defined K_RELEASE + initNotifiedFIFO(&oran_sync_fifo_prach); +#endif eth->e.flags = ETH_RAW_IF4p5_MODE; eth->e.compression = NO_COMPRESS;