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 "envopt.h" /* environment options */
52 #include "envdep.h" /* environment dependent */
53 #include "envind.h" /* environment independent */
55 #include "gen.h" /* general */
56 #include "ssi.h" /* system services */
57 #include "cm5.h" /* common timer defines */
58 #include "cm_tkns.h" /* common tokens defines */
59 #include "cm_mblk.h" /* common memory allocation library defines */
60 #include "cm_llist.h" /* common link list defines */
61 #include "cm_hash.h" /* common hash list defines */
62 #include "cm_lte.h" /* common LTE defines */
63 #include "lkw.h" /* LKW defines */
64 #include "ckw.h" /* CKW defines */
65 #include "kwu.h" /* KWU defines */
66 #include "rgu.h" /* RGU defines */
68 #include "kw_env.h" /* RLC environment options */
70 #include "kw.h" /* RLC defines */
75 /* extern (.x) include files */
76 #include "gen.x" /* general */
77 #include "ssi.x" /* system services */
79 #include "cm5.x" /* common timer library */
80 #include "cm_tkns.x" /* common tokens */
81 #include "cm_mblk.x" /* common memory allocation */
82 #include "cm_llist.x" /* common link list */
83 #include "cm_hash.x" /* common hash list */
84 #include "cm_lte.x" /* common LTE includes */
85 #include "cm_lib.x" /* common memory allocation library */
86 #include "lkw.x" /* LKW */
87 #include "ckw.x" /* CKW */
88 #include "kwu.x" /* KWU */
89 #include "rgu.x" /* RGU */
98 #endif /* __cplusplus */
101 /*****************************************************************************
103 ****************************************************************************/
105 * @brief Handler for bind confirmation from MAC.
108 * This function handles the bind confirmation received from MAC. If the
109 * bind was successful changes the state of the SAP to KW_SAP_BND
110 * else KW_SAP_CFG. Sends an alarm to LM in any case
112 * @param[in] pst Post structure
113 * @param[in] suId Service User ID
114 * @param[in] status Status whether the bind was successful or not
122 PUBLIC S16 KwLiRguBndCfm
129 PUBLIC S16 KwLiRguBndCfm (pst, suId, status)
135 U16 event; /* Event */
136 U16 cause; /* Cause */
137 KwRguSapCb *rguSap; /* RGU SAP Control Block */
142 #if (ERRCLASS & ERRCLS_INT_PAR)
143 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
148 tKwCb = KW_GET_KWCB(pst->dstInst);
150 RLOG2(L_DEBUG,"KwLiRguBndCfm(suId(%d), status(%d)", suId, status);
152 #if (ERRCLASS & ERRCLS_INT_PAR)
153 if (tKwCb->init.cfgDone != TRUE)
155 RLOG0(L_FATAL,"General configuration not done");
157 KW_SEND_SAPID_ALARM(tKwCb,suId,LKW_EVENT_LI_BND_CFM, LCM_CAUSE_INV_STATE);
162 if ((suId >= tKwCb->genCfg.maxRguSaps) || (suId < 0))
164 RLOG0(L_ERROR, "Invalid suId");
166 KW_SEND_SAPID_ALARM(tKwCb,suId, LKW_EVENT_LI_BND_CFM, LCM_CAUSE_INV_SUID);
170 #endif /* ERRCLASS & ERRCLS_INT_PAR */
172 rguSap = (tKwCb->genCfg.rlcMode == LKW_RLC_MODE_DL) ?
173 &(tKwCb->u.dlCb->rguDlSap[suId]) : &(tKwCb->u.ulCb->rguUlSap[suId]);
175 RLOG1(L_DEBUG, "KwLiRguBndCfm: For RGU SAP state=%d", rguSap->state)
177 switch (rguSap->state)
181 kwStopTmr (tKwCb,(PTR)rguSap, KW_EVT_WAIT_BNDCFM);
183 rguSap->retryCnt = 0;
185 if (status == CM_BND_OK)
187 rguSap->state = KW_SAP_BND;
188 event = LCM_EVENT_BND_OK;
189 cause = LKW_CAUSE_SAP_BNDENB;
193 rguSap->state = KW_SAP_CFG;
194 event = LCM_EVENT_BND_FAIL;
195 cause = LKW_CAUSE_UNKNOWN;
201 event = LKW_EVENT_RGU_BND_CFM;
202 cause = LCM_CAUSE_INV_STATE;
206 /* Send an alarm with proper event and cause */
207 KW_SEND_SAPID_ALARM(tKwCb, suId, event, cause);
210 } /* KwLiRguBndCfm */
213 * @brief Handler to process PDU received from MAC
216 * This function receives the PDU from MAC.
217 * seggregates common and dedicated logical channel
218 * PDU and call respective handler.
220 * @param[in] pst Post structure
221 * @param[in] suId Service User ID
222 * @param[in] datInd Data Indication Information
231 PUBLIC S16 RlcMacProcUlData
238 PUBLIC S16 RlcMacProcUlData(pst, suId, ulData)
245 U8 lcId; /* Logical Channel */
246 U8 numDLch = 0; /* Number of dedicated logical channel */
247 Bool dLchPduPres; /* PDU received on dedicated logical channel */
248 RguLchDatInd dLchData[RGU_MAX_LC]; /* PDU info on dedicated logical channel */
249 RguDDatIndInfo dLchUlDat; /* UL data on dedicated logical channel */
250 RguCDatIndInfo cLchUlDat; /* UL data on common logical channel */
252 /* Initializing dedicated logical channel Database */
253 for(idx = 0; idx < RGU_MAX_LC; idx++)
255 dLchData[idx].lcId = idx;
256 dLchData[idx].pdu.numPdu = 0;
261 /* Seggregate PDUs received on common and dedicated channels
262 * and call common channel's handler */
263 for(idx = 0; idx< ulData->nmbPdu; idx++)
265 if(ulData->pduInfo[idx].commCh)
267 cmMemset((U8*)&cLchUlDat, (U8)0, sizeof(RguCDatIndInfo));
269 cLchUlDat.cellId = ulData->cellId;
270 cLchUlDat.rnti = ulData->rnti;
271 cLchUlDat.lcId = ulData->pduInfo[idx].lcId;
272 cLchUlDat.pdu = ulData->pduInfo[idx].pduBuf;
274 KwLiRguCDatInd(pst, suId, &cLchUlDat);
283 lcId = ulData->pduInfo[idx].lcId;
284 dLchData[lcId].pdu.mBuf[dLchData[lcId].pdu.numPdu] = ulData->pduInfo[idx].pduBuf;
285 dLchData[lcId].pdu.numPdu++;
289 /* If any PDU received on dedicated logical channel, copy into RguDDatIndInfo
290 * and call its handler */
293 dLchUlDat.cellId = ulData->cellId;
294 dLchUlDat.rnti = ulData->rnti;
296 for(idx = 0; idx < RGU_MAX_LC; idx++)
298 if(dLchData[idx].pdu.numPdu)
300 cmMemcpy((U8 *)&dLchUlDat.lchData[numDLch], (U8 *)&dLchData[idx], sizeof(RguLchDatInd));
304 dLchUlDat.numLch = numDLch;
305 KwLiRguDDatInd(pst, suId, &dLchUlDat);
310 }/* End of RlcMacProcUlData */
312 PUBLIC int rlcDDatIndRcvd;
313 PUBLIC int rlcCDatIndRcvd;
315 * @brief Handler to process PDU received from MAC for common logical channels.
318 * This function receives the PDU from MAC for common logical channels
319 * does checks before handing over the PDU to the TM module
321 * @param[in] pst Post structure
322 * @param[in] suId Service User ID
323 * @param[in] datInd Data Indication Information
331 PUBLIC S16 KwLiRguCDatInd
335 RguCDatIndInfo *datInd
338 PUBLIC S16 KwLiRguCDatInd(pst,suId,datInd)
341 RguCDatIndInfo *datInd;
350 #if (ERRCLASS & ERRCLS_INT_PAR)
351 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
353 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
358 tKwCb = KW_GET_KWCB(pst->dstInst);
361 #if (ERRCLASS & ERRCLS_DEBUG)
362 if (tKwCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
364 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
369 /* kw006.201 ccpu00120058, Added array boundary condition check */
370 #if (ERRCLASS & ERRCLS_DEBUG)
371 if(KW_MAX_LCH_PER_CELL <= datInd->lcId)
373 RLOG_ARG1(L_ERROR,DBG_LCID,datInd->lcId, "Invalid LcId, Max is [%d]",
374 KW_MAX_LCH_PER_CELL);
375 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
378 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
380 /* Fetch RbCb from lcId */
381 kwDbmFetchUlRbCbFromLchId(tKwCb, 0, datInd->cellId, datInd->lcId, &rbCb);
384 RLOG_ARG1(L_ERROR, DBG_CELLID,datInd->cellId, "LcId [%d] not found",
386 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
390 /* Dispatch to TM Module */
392 kwTmmRcvFrmLi(tKwCb, rbCb, datInd->rnti, datInd->pdu);
394 kwTmmRcvFrmLi(tKwCb, rbCb, datInd->pdu);
395 #endif /* CCPU_OPT */
397 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
400 } /* KwLiRguCDatInd */
403 * @brief Handler to process PDU received from MAC for
404 * dedicated logical channels.
407 * This function receives the PDU from MAC for one or more dedicated
408 * logical channels and passes it to the UTL module for further processing
410 * @param[in] pst Post structure
411 * @param[in] suId Service User ID
412 * @param[in] datInd Data Indication Information
421 PUBLIC S16 KwLiRguDDatInd
425 RguDDatIndInfo *datInd
428 PUBLIC S16 KwLiRguDDatInd(pst, suId, datInd)
431 RguDDatIndInfo *datInd;
437 #if (ERRCLASS & ERRCLS_INT_PAR)
438 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
440 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
445 #if (ERRCLASS & ERRCLS_DEBUG)
446 if (((KwCb*)KW_GET_KWCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_DL)
448 RLOG1(L_DEBUG,"KwLiRguDDatInd(pst, suId(%d))recieved in DL Inst",suId);
449 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
453 kwUtlRcvFrmLi(KW_GET_KWCB(pst->dstInst),datInd);
455 #ifdef SS_LOCKLESS_MEMORY
456 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
458 KW_PST_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
463 } /* KwLiRguDDatInd */
466 /*******************************************************************
468 * @brief Handler for extracting common and dedicated channel
469 * Scheduling result report.
473 * Function : RlcMacProcSchedRep
476 * Handler for extracting common and dedicated channel
477 * Scheduling result report
480 * @return ROK - success
483 * ****************************************************************/
485 PUBLIC S16 RlcMacProcSchedRep
489 RlcMacSchedRep *schRep
492 PUBLIC S16 RlcMacProcSchedRep(pst, suId, schRep)
495 RlcMacSchedRep *schRep;
498 U8 idx; /* Iterator */
499 U8 nmbDLch = 0; /* Number of dedicated logical channles */
500 RguCStaIndInfo cLchSchInfo; /* Common logical channel scheduling result */
501 RguDStaIndInfo dLchSchInfo; /* Dedicated logical channel scheduling result */
503 for(idx=0; idx < schRep->nmbLch; idx++)
505 /* If it is common channel, fill status indication information
506 * and trigger the handler for each common lch separately */
507 if(schRep->lchSta[idx].commCh)
509 cmMemset((U8*)&cLchSchInfo, (U8)0, sizeof(RguCStaIndInfo));
511 cLchSchInfo.cellId = schRep->cellId;
512 cLchSchInfo.lcId = schRep->lchSta[idx].lchStaInd.lcId;
513 //cLchSchInfo.transId = schRep->timeToTx; /* TODO : fill transId suing timeToTx */
514 cLchSchInfo.rnti = schRep->rnti;
516 KwLiRguCStaInd(pst, suId, &cLchSchInfo);
521 /* Fill status info structure if at least one dedicated channel
522 * scheduling report is received */
525 dLchSchInfo.cellId = schRep->cellId;
526 dLchSchInfo.nmbOfUeGrantPerTti = 1;
527 dLchSchInfo.staInd[0].rnti = schRep->rnti;
528 //dLchSchInfo.staInd[0].transId = schRep->timeToTx; /* TODO : fill transId suing timeToTx */
529 dLchSchInfo.staInd[0].nmbOfTbs = 1;
530 //dLchSchInfo.staInd[0].fillCrlPdu = /* TODO : Check the value needed to be filled */
533 /* Fill logical channel scheduling info */
534 cmMemcpy((U8 *)&dLchSchInfo.staInd[0].staIndTb[0].lchStaInd[nmbDLch], (U8 *)&schRep->lchSta[idx].lchStaInd, sizeof(RguLchStaInd));
541 /* Calling handler for all dedicated channels scheduling*/
544 dLchSchInfo.staInd[0].staIndTb[0].nmbLch = nmbDLch;
545 KwLiRguDStaInd(pst, suId, &dLchSchInfo);
552 * @brief Handler for trigerring the data transfer from RLC to MAC
553 * for common logical channels.
556 * This function receives the size of the PDU to be transmitted
557 * and acts as a trigger for forming PDU and sending it to MAC.
559 * @param[in] pst Post structure
560 * @param[in] suId Service User ID
561 * @param[in] staInd Status Indication Information for Common Logical
570 PUBLIC S16 KwLiRguCStaInd
574 RguCStaIndInfo *staInd
577 PUBLIC S16 KwLiRguCStaInd(pst,suId,staInd)
580 RguCStaIndInfo *staInd;
588 #if (ERRCLASS & ERRCLS_INT_PAR)
589 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
591 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
596 tKwCb = KW_GET_KWCB(pst->dstInst);
599 #if (ERRCLASS & ERRCLS_INT_PAR)
600 if ((suId >= tKwCb->genCfg.maxRguSaps) || (suId < 0))
606 "KwLiRguCStaInd: Invalid RGU suId\n");
609 if (tKwCb->genCfg.rlcMode == LKW_RLC_MODE_UL)
611 RLOG_ARG1(L_ERROR,DBG_LCID,staInd->lcId,
612 "Received in RLC UL CELLID:%d",
614 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
621 /* kw006.201 ccpu00120058, added boundary condition check */
622 #if (ERRCLASS & ERRCLS_DEBUG)
623 if(KW_MAX_LCH_PER_CELL < staInd->lcId)
625 RLOG_ARG2(L_ERROR,DBG_LCID,staInd->lcId,
626 "Invalid LcId, Max is [%d] CELLID:%d",
629 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
632 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
633 /* Fertch RbCb from lcId */
634 kwDbmFetchDlRbCbFromLchId(tKwCb,0, staInd->cellId, staInd->lcId, &rbCb);
637 RLOG_ARG1(L_ERROR, DBG_CELLID,staInd->cellId,
638 "LcId [%d] not found CELLID:%d",
640 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
644 /* Dispatch to TM Module */
645 rbCb->transId = staInd->transId;
647 /* If trace flag is enabled send the trace indication */
648 if(tKwCb->init.trc == TRUE)
650 /* Populate the trace params */
651 kwLmmSendTrc(tKwCb,EVTRGUCSTAIND, NULLP);
653 kwTmmSndToLi(tKwCb, suId, rbCb, staInd);
655 #ifdef SS_LOCKLESS_MEMORY
656 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
658 KW_PST_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
661 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
664 } /* KwLiRguCStaInd */
667 * @brief Handler for trigerring the data transfer from RLC to MAC
668 * for dedicated logical channels.
671 * This function receives the size of the PDUs to be transmitted to
672 * MAC via one or more dedicated logical channels and acts as a trigger
673 * for forming PDUs and sending them to MAC.
675 * @param[in] pst Post structure
676 * @param[in] suId Service User ID
677 * @param[in] staInd Status Indication Information for Dedicated Logical
686 PUBLIC S16 KwLiRguDStaInd
690 RguDStaIndInfo *staInd
693 PUBLIC S16 KwLiRguDStaInd(pst, suId, staInd)
696 RguDStaIndInfo *staInd;
702 #if (ERRCLASS & ERRCLS_INT_PAR)
703 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
705 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
710 gCb = KW_GET_KWCB(pst->dstInst);
712 #if (ERRCLASS & ERRCLS_INT_PAR)
713 if (((KwCb*)KW_GET_KWCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_UL)
715 RLOG_ARG0(L_ERROR,DBG_CELLID,staInd->cellId,"Received in RLC UL ");
716 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
719 if ((suId >= gCb->genCfg.maxRguSaps) || (suId < 0))
725 "KwLiRguDStaInd: Invalid RGU suId\n");
729 kwUtlSndToLi(gCb, suId, staInd);
731 /* kw002.201 :Freeing from proper region */
732 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
734 } /* KwLiRguDStaInd */
737 * @brief Handler for handling the flow cntrl Ind from MAC
741 * This function receives the flow control indication from
742 * MAC and calls kwUtlTrigPdbFlowCntrl
744 * @param[in] pst Post structure
745 * @param[in] suId Service User ID
746 * @param[in] flowCntrlInd flow control Indication Information
755 PUBLIC S16 KwLiRguFlowCntrlInd
759 RguFlowCntrlInd *flowCntrlInd
762 PUBLIC S16 KwLiRguFlowCntrlInd(pst, suId, flowCntrlInd)
765 RguFlowCntrlInd *flowCntrlInd;
769 KwDlRbCb *rbCb = NULLP;
773 tKwCb = KW_GET_KWCB(pst->dstInst);
774 for (idx = 0; idx < flowCntrlInd->numUes; idx++)
776 for (lcIdx = 0; lcIdx < flowCntrlInd->ueFlowCntrlInfo[idx].numLcs; lcIdx++)
778 RguLcFlowCntrlInfo *lcInfo = &(flowCntrlInd->ueFlowCntrlInfo[idx].lcInfo[lcIdx]);
779 kwDbmFetchDlRbCbFromLchId(tKwCb, flowCntrlInd->ueFlowCntrlInfo[idx].ueId, flowCntrlInd->cellId, lcInfo->lcId, &rbCb);
783 if (lcInfo->pktAdmitCnt == 0) /* Special case */
785 kwUtlTrigPdbFlowCntrl(tKwCb, rbCb, lcInfo->pktAdmitCnt);
788 if (rbCb->mode == CM_LTE_MODE_AM)
790 if ((rbCb->m.amDl.retxLst.count != 0) ||
791 ((rbCb->m.amDl.bo == 0) ||
792 (rbCb->m.amDl.bo < lcInfo->maxBo4FlowCtrl)))
799 if ((rbCb->m.umDl.bo == 0) ||
800 (rbCb->m.umDl.bo < lcInfo->maxBo4FlowCtrl))
805 kwUtlTrigPdbFlowCntrl(tKwCb, rbCb, lcInfo->pktAdmitCnt);
811 /* kw005.201 added support for L2 Measurement */
818 * Handler for indicating the Harq Status of the data sent.
822 * This function receives the harq status of the data sent to MAC.
823 * This information is used for two things.
824 * 1. Computing the UuLoss of UM
825 * 2. Computing the DL Delay for UM and AM.
827 * @param[in] pst - Post structure
828 * @param[in] suId - Service User ID
829 * @param[in] staInd - Harq Status Indication Information.
837 PUBLIC S16 KwLiRguHqStaInd
841 RguHarqStatusInd *staInd
844 PUBLIC S16 KwLiRguHqStaInd(pst,suId,staInd)
847 RguHarqStatusInd *staInd;
857 TRC3(KwLiRguHqStaInd)
859 tKwCb = KW_GET_KWCB(pst->dstInst);
860 ueKey.cellId = staInd->cellId;
861 ueKey.ueId = staInd->ueId;
863 ret = kwDbmFetchDlUeCb(tKwCb, ueKey.ueId, ueKey.cellId, &ueCb);
869 /*Call kwUtlProcHarqInd as many times as number of Tbs present*/
870 for ( tbIdx = 0; tbIdx < staInd->numTbs; tbIdx++)
872 kwUtlProcHarqInd(tKwCb, staInd, ueCb, tbIdx);
876 } /* KwLiRguHqStaInd */
877 #endif /* LTE_L2_MEAS */
881 #endif /* __cplusplus */
883 /********************************************************************30**
885 **********************************************************************/