1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
19 /********************************************************************20**
21 Name: LTE-RLC Layer - Lower Interface Functions
25 Desc: Source code for RLC Lower Interface Module.
26 This file contains following functions
37 **********************************************************************/
38 static const char* RLOG_MODULE_NAME="LIM";
39 static int RLOG_MODULE_ID=2048;
40 static int RLOG_FILE_ID=196;
44 * @brief RLC Lower Interface module
47 #define KW_MODULE KW_DBGMASK_INF
50 /* header (.h) include files */
51 #include "common_def.h"
52 #include "lkw.h" /* LKW defines */
53 #include "ckw.h" /* CKW defines */
54 #include "kwu.h" /* KWU defines */
55 #include "rgu.h" /* RGU defines */
57 #include "kw_env.h" /* RLC environment options */
59 #include "kw.h" /* RLC defines */
64 /* extern (.x) include files */
65 #include "lkw.x" /* LKW */
66 #include "ckw.x" /* CKW */
67 #include "kwu.x" /* KWU */
68 #include "rgu.x" /* RGU */
74 #include "rlc_utils.h"
78 #endif /* __cplusplus */
81 /*****************************************************************************
83 ****************************************************************************/
85 * @brief Handler for bind confirmation from MAC.
88 * This function handles the bind confirmation received from MAC. If the
89 * bind was successful changes the state of the SAP to KW_SAP_BND
90 * else KW_SAP_CFG. Sends an alarm to LM in any case
92 * @param[in] pst Post structure
93 * @param[in] suId Service User ID
94 * @param[in] status Status whether the bind was successful or not
102 PUBLIC S16 KwLiRguBndCfm
109 PUBLIC S16 KwLiRguBndCfm (pst, suId, status)
115 U16 event; /* Event */
116 U16 cause; /* Cause */
117 KwRguSapCb *rguSap; /* RGU SAP Control Block */
122 #if (ERRCLASS & ERRCLS_INT_PAR)
123 if (pst->dstInst >= MAX_RLC_INSTANCES)
128 tRlcCb = RLC_GET_RLCCB(pst->dstInst);
130 RLOG2(L_DEBUG,"KwLiRguBndCfm(suId(%d), status(%d)", suId, status);
132 #if (ERRCLASS & ERRCLS_INT_PAR)
133 if (tRlcCb->init.cfgDone != TRUE)
135 RLOG0(L_FATAL,"General configuration not done");
137 KW_SEND_SAPID_ALARM(tRlcCb,suId,LKW_EVENT_LI_BND_CFM, LCM_CAUSE_INV_STATE);
142 if ((suId >= tRlcCb->genCfg.maxRguSaps) || (suId < 0))
144 RLOG0(L_ERROR, "Invalid suId");
146 KW_SEND_SAPID_ALARM(tRlcCb,suId, LKW_EVENT_LI_BND_CFM, LCM_CAUSE_INV_SUID);
150 #endif /* ERRCLASS & ERRCLS_INT_PAR */
152 rguSap = (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_DL) ?
153 &(tRlcCb->u.dlCb->rguDlSap[suId]) : &(tRlcCb->u.ulCb->rguUlSap[suId]);
155 RLOG1(L_DEBUG, "KwLiRguBndCfm: For RGU SAP state=%d", rguSap->state)
157 switch (rguSap->state)
161 kwStopTmr (tRlcCb,(PTR)rguSap, KW_EVT_WAIT_BNDCFM);
163 rguSap->retryCnt = 0;
165 if (status == CM_BND_OK)
167 rguSap->state = KW_SAP_BND;
168 event = LCM_EVENT_BND_OK;
169 cause = LKW_CAUSE_SAP_BNDENB;
173 rguSap->state = KW_SAP_CFG;
174 event = LCM_EVENT_BND_FAIL;
175 cause = LKW_CAUSE_UNKNOWN;
181 event = LKW_EVENT_RGU_BND_CFM;
182 cause = LCM_CAUSE_INV_STATE;
186 /* Send an alarm with proper event and cause */
187 KW_SEND_SAPID_ALARM(tRlcCb, suId, event, cause);
190 } /* KwLiRguBndCfm */
193 * @brief Handler to process PDU received from MAC
196 * This function receives the PDU from MAC.
197 * seggregates common and dedicated logical channel
198 * PDU and call respective handler.
200 * @param[in] pst Post structure
201 * @param[in] suId Service User ID
202 * @param[in] datInd Data Indication Information
210 uint8_t RlcProcUlData(Pst *pst, RlcMacData *ulData)
213 U8 lcId; /* Logical Channel */
214 U8 numDLch = 0; /* Number of dedicated logical channel */
215 Bool dLchPduPres; /* PDU received on dedicated logical channel */
216 RguLchDatInd dLchData[RGU_MAX_LC]; /* PDU info on dedicated logical channel */
217 RguDDatIndInfo *dLchUlDat; /* UL data on dedicated logical channel */
218 RguCDatIndInfo *cLchUlDat; /* UL data on common logical channel */
221 /* Initializing dedicated logical channel Database */
222 for(idx = 0; idx < RGU_MAX_LC; idx++)
224 dLchData[idx].lcId = idx;
225 dLchData[idx].pdu.numPdu = 0;
230 /* Seggregate PDUs received on common and dedicated channels
231 * and call common channel's handler */
232 for(idx = 0; idx< ulData->numPdu; idx++)
234 if(ulData->pduInfo[idx].commCh)
236 RLC_SHRABL_STATIC_BUF_ALLOC(pst->region, pst->pool, cLchUlDat, sizeof(RguCDatIndInfo));
237 cmMemset((U8*)cLchUlDat, (U8)0, sizeof(RguCDatIndInfo));
239 cLchUlDat->cellId = ulData->cellId;
240 GET_UE_IDX(ulData->rnti, cLchUlDat->rnti);
241 cLchUlDat->lcId = ulData->pduInfo[idx].lcId;
243 /* Copy fixed buffer to message */
244 if(SGetMsg(RLC_MEM_REGION_UL, RLC_POOL, &cLchUlDat->pdu) != ROK)
246 DU_LOG("\nRLC : Memory allocation failed at RlcProcUlData");
249 reverseFixBuf(ulData->pduInfo[idx].pduBuf, ulData->pduInfo[idx].pduLen);
250 SCpyFixMsg(ulData->pduInfo[idx].pduBuf, cLchUlDat->pdu, 0, \
251 ulData->pduInfo[idx].pduLen, (MsgLen *)©Len);
253 KwLiRguCDatInd(pst, 0, cLchUlDat);
259 RLC_SHRABL_STATIC_BUF_ALLOC(pst->region, pst->pool, dLchUlDat, sizeof(RguDDatIndInfo));
263 lcId = ulData->pduInfo[idx].lcId;
264 dLchData[lcId].pdu.mBuf[dLchData[lcId].pdu.numPdu] = ulData->pduInfo[idx].pduBuf;
265 dLchData[lcId].pdu.numPdu++;
269 /* If any PDU received on dedicated logical channel, copy into RguDDatIndInfo
270 * and call its handler */
273 dLchUlDat->cellId = ulData->cellId;
274 dLchUlDat->rnti = ulData->rnti;
276 for(idx = 0; idx < RGU_MAX_LC; idx++)
278 if(dLchData[idx].pdu.numPdu)
280 cmMemcpy((U8 *)&dLchUlDat->lchData[numDLch], (U8 *)&dLchData[idx], sizeof(RguLchDatInd));
284 dLchUlDat->numLch = numDLch;
285 KwLiRguDDatInd(pst, 0, dLchUlDat);
289 RLC_FREE_SHRABL_BUF(pst->region, pst->pool, ulData, sizeof(RlcMacData));
292 }/* End of RlcProcUlData */
294 PUBLIC int rlcDDatIndRcvd;
295 PUBLIC int rlcCDatIndRcvd;
297 * @brief Handler to process PDU received from MAC for common logical channels.
300 * This function receives the PDU from MAC for common logical channels
301 * does checks before handing over the PDU to the TM module
303 * @param[in] pst Post structure
304 * @param[in] suId Service User ID
305 * @param[in] datInd Data Indication Information
313 PUBLIC S16 KwLiRguCDatInd
317 RguCDatIndInfo *datInd
320 PUBLIC S16 KwLiRguCDatInd(pst,suId,datInd)
323 RguCDatIndInfo *datInd;
332 #if (ERRCLASS & ERRCLS_INT_PAR)
333 if (pst->dstInst >= MAX_RLC_INSTANCES)
335 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
340 tRlcCb = RLC_GET_RLCCB(pst->dstInst);
343 #if (ERRCLASS & ERRCLS_DEBUG)
344 if (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
346 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
351 /* kw006.201 ccpu00120058, Added array boundary condition check */
352 #if (ERRCLASS & ERRCLS_DEBUG)
353 if(KW_MAX_LCH_PER_CELL <= datInd->lcId)
355 RLOG_ARG1(L_ERROR,DBG_LCID,datInd->lcId, "Invalid LcId, Max is [%d]",
356 KW_MAX_LCH_PER_CELL);
357 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
360 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
362 /* Fetch RbCb from lcId */
363 kwDbmFetchUlRbCbFromLchId(tRlcCb, datInd->rnti, datInd->cellId, datInd->lcId, &rbCb);
366 RLOG_ARG1(L_ERROR, DBG_CELLID,datInd->cellId, "LcId [%d] not found",
368 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
372 /* Dispatch to TM Module */
374 kwTmmRcvFrmLi(tRlcCb, rbCb, datInd->rnti, datInd->pdu);
376 kwTmmRcvFrmLi(tRlcCb, rbCb, datInd->pdu);
377 #endif /* CCPU_OPT */
379 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
382 } /* KwLiRguCDatInd */
385 * @brief Handler to process PDU received from MAC for
386 * dedicated logical channels.
389 * This function receives the PDU from MAC for one or more dedicated
390 * logical channels and passes it to the UTL module for further processing
392 * @param[in] pst Post structure
393 * @param[in] suId Service User ID
394 * @param[in] datInd Data Indication Information
403 PUBLIC S16 KwLiRguDDatInd
407 RguDDatIndInfo *datInd
410 PUBLIC S16 KwLiRguDDatInd(pst, suId, datInd)
413 RguDDatIndInfo *datInd;
419 #if (ERRCLASS & ERRCLS_INT_PAR)
420 if (pst->dstInst >= MAX_RLC_INSTANCES)
422 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
427 #if (ERRCLASS & ERRCLS_DEBUG)
428 if (((RlcCb*)RLC_GET_RLCCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_DL)
430 RLOG1(L_DEBUG,"KwLiRguDDatInd(pst, suId(%d))recieved in DL Inst",suId);
431 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
435 kwUtlRcvFrmLi(RLC_GET_RLCCB(pst->dstInst),datInd);
437 #ifdef SS_LOCKLESS_MEMORY
438 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
440 RLC_PST_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
445 } /* KwLiRguDDatInd */
448 /*******************************************************************
450 * @brief Handler for extracting common and dedicated channel
451 * Scheduling result report.
455 * Function : RlcMacProcSchedRep
458 * Handler for extracting common and dedicated channel
459 * Scheduling result report
462 * @return ROK - success
465 * ****************************************************************/
466 PUBLIC uint16_t RlcMacProcSchedRep(Pst *pst, SuId suId, RlcMacSchedRepInfo *schRep)
468 U8 idx; /* Iterator */
469 U8 nmbDLch = 0; /* Number of dedicated logical channles */
470 RguCStaIndInfo *cLchSchInfo; /* Common logical channel scheduling result */
471 RguDStaIndInfo *dLchSchInfo; /* Dedicated logical channel scheduling result */
473 DU_LOG("\nRLC : Received scheduling report from MAC");
475 for(idx=0; idx < schRep->nmbLch; idx++)
477 /* If it is common channel, fill status indication information
478 * and trigger the handler for each common lch separately */
479 if(schRep->lchSta[idx].commCh)
481 RLC_SHRABL_STATIC_BUF_ALLOC(pst->region, pst->pool, cLchSchInfo, sizeof(RguCStaIndInfo));
482 cmMemset((U8*)cLchSchInfo, (U8)0, sizeof(RguCStaIndInfo));
484 cLchSchInfo->cellId = schRep->cellId;
485 cLchSchInfo->lcId = schRep->lchSta[idx].lchStaInd.lcId;
486 //cLchSchInfo->transId = schRep->timeToTx; /* TODO : fill transId suing timeToTx */
487 cLchSchInfo->rnti = schRep->rnti;
489 KwLiRguCStaInd(pst, suId, cLchSchInfo);
494 /* Fill status info structure if at least one dedicated channel
495 * scheduling report is received */
498 RLC_SHRABL_STATIC_BUF_ALLOC(pst->region, pst->pool, dLchSchInfo, sizeof(RguDStaIndInfo));
500 dLchSchInfo->cellId = schRep->cellId;
501 dLchSchInfo->nmbOfUeGrantPerTti = 1;
502 dLchSchInfo->staInd[0].rnti = schRep->rnti;
503 //dLchSchInfo->staInd[0].transId = schRep->timeToTx; /* TODO : fill transId suing timeToTx */
504 dLchSchInfo->staInd[0].nmbOfTbs = 1;
505 //dLchSchInfo->staInd[0].fillCrlPdu = /* TODO : Check the value needed to be filled */
508 /* Fill logical channel scheduling info */
509 cmMemcpy((U8 *)&dLchSchInfo->staInd[0].staIndTb[0].lchStaInd[nmbDLch], (U8 *)&schRep->lchSta[idx].lchStaInd, sizeof(RguLchStaInd));
516 /* Calling handler for all dedicated channels scheduling*/
519 dLchSchInfo->staInd[0].staIndTb[0].nmbLch = nmbDLch;
520 KwLiRguDStaInd(pst, suId, dLchSchInfo);
523 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, schRep, sizeof(RlcMacSchedRepInfo));
529 * @brief Handler for trigerring the data transfer from RLC to MAC
530 * for common logical channels.
533 * This function receives the size of the PDU to be transmitted
534 * and acts as a trigger for forming PDU and sending it to MAC.
536 * @param[in] pst Post structure
537 * @param[in] suId Service User ID
538 * @param[in] staInd Status Indication Information for Common Logical
547 PUBLIC S16 KwLiRguCStaInd
551 RguCStaIndInfo *staInd
554 PUBLIC S16 KwLiRguCStaInd(pst,suId,staInd)
557 RguCStaIndInfo *staInd;
565 #if (ERRCLASS & ERRCLS_INT_PAR)
566 if (pst->dstInst >= MAX_RLC_INSTANCES)
568 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
573 tRlcCb = RLC_GET_RLCCB(pst->dstInst);
576 #if (ERRCLASS & ERRCLS_INT_PAR)
577 if ((suId >= tRlcCb->genCfg.maxRguSaps) || (suId < 0))
583 "KwLiRguCStaInd: Invalid RGU suId\n");
586 if (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_UL)
588 RLOG_ARG1(L_ERROR,DBG_LCID,staInd->lcId,
589 "Received in RLC UL CELLID:%d",
591 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
598 /* kw006.201 ccpu00120058, added boundary condition check */
599 #if (ERRCLASS & ERRCLS_DEBUG)
600 if(KW_MAX_LCH_PER_CELL < staInd->lcId)
602 RLOG_ARG2(L_ERROR,DBG_LCID,staInd->lcId,
603 "Invalid LcId, Max is [%d] CELLID:%d",
606 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
609 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
610 /* Fertch RbCb from lcId */
611 kwDbmFetchDlRbCbFromLchId(tRlcCb,0, staInd->cellId, staInd->lcId, &rbCb);
614 RLOG_ARG1(L_ERROR, DBG_CELLID,staInd->cellId,
615 "LcId [%d] not found CELLID:%d",
617 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
621 /* Dispatch to TM Module */
622 rbCb->transId = staInd->transId;
624 /* If trace flag is enabled send the trace indication */
625 if(tRlcCb->init.trc == TRUE)
627 /* Populate the trace params */
628 kwLmmSendTrc(tRlcCb,EVTRGUCSTAIND, NULLP);
630 kwTmmSndToLi(tRlcCb, suId, rbCb, staInd);
632 #ifdef SS_LOCKLESS_MEMORY
633 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
635 RLC_PST_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
638 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
641 } /* KwLiRguCStaInd */
644 * @brief Handler for trigerring the data transfer from RLC to MAC
645 * for dedicated logical channels.
648 * This function receives the size of the PDUs to be transmitted to
649 * MAC via one or more dedicated logical channels and acts as a trigger
650 * for forming PDUs and sending them to MAC.
652 * @param[in] pst Post structure
653 * @param[in] suId Service User ID
654 * @param[in] staInd Status Indication Information for Dedicated Logical
663 PUBLIC S16 KwLiRguDStaInd
667 RguDStaIndInfo *staInd
670 PUBLIC S16 KwLiRguDStaInd(pst, suId, staInd)
673 RguDStaIndInfo *staInd;
679 #if (ERRCLASS & ERRCLS_INT_PAR)
680 if (pst->dstInst >= MAX_RLC_INSTANCES)
682 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
687 gCb = RLC_GET_RLCCB(pst->dstInst);
689 #if (ERRCLASS & ERRCLS_INT_PAR)
690 if (((RlcCb*)RLC_GET_RLCCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_UL)
692 RLOG_ARG0(L_ERROR,DBG_CELLID,staInd->cellId,"Received in RLC UL ");
693 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
696 if ((suId >= gCb->genCfg.maxRguSaps) || (suId < 0))
702 "KwLiRguDStaInd: Invalid RGU suId\n");
706 kwUtlSndToLi(gCb, suId, staInd);
708 /* kw002.201 :Freeing from proper region */
709 RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
711 } /* KwLiRguDStaInd */
714 * @brief Handler for handling the flow cntrl Ind from MAC
718 * This function receives the flow control indication from
719 * MAC and calls kwUtlTrigPdbFlowCntrl
721 * @param[in] pst Post structure
722 * @param[in] suId Service User ID
723 * @param[in] flowCntrlInd flow control Indication Information
732 PUBLIC S16 KwLiRguFlowCntrlInd
736 RguFlowCntrlInd *flowCntrlInd
739 PUBLIC S16 KwLiRguFlowCntrlInd(pst, suId, flowCntrlInd)
742 RguFlowCntrlInd *flowCntrlInd;
746 RlcDlRbCb *rbCb = NULLP;
750 tRlcCb = RLC_GET_RLCCB(pst->dstInst);
751 for (idx = 0; idx < flowCntrlInd->numUes; idx++)
753 for (lcIdx = 0; lcIdx < flowCntrlInd->ueFlowCntrlInfo[idx].numLcs; lcIdx++)
755 RguLcFlowCntrlInfo *lcInfo = &(flowCntrlInd->ueFlowCntrlInfo[idx].lcInfo[lcIdx]);
756 kwDbmFetchDlRbCbFromLchId(tRlcCb, flowCntrlInd->ueFlowCntrlInfo[idx].ueId, flowCntrlInd->cellId, lcInfo->lcId, &rbCb);
760 if (lcInfo->pktAdmitCnt == 0) /* Special case */
762 kwUtlTrigPdbFlowCntrl(tRlcCb, rbCb, lcInfo->pktAdmitCnt);
765 if (rbCb->mode == CM_LTE_MODE_AM)
767 if ((rbCb->m.amDl.retxLst.count != 0) ||
768 ((rbCb->m.amDl.bo == 0) ||
769 (rbCb->m.amDl.bo < lcInfo->maxBo4FlowCtrl)))
776 if ((rbCb->m.umDl.bo == 0) ||
777 (rbCb->m.umDl.bo < lcInfo->maxBo4FlowCtrl))
782 kwUtlTrigPdbFlowCntrl(tRlcCb, rbCb, lcInfo->pktAdmitCnt);
788 /* kw005.201 added support for L2 Measurement */
795 * Handler for indicating the Harq Status of the data sent.
799 * This function receives the harq status of the data sent to MAC.
800 * This information is used for two things.
801 * 1. Computing the UuLoss of UM
802 * 2. Computing the DL Delay for UM and AM.
804 * @param[in] pst - Post structure
805 * @param[in] suId - Service User ID
806 * @param[in] staInd - Harq Status Indication Information.
814 PUBLIC S16 KwLiRguHqStaInd
818 RguHarqStatusInd *staInd
821 PUBLIC S16 KwLiRguHqStaInd(pst,suId,staInd)
824 RguHarqStatusInd *staInd;
834 TRC3(KwLiRguHqStaInd)
836 tRlcCb = RLC_GET_RLCCB(pst->dstInst);
837 ueKey.cellId = staInd->cellId;
838 ueKey.ueId = staInd->ueId;
840 ret = kwDbmFetchDlUeCb(tRlcCb, ueKey.ueId, ueKey.cellId, &ueCb);
846 /*Call kwUtlProcHarqInd as many times as number of Tbs present*/
847 for ( tbIdx = 0; tbIdx < staInd->numTbs; tbIdx++)
849 kwUtlProcHarqInd(tRlcCb, staInd, ueCb, tbIdx);
853 } /* KwLiRguHqStaInd */
854 #endif /* LTE_L2_MEAS */
858 #endif /* __cplusplus */
860 /********************************************************************30**
862 **********************************************************************/