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
230 PUBLIC S16 RlcMacProcUlData(Pst *pst, SuId suId, RlcMacData *ulData)
233 U8 lcId; /* Logical Channel */
234 U8 numDLch = 0; /* Number of dedicated logical channel */
235 Bool dLchPduPres; /* PDU received on dedicated logical channel */
236 RguLchDatInd dLchData[RGU_MAX_LC]; /* PDU info on dedicated logical channel */
237 RguDDatIndInfo dLchUlDat; /* UL data on dedicated logical channel */
238 RguCDatIndInfo cLchUlDat; /* UL data on common logical channel */
240 /* Initializing dedicated logical channel Database */
241 for(idx = 0; idx < RGU_MAX_LC; idx++)
243 dLchData[idx].lcId = idx;
244 dLchData[idx].pdu.numPdu = 0;
249 /* Seggregate PDUs received on common and dedicated channels
250 * and call common channel's handler */
251 for(idx = 0; idx< ulData->nmbPdu; idx++)
253 if(ulData->pduInfo[idx].commCh)
255 cmMemset((U8*)&cLchUlDat, (U8)0, sizeof(RguCDatIndInfo));
257 cLchUlDat.cellId = ulData->cellId;
258 cLchUlDat.rnti = ulData->rnti;
259 cLchUlDat.lcId = ulData->pduInfo[idx].lcId;
260 cLchUlDat.pdu = ulData->pduInfo[idx].pduBuf;
262 KwLiRguCDatInd(pst, suId, &cLchUlDat);
271 lcId = ulData->pduInfo[idx].lcId;
272 dLchData[lcId].pdu.mBuf[dLchData[lcId].pdu.numPdu] = ulData->pduInfo[idx].pduBuf;
273 dLchData[lcId].pdu.numPdu++;
277 /* If any PDU received on dedicated logical channel, copy into RguDDatIndInfo
278 * and call its handler */
281 dLchUlDat.cellId = ulData->cellId;
282 dLchUlDat.rnti = ulData->rnti;
284 for(idx = 0; idx < RGU_MAX_LC; idx++)
286 if(dLchData[idx].pdu.numPdu)
288 cmMemcpy((U8 *)&dLchUlDat.lchData[numDLch], (U8 *)&dLchData[idx], sizeof(RguLchDatInd));
292 dLchUlDat.numLch = numDLch;
293 KwLiRguDDatInd(pst, suId, &dLchUlDat);
298 }/* End of RlcMacProcUlData */
300 PUBLIC int rlcDDatIndRcvd;
301 PUBLIC int rlcCDatIndRcvd;
303 * @brief Handler to process PDU received from MAC for common logical channels.
306 * This function receives the PDU from MAC for common logical channels
307 * does checks before handing over the PDU to the TM module
309 * @param[in] pst Post structure
310 * @param[in] suId Service User ID
311 * @param[in] datInd Data Indication Information
319 PUBLIC S16 KwLiRguCDatInd
323 RguCDatIndInfo *datInd
326 PUBLIC S16 KwLiRguCDatInd(pst,suId,datInd)
329 RguCDatIndInfo *datInd;
338 #if (ERRCLASS & ERRCLS_INT_PAR)
339 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
341 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
346 tKwCb = KW_GET_KWCB(pst->dstInst);
349 #if (ERRCLASS & ERRCLS_DEBUG)
350 if (tKwCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
352 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
357 /* kw006.201 ccpu00120058, Added array boundary condition check */
358 #if (ERRCLASS & ERRCLS_DEBUG)
359 if(KW_MAX_LCH_PER_CELL <= datInd->lcId)
361 RLOG_ARG1(L_ERROR,DBG_LCID,datInd->lcId, "Invalid LcId, Max is [%d]",
362 KW_MAX_LCH_PER_CELL);
363 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
366 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
368 /* Fetch RbCb from lcId */
369 kwDbmFetchUlRbCbFromLchId(tKwCb, 0, datInd->cellId, datInd->lcId, &rbCb);
372 RLOG_ARG1(L_ERROR, DBG_CELLID,datInd->cellId, "LcId [%d] not found",
374 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
378 /* Dispatch to TM Module */
380 kwTmmRcvFrmLi(tKwCb, rbCb, datInd->rnti, datInd->pdu);
382 kwTmmRcvFrmLi(tKwCb, rbCb, datInd->pdu);
383 #endif /* CCPU_OPT */
385 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguCDatIndInfo));
388 } /* KwLiRguCDatInd */
391 * @brief Handler to process PDU received from MAC for
392 * dedicated logical channels.
395 * This function receives the PDU from MAC for one or more dedicated
396 * logical channels and passes it to the UTL module for further processing
398 * @param[in] pst Post structure
399 * @param[in] suId Service User ID
400 * @param[in] datInd Data Indication Information
409 PUBLIC S16 KwLiRguDDatInd
413 RguDDatIndInfo *datInd
416 PUBLIC S16 KwLiRguDDatInd(pst, suId, datInd)
419 RguDDatIndInfo *datInd;
425 #if (ERRCLASS & ERRCLS_INT_PAR)
426 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
428 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
433 #if (ERRCLASS & ERRCLS_DEBUG)
434 if (((KwCb*)KW_GET_KWCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_DL)
436 RLOG1(L_DEBUG,"KwLiRguDDatInd(pst, suId(%d))recieved in DL Inst",suId);
437 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
441 kwUtlRcvFrmLi(KW_GET_KWCB(pst->dstInst),datInd);
443 #ifdef SS_LOCKLESS_MEMORY
444 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
446 KW_PST_FREE(pst->region, pst->pool, datInd, sizeof(RguDDatIndInfo));
451 } /* KwLiRguDDatInd */
454 /*******************************************************************
456 * @brief Handler for extracting common and dedicated channel
457 * Scheduling result report.
461 * Function : RlcMacProcSchedRep
464 * Handler for extracting common and dedicated channel
465 * Scheduling result report
468 * @return ROK - success
471 * ****************************************************************/
472 PUBLIC S16 RlcMacProcSchedRep(Pst *pst, SuId suId,RlcMacSchedRep *schRep)
474 U8 idx; /* Iterator */
475 U8 nmbDLch = 0; /* Number of dedicated logical channles */
476 RguCStaIndInfo cLchSchInfo; /* Common logical channel scheduling result */
477 RguDStaIndInfo dLchSchInfo; /* Dedicated logical channel scheduling result */
479 for(idx=0; idx < schRep->nmbLch; idx++)
481 /* If it is common channel, fill status indication information
482 * and trigger the handler for each common lch separately */
483 if(schRep->lchSta[idx].commCh)
485 cmMemset((U8*)&cLchSchInfo, (U8)0, sizeof(RguCStaIndInfo));
487 cLchSchInfo.cellId = schRep->cellId;
488 cLchSchInfo.lcId = schRep->lchSta[idx].lchStaInd.lcId;
489 //cLchSchInfo.transId = schRep->timeToTx; /* TODO : fill transId suing timeToTx */
490 cLchSchInfo.rnti = schRep->rnti;
492 KwLiRguCStaInd(pst, suId, &cLchSchInfo);
497 /* Fill status info structure if at least one dedicated channel
498 * scheduling report is received */
501 dLchSchInfo.cellId = schRep->cellId;
502 dLchSchInfo.nmbOfUeGrantPerTti = 1;
503 dLchSchInfo.staInd[0].rnti = schRep->rnti;
504 //dLchSchInfo.staInd[0].transId = schRep->timeToTx; /* TODO : fill transId suing timeToTx */
505 dLchSchInfo.staInd[0].nmbOfTbs = 1;
506 //dLchSchInfo.staInd[0].fillCrlPdu = /* TODO : Check the value needed to be filled */
509 /* Fill logical channel scheduling info */
510 cmMemcpy((U8 *)&dLchSchInfo.staInd[0].staIndTb[0].lchStaInd[nmbDLch], (U8 *)&schRep->lchSta[idx].lchStaInd, sizeof(RguLchStaInd));
517 /* Calling handler for all dedicated channels scheduling*/
520 dLchSchInfo.staInd[0].staIndTb[0].nmbLch = nmbDLch;
521 KwLiRguDStaInd(pst, suId, &dLchSchInfo);
528 * @brief Handler for trigerring the data transfer from RLC to MAC
529 * for common logical channels.
532 * This function receives the size of the PDU to be transmitted
533 * and acts as a trigger for forming PDU and sending it to MAC.
535 * @param[in] pst Post structure
536 * @param[in] suId Service User ID
537 * @param[in] staInd Status Indication Information for Common Logical
546 PUBLIC S16 KwLiRguCStaInd
550 RguCStaIndInfo *staInd
553 PUBLIC S16 KwLiRguCStaInd(pst,suId,staInd)
556 RguCStaIndInfo *staInd;
564 #if (ERRCLASS & ERRCLS_INT_PAR)
565 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
567 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
572 tKwCb = KW_GET_KWCB(pst->dstInst);
575 #if (ERRCLASS & ERRCLS_INT_PAR)
576 if ((suId >= tKwCb->genCfg.maxRguSaps) || (suId < 0))
582 "KwLiRguCStaInd: Invalid RGU suId\n");
585 if (tKwCb->genCfg.rlcMode == LKW_RLC_MODE_UL)
587 RLOG_ARG1(L_ERROR,DBG_LCID,staInd->lcId,
588 "Received in RLC UL CELLID:%d",
590 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
597 /* kw006.201 ccpu00120058, added boundary condition check */
598 #if (ERRCLASS & ERRCLS_DEBUG)
599 if(KW_MAX_LCH_PER_CELL < staInd->lcId)
601 RLOG_ARG2(L_ERROR,DBG_LCID,staInd->lcId,
602 "Invalid LcId, Max is [%d] CELLID:%d",
605 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
608 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
609 /* Fertch RbCb from lcId */
610 kwDbmFetchDlRbCbFromLchId(tKwCb,0, staInd->cellId, staInd->lcId, &rbCb);
613 RLOG_ARG1(L_ERROR, DBG_CELLID,staInd->cellId,
614 "LcId [%d] not found CELLID:%d",
616 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
620 /* Dispatch to TM Module */
621 rbCb->transId = staInd->transId;
623 /* If trace flag is enabled send the trace indication */
624 if(tKwCb->init.trc == TRUE)
626 /* Populate the trace params */
627 kwLmmSendTrc(tKwCb,EVTRGUCSTAIND, NULLP);
629 kwTmmSndToLi(tKwCb, suId, rbCb, staInd);
631 #ifdef SS_LOCKLESS_MEMORY
632 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
634 KW_PST_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
637 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguCStaIndInfo));
640 } /* KwLiRguCStaInd */
643 * @brief Handler for trigerring the data transfer from RLC to MAC
644 * for dedicated logical channels.
647 * This function receives the size of the PDUs to be transmitted to
648 * MAC via one or more dedicated logical channels and acts as a trigger
649 * for forming PDUs and sending them to MAC.
651 * @param[in] pst Post structure
652 * @param[in] suId Service User ID
653 * @param[in] staInd Status Indication Information for Dedicated Logical
662 PUBLIC S16 KwLiRguDStaInd
666 RguDStaIndInfo *staInd
669 PUBLIC S16 KwLiRguDStaInd(pst, suId, staInd)
672 RguDStaIndInfo *staInd;
678 #if (ERRCLASS & ERRCLS_INT_PAR)
679 if (pst->dstInst >= KW_MAX_RLC_INSTANCES)
681 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
686 gCb = KW_GET_KWCB(pst->dstInst);
688 #if (ERRCLASS & ERRCLS_INT_PAR)
689 if (((KwCb*)KW_GET_KWCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_UL)
691 RLOG_ARG0(L_ERROR,DBG_CELLID,staInd->cellId,"Received in RLC UL ");
692 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
695 if ((suId >= gCb->genCfg.maxRguSaps) || (suId < 0))
701 "KwLiRguDStaInd: Invalid RGU suId\n");
705 kwUtlSndToLi(gCb, suId, staInd);
707 /* kw002.201 :Freeing from proper region */
708 KW_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, staInd, sizeof(RguDStaIndInfo));
710 } /* KwLiRguDStaInd */
713 * @brief Handler for handling the flow cntrl Ind from MAC
717 * This function receives the flow control indication from
718 * MAC and calls kwUtlTrigPdbFlowCntrl
720 * @param[in] pst Post structure
721 * @param[in] suId Service User ID
722 * @param[in] flowCntrlInd flow control Indication Information
731 PUBLIC S16 KwLiRguFlowCntrlInd
735 RguFlowCntrlInd *flowCntrlInd
738 PUBLIC S16 KwLiRguFlowCntrlInd(pst, suId, flowCntrlInd)
741 RguFlowCntrlInd *flowCntrlInd;
745 KwDlRbCb *rbCb = NULLP;
749 tKwCb = KW_GET_KWCB(pst->dstInst);
750 for (idx = 0; idx < flowCntrlInd->numUes; idx++)
752 for (lcIdx = 0; lcIdx < flowCntrlInd->ueFlowCntrlInfo[idx].numLcs; lcIdx++)
754 RguLcFlowCntrlInfo *lcInfo = &(flowCntrlInd->ueFlowCntrlInfo[idx].lcInfo[lcIdx]);
755 kwDbmFetchDlRbCbFromLchId(tKwCb, flowCntrlInd->ueFlowCntrlInfo[idx].ueId, flowCntrlInd->cellId, lcInfo->lcId, &rbCb);
759 if (lcInfo->pktAdmitCnt == 0) /* Special case */
761 kwUtlTrigPdbFlowCntrl(tKwCb, rbCb, lcInfo->pktAdmitCnt);
764 if (rbCb->mode == CM_LTE_MODE_AM)
766 if ((rbCb->m.amDl.retxLst.count != 0) ||
767 ((rbCb->m.amDl.bo == 0) ||
768 (rbCb->m.amDl.bo < lcInfo->maxBo4FlowCtrl)))
775 if ((rbCb->m.umDl.bo == 0) ||
776 (rbCb->m.umDl.bo < lcInfo->maxBo4FlowCtrl))
781 kwUtlTrigPdbFlowCntrl(tKwCb, rbCb, lcInfo->pktAdmitCnt);
787 /* kw005.201 added support for L2 Measurement */
794 * Handler for indicating the Harq Status of the data sent.
798 * This function receives the harq status of the data sent to MAC.
799 * This information is used for two things.
800 * 1. Computing the UuLoss of UM
801 * 2. Computing the DL Delay for UM and AM.
803 * @param[in] pst - Post structure
804 * @param[in] suId - Service User ID
805 * @param[in] staInd - Harq Status Indication Information.
813 PUBLIC S16 KwLiRguHqStaInd
817 RguHarqStatusInd *staInd
820 PUBLIC S16 KwLiRguHqStaInd(pst,suId,staInd)
823 RguHarqStatusInd *staInd;
833 TRC3(KwLiRguHqStaInd)
835 tKwCb = KW_GET_KWCB(pst->dstInst);
836 ueKey.cellId = staInd->cellId;
837 ueKey.ueId = staInd->ueId;
839 ret = kwDbmFetchDlUeCb(tKwCb, ueKey.ueId, ueKey.cellId, &ueCb);
845 /*Call kwUtlProcHarqInd as many times as number of Tbs present*/
846 for ( tbIdx = 0; tbIdx < staInd->numTbs; tbIdx++)
848 kwUtlProcHarqInd(tKwCb, staInd, ueCb, tbIdx);
852 } /* KwLiRguHqStaInd */
853 #endif /* LTE_L2_MEAS */
857 #endif /* __cplusplus */
859 /********************************************************************30**
861 **********************************************************************/