X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2F5gnrsch%2Fsch_harq_dl.c;fp=src%2F5gnrsch%2Fsch_harq_dl.c;h=c5cebed368572c219aab47292201ebd5b3978f65;hb=2c0a8253f51c046ed8f291e14e13cde42a43a109;hp=0000000000000000000000000000000000000000;hpb=e2417efa29f0d317a3ed1044ee20cc14df32e1d3;p=o-du%2Fl2.git diff --git a/src/5gnrsch/sch_harq_dl.c b/src/5gnrsch/sch_harq_dl.c new file mode 100644 index 000000000..c5cebed36 --- /dev/null +++ b/src/5gnrsch/sch_harq_dl.c @@ -0,0 +1,403 @@ +/******************************************************************************* +################################################################################ +# Copyright (c) [2017-2019] [Radisys] # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +################################################################################ + *******************************************************************************/ +#include "common_def.h" +#include "tfu.h" +#include "lrg.h" +#include "tfu.x" +#include "lrg.x" +#include "du_log.h" +#include "du_app_mac_inf.h" +#include "mac_sch_interface.h" +#include "sch.h" +#include "sch_utils.h" +#include "cm_llist.h" + +SchMacDlReleaseHarqFunc schMacDlReleaseHarqOpts[] = +{ + packSchMacDlReleaseHarq, + MacSchReleaseDlHarqProc, + packSchMacDlReleaseHarq +}; + +typedef struct schCellCb SchCellCb; +typedef struct schUeCb SchUeCb; +void schDlHqEntReset(SchCellCb *cellCb, SchUeCb *ueCb, SchDlHqEnt *hqE); +void schDlHqAddToFreeList(SchDlHqProcCb *hqP); + +/** + * @brief DL Harq entity intialization + * + * @details + * + * Function : schDlHqEntInit + * + * This function intialize DL Harq entity + * + * @param[in] SchCellCb *cellCb, cell cb pointer + * @param[in] SchUeCb *ueCb, ue cb pointer + * @return + * -# void + **/ +void schDlHqEntInit(SchCellCb *cellCb, SchUeCb *ueCb) +{ + ueCb->dlHqEnt.numHqPrcs = SCH_MAX_NUM_DL_HQ_PROC; + ueCb->dlHqEnt.maxHqTx = cellCb->cellCfg.schHqCfg.maxDlDataHqTx; + ueCb->dlHqEnt.cell = cellCb; + ueCb->dlHqEnt.ue =ueCb; + schDlHqEntReset(cellCb, ueCb, &ueCb->dlHqEnt); +} +/** + * @brief DL Harq entity Reset + * + * @details + * + * Function : schDlHqEntReset + * + * This function Reset DL Harq entity + * + * @param[in] SchCellCb *cellCb, cell cb pointer + * @param[in] SchUeCb *ueCb, ue cb pointer + * @param[in] SchDlHqEnt *hqE, Dl Harq entity pointer + * @return + * -# void + **/ +void schDlHqEntReset(SchCellCb *cellCb, SchUeCb *ueCb, SchDlHqEnt *hqE) +{ + uint8_t count = 0; + SchDlHqProcCb *hqP = NULL; + cmLListInit(&hqE->free); + cmLListInit(&hqE->inUse); + + for(count=0; count < hqE->numHqPrcs; count++) + { + hqP = &(hqE->procs[count]); + hqP->procId = count; + hqP->hqEnt = hqE; + hqP->maxHqTxPerHqP = hqE->maxHqTx; + hqP->dlHqEntLnk.node = (PTR)hqP; + hqP->dlHqProcLink.node = (PTR)hqP; + hqP->ulSlotLnk.node = (PTR)hqP; + schDlHqAddToFreeList(hqP); + } +} +/** + * @brief Add hq process to free list of DL Harq entity + * + * @details + * + * Function : schDlHqAddToFreeList + * + * This function adds hq process to free list of DL Harq entity + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @return + * -# void + **/ +void schDlHqAddToFreeList(SchDlHqProcCb *hqP) +{ + cmLListAdd2Tail(&(hqP->hqEnt->free), &hqP->dlHqEntLnk); +} +/** + * @brief Delete hq process from free list of DL Harq entity + * + * @details + * + * Function : schDlHqDeleteFromFreeList + * + * This function deletes hq process to free list of DL Harq entity + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @return + * -# void + **/ +void schDlHqDeleteFromFreeList(SchDlHqProcCb *hqP) +{ + cmLListDelFrm(&(hqP->hqEnt->free), &hqP->dlHqEntLnk); +} +/** + * @brief Add hq process to in use list of DL Harq entity + * + * @details + * + * Function : schDlHqAddToInUseList + * + * This function adds hq process to in use list of DL Harq entity + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @return + * -# void + **/ +void schDlHqAddToInUseList(SchDlHqProcCb *hqP) +{ + cmLListAdd2Tail(&(hqP->hqEnt->inUse), &hqP->dlHqEntLnk); +} +/** + * @brief Delete hq process from in use list of DL Harq entity + * + * @details + * + * Function : schDlHqDeleteFromInUseList + * + * This function deletes hq process to in use list of DL Harq entity + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @return + * -# void + **/ +void schDlHqDeleteFromInUseList(SchDlHqProcCb *hqP) +{ + cmLListDelFrm(&(hqP->hqEnt->inUse), &hqP->dlHqEntLnk); +} +/** + * @brief Get available Harq process from Harq entity + * + * @details + * + * Function : schDlGetAvlHqProcess + * + * This function fetches hq process from free list and puts in in use list + * + * @param[in] SchCellCb *cellCb, cell cb pointer + * @param[in] SchUeCb *ueCb, ue cb pointer + * @param[in] SchDlHqProcCb **hqP, Address of DL harq process pointer + * @return + * -# ROK + * -# RFAILED + **/ +uint8_t schDlGetAvlHqProcess(SchCellCb *cellCb, SchUeCb *ueCb, SchDlHqProcCb **hqP) +{ + SchDlHqProcCb *tmp; + if (ueCb->dlHqEnt.free.count == 0) + { + return RFAILED; + } + tmp = (SchDlHqProcCb*)(cmLListFirst(&(ueCb->dlHqEnt.free))->node); + if (NULLP == tmp) + { + return RFAILED; + } + schDlHqDeleteFromFreeList(tmp); + schDlHqAddToInUseList(tmp); + *hqP = tmp; + (*hqP)->maxHqTxPerHqP = ueCb->dlHqEnt.maxHqTx; + return ROK; +} +/** + * @brief Release Harq process from the DL Harq entity + * + * @details + * + * Function : schDlReleaseHqProcess + * + * This function releases Harq process from DL Harq entity + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @return + * -# void + **/ +void schDlReleaseHqProcess(SchDlHqProcCb *hqP) +{ + cmLListDeleteLList(&hqP->dlLcPrbEst.dedLcList); + cmLListDeleteLList(&hqP->dlLcPrbEst.defLcList); + schDlHqDeleteFromInUseList(hqP); + schDlHqAddToFreeList(hqP); +} + +/******************************************************************* + * + * @brief Handles sending DL HARQ process release to MAC + * + * @details + * + * Function : sendDlHarqProcReleaseToMac + * + * Functionality: + * Sends DL DL HARQ process release to MAC from SCH + * + * @params[in] + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t sendDlHarqProcReleaseToMac(SchDlHqProcCb *hqP, Inst inst) +{ + Pst pst; + SchRlsHqInfo *rlsHqInfo; + memset(&pst, 0, sizeof(Pst)); + FILL_PST_SCH_TO_MAC(pst, inst); + pst.event = EVENT_DL_REL_HQ_PROC; + + SCH_ALLOC(rlsHqInfo, sizeof(SchRlsHqInfo)); + rlsHqInfo->cellId = hqP->hqEnt->cell->cellId; + rlsHqInfo->numUes = 1; + + SCH_ALLOC(rlsHqInfo->ueHqInfo, sizeof(SchUeHqInfo)*rlsHqInfo->numUes); + rlsHqInfo->ueHqInfo[0].crnti = hqP->hqEnt->ue->crnti; + rlsHqInfo->ueHqInfo[0].hqProcId = hqP->procId; + + return(*schMacDlReleaseHarqOpts[pst.selector])(&pst, rlsHqInfo); +} +/** + * @brief Release Harq process TB from the DL Harq process + * + * @details + * + * Function : schDlReleaseHqPTb + * + * This function releases Harq process TB from DL Harq proces + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @param[in] uint8_t tbIdx, TB index + * @param[in] bool togNdi, indication to toggle NDI bit + * @return + * -# void + **/ +void schDlReleaseHqPTb(SchDlHqProcCb *hqP, uint8_t tbIdx, bool togNdi) +{ + if (TRUE == togNdi) + { + hqP->tbInfo[tbIdx].ndi ^= 1; + } + + { + hqP->tbInfo[tbIdx].isAckNackDtx = HQ_ACK; + hqP->tbInfo[tbIdx].isEnabled = FALSE; + hqP->tbInfo[tbIdx].state = HQ_TB_ACKED; + hqP->tbInfo[tbIdx].txCntr = 0; + if (HQ_TB_ACKED == hqP->tbInfo[tbIdx^1].state) + { + schDlReleaseHqProcess(hqP); + sendDlHarqProcReleaseToMac(hqP, hqP->hqEnt->cell->instIdx); + } + } +} +/** + * @brief Handles failure of HARQ process TB + * + * @details + * + * Function : schDlHqTbFail + * + * This function handles failure of HARQ process TB + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @param[in] uint8_t tbIdx, TB index + * @param[in] bool isMaxRetx, indicates max retransmission + * @return + * -# void + **/ +void schDlHqTbFail(SchDlHqProcCb *hqP, uint8_t tbIdx, bool isMaxRetx) +{ + if (isMaxRetx) + { + schDlReleaseHqPTb(hqP, tbIdx, TRUE); + } + else + { + hqP->tbInfo[tbIdx].state = HQ_TB_NACKED; + if (HQ_TB_WAITING == hqP->tbInfo[tbIdx^1].state) + { + cmLListAdd2Tail( &(hqP->hqEnt->ue->dlRetxHqList), &hqP->dlHqProcLink); + } + } +} +/** + * @brief Handles Harq feedback for MSG4 + * + * @details + * + * Function : schMsg4FeedbackUpdate + * + * This function handles Harq feedback for MSG4 + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @param[in] uint8_t fdbk, Received feedback + * @return + * -# void + **/ +void schMsg4FeedbackUpdate(SchDlHqProcCb *hqP, uint8_t fdbk) +{ + hqP->tbInfo[0].isAckNackDtx = fdbk; + hqP->tbInfo[1].isAckNackDtx = HQ_TB_ACKED; + if (HQ_TB_ACKED == hqP->tbInfo[0].isAckNackDtx) + { + schDlReleaseHqPTb(hqP, 0, TRUE); + schDlReleaseHqPTb(hqP, 1, TRUE); + schMsg4Complete(hqP->hqEnt->ue); + } + else + { + if( hqP->tbInfo[0].txCntr >= hqP->hqEnt->cell->cellCfg.schHqCfg.maxMsg4HqTx) + { + schDlReleaseHqProcess(hqP); + hqP->hqEnt->ue->msg4Proc = NULLP; + hqP->hqEnt->ue->retxMsg4HqProc = NULLP; + /* Delete UE and RA context */ + } + addUeToBeScheduled(hqP->hqEnt->cell,hqP->hqEnt->ue->ueId); + hqP->hqEnt->ue->retxMsg4HqProc = hqP; + } +} +/** + * @brief Handles Harq feedback for DL Data + * + * @details + * + * Function : schDlHqFeedbackUpdate + * + * This function handles Harq feedback for DL data + * + * @param[in] SchDlHqProcCb *hqP, DL harq process pointer + * @param[in] uint8_t fdbk1, Received feedback for TB -0 + * @param[in] uint8_t fdbk2, Received feedback for TB -1 + * @return + * -# void + **/ +void schDlHqFeedbackUpdate(SchDlHqProcCb *hqP, uint8_t fdbk1, uint8_t fdbk2) +{ + uint8_t tbIdx; + for (tbIdx = 0; tbIdx <2; tbIdx++) + { + if (HQ_TB_WAITING == hqP->tbInfo[tbIdx].state) + { + hqP->tbInfo[tbIdx].isAckNackDtx = (0 == tbIdx)?fdbk1:fdbk2; + } + if (TRUE == hqP->tbInfo[tbIdx].isEnabled) + { + if (HQ_TB_ACKED == hqP->tbInfo[tbIdx].isAckNackDtx) + { + schDlReleaseHqPTb(hqP, tbIdx, TRUE); + } + else + { + if(hqP->tbInfo[tbIdx].txCntr >= hqP->maxHqTxPerHqP) + { + schDlHqTbFail(hqP, tbIdx, TRUE); + } + else + { + schDlHqTbFail(hqP, tbIdx, FALSE); + addUeToBeScheduled(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId); + } + } + } + } +} +/********************************************************************** + End of file + **********************************************************************/