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: PDCP - TMR module file
25 Desc: Source code for timer functions such as,
32 - pjHdlUeDelWaitTmrExp
36 *********************************************************************21*/
37 static const char* RLOG_MODULE_NAME="PDCP";
38 static int RLOG_MODULE_ID=1024;
39 static int RLOG_FILE_ID=223;
42 /* header (.h) include files */
43 #include "envopt.h" /* environment options */
44 #include "envdep.h" /* environment dependent */
45 #include "envind.h" /* environment independent */
47 #include "gen.h" /* general */
48 #include "ssi.h" /* system services */
49 #include "cm5.h" /* common timer defines */
50 #include "cm_tkns.h" /* common tokens defines */
51 #include "cm_mblk.h" /* common memory allocation library defines */
52 #include "cm_llist.h" /* common link list defines */
53 #include "cm_hash.h" /* common hash list defines */
54 #include "cm_lte.h" /* common LTE defines */
55 #include "cpj.h" /* RRC layer */
56 #include "pju.h" /* PDCP service user */
58 #include "lpj.h" /* LPJ defines */
59 #include "pj_env.h" /* RLC environment options */
60 #include "pj.h" /* RLC defines */
61 #include "pj_err.h" /* Error defines */
64 /* extern (.x) include files */
65 #include "gen.x" /* general */
66 #include "ssi.x" /* system services */
67 #include "cm5.x" /* common timer library */
68 #include "cm_tkns.x" /* common tokens */
69 #include "cm_mblk.x" /* common memory allocation */
70 #include "cm_llist.x" /* common link list */
71 #include "cm_hash.x" /* common hash list */
72 #include "cm_lte.x" /* common LTE includes */
73 #include "cm_lib.x" /* common memory allocation library */
74 #include "cpj.x" /* RRC layer */
76 #include "pju.x" /* PDCP service user */
77 #include "lpj.x" /* LPJ */
88 /* forward references */
89 PRIVATE Void pjBndTmrExpiry ARGS ((S16 tmrEvnt, PTR cb));
90 /* public variable declarations */
92 /* This structure holds all the global structs we need. */
94 /* private variable declarations */
96 /* private function declarations */
98 @brief PDCP Timer Module
102 * @def PJ_TMR_CALCUATE_WAIT
104 * This macro calculates and assigns wait time based on the value of the
105 * timer and the timer resolution. Timer value of 0 signifies that the
106 * timer is not configured
108 * @param[out] _wait Time for which to arm the timer changed to proper
109 * value according to the resolution
110 * @param[in] _tmrVal Value of the timer
111 * @param[in] _timerRes Resolution of the timer
114 #define PJ_TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes) \
116 (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \
117 if((0 != (_tmrVal)) && (0 == (_wait))) \
125 * @brief Handler to start timer
129 * This function is invoked by DLM modules to start the discard timer for SDUs.
132 * @param[in] cb Transmission Buffer control block
133 * @param[in] tmrEvnt Timer event to be started
141 PUBLIC S16 pjStartTmr
144 PTR cb, /* Parent control block */
145 S16 tmrEvnt /* Timer event */
148 PUBLIC S16 pjStartTmr (gCb, cb, tmrEvnt)
150 PTR cb; /* Parent control block */
151 S16 tmrEvnt; /* Timer event */
154 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
162 /* kw005.201 added support for L2 Measurement */
163 #ifdef LTE_L2_MEAS_COMMENT
164 PjL2MeasEvtCb *measEvtCb;
168 PjL2Cb *pjL2Cb = NULLP;
169 PjCb *tPjMeasCb = NULLP;
175 RLOG1(L_DEBUG, "pjStartTmr(cb, tmrEvnt (%d)) ", tmrEvnt);
177 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
190 case PJ_EVT_WAIT_KWU_BNDCFM:
192 PjKwuSapCb *kwuSap = (PjKwuSapCb *)cb;
193 wait = (U16)((kwuSap->bndTmrInt * SS_TICKS_SEC)/(gCb->pjGenCfg.timeRes * 1000)); /*KW_FIX*/
194 if( (0 != kwuSap->bndTmrInt) && (0 == wait) )
198 tmr = &kwuSap->bndTmr;
199 maxTmrs = PJ_MAX_KWUSAP_TMR;
202 case PJ_EVT_WAIT_UDX_BNDCFM:
204 PjUdxUlSapCb *udxSap = (PjUdxUlSapCb *)cb;
205 wait = (U16)((udxSap->bndTmrInt * SS_TICKS_SEC)/(gCb->pjGenCfg.timeRes * 1000)); /*KW_FIX*/
206 if( (0 != udxSap->bndTmrInt) && (0 == wait) )
210 tmr = &udxSap->bndTmr;
211 maxTmrs = PJ_MAX_UDXSAP_TMR;
214 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
215 case PJ_EVT_DL_OBD_TMR:
217 dlRbCb = (PjDlRbCb *)cb;
218 tmr=&(dlRbCb->dlCb.obdTmr);
219 maxTmrs = PJ_MAX_OBD_TMR;
220 txEnt = pjDbmGetTxEnt(gCb,&(dlRbCb->dlCb.txBuf), dlRbCb->dlCb.nxtToSub);
221 if ( txEnt != NULLP )
223 wait = gCb->pjGenCfg.obdTmrInt;
224 dlRbCb->dlCb.obdCount = txEnt->count;
229 case PJ_EVT_UL_OBD_TMR:
231 ulRbCb = (PjUlRbCb *)cb;
232 tmr=&(ulRbCb->ulCb.obdTmr);
233 maxTmrs = PJ_MAX_OBD_TMR;
234 PJ_ULM_GET_SUBCNT(ulRbCb,(ulRbCb->ulCb.obdPdu),gCb);
235 if(pjDbmGetRxEnt(gCb,&(ulRbCb->ulCb.recBuf), ulRbCb->ulCb.obdPdu) != NULLP )
237 wait = gCb->pjGenCfg.obdTmrInt;
242 case PJ_EVT_OBD_WAIT_TMR:
244 if (gCb->pjGenCfg.mode == LPJ_MODE_PDCP_DL)
246 PjDlUeCb *dlUeCb = (PjDlUeCb *)cb;
247 tmr=&(dlUeCb->libInfo.obdTmr);
251 PjUlUeCb *ulUeCb = (PjUlUeCb *)cb;
252 tmr=&(ulUeCb->libInfo.obdTmr);
254 maxTmrs = PJ_MAX_OBD_TMR;
255 wait = gCb->pjGenCfg.obdWtTmrInt;
260 /* kw005.201 added support for L2 Measurement */
261 #ifdef LTE_L2_MEAS_COMMENT
264 measEvtCb = (PjL2MeasEvtCb *)cb;
265 tmr=&(measEvtCb->l2Tmr);
266 maxTmrs = PJ_L2_MAX_TIMERS;
267 wait = (measEvtCb->l2TmrCfg.val * SS_TICKS_SEC)/(pjCb.genCfg.timeRes * 1000);
268 if((measEvtCb->l2TmrCfg.val > 0) && wait == 0)
276 case PJ_EVT_L2_MEAS_TMR:
278 tPjMeasCb = (PjCb *)cb;
279 pjL2Cb = &tPjMeasCb->u.ulCb->pjL2Cb;
280 tmr=&(pjL2Cb->measTmr);
281 maxTmrs = PJ_L2_MAX_TIMERS;
282 wait = (pjL2Cb->measTmrCfg.val * SS_TICKS_SEC)/(gCb->pjGenCfg.timeRes * 1000);
284 if((pjL2Cb->measTmrCfg.val > 0) && wait == 0)
291 case PJ_EVT_UL_REORD_TMR:
293 ulRbCb = (PjUlRbCb *)cb;
294 tmr=&(ulRbCb->ulCb.tReordTmr);
295 maxTmrs = PJ_MAX_UL_REORD_TMRS;
296 PJ_TMR_CALCUATE_WAIT(wait, ulRbCb->reOrdrTmrVal, gCb->pjGenCfg.timeRes);
301 RLOG0(L_ERROR, "Invalid Start tmr Evnt");
308 arg.tqCp = &gCb->pjTqCp;
325 * @brief Handler to stop timer
329 * This function is used to stop protocol timer, based on the timer event.
332 * @param[in] cb Transmission Buffer control block
333 * @param[in] tmrEvnt Timer event to be started
344 PTR cb, /* Parent control block */
345 U8 tmrEvnt /* Timer */
348 PUBLIC S16 pjStopTmr (gCb, cb, tmrEvnt)
350 PTR cb; /* Parent control block */
351 U8 tmrEvnt; /* Timer */
356 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
360 PjUdxUlSapCb *udxSap;
361 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
365 /* kw005.201 added support for L2 Measurement */
367 PjL2Cb *pjL2Cb = NULLP;
368 PjCb *tPjMeasCb = NULLP;
375 RLOG1(L_DEBUG, "pjStopTmr(cb, tmrEvnt(%d)) ", tmrEvnt);
379 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
387 case PJ_EVT_WAIT_KWU_BNDCFM:
389 kwuSap = (PjKwuSapCb *)cb;
390 tmr = &kwuSap->bndTmr;
391 arg.max = PJ_MAX_KWUSAP_TMR;
394 case PJ_EVT_WAIT_UDX_BNDCFM:
396 udxSap = (PjUdxUlSapCb *)cb;
397 tmr = &udxSap->bndTmr;
398 arg.max = PJ_MAX_UDXSAP_TMR;
401 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
402 case PJ_EVT_DL_OBD_TMR:
404 pjDlRbCb = (PjDlRbCb *)cb;
405 tmr = &(pjDlRbCb->dlCb.obdTmr);
406 maxTimers = PJ_MAX_OBD_TMR;
409 case PJ_EVT_UL_OBD_TMR:
411 pjUlRbCb = (PjUlRbCb *)cb;
412 tmr = &(pjUlRbCb->ulCb.obdTmr);
413 maxTimers = PJ_MAX_OBD_TMR;
416 case PJ_EVT_OBD_WAIT_TMR:
418 /*if (gCb->pjGenCfg.mode == LPJ_PDCP_MODE_DL)*/
419 if (gCb->pjGenCfg.mode == LPJ_MODE_PDCP_DL)
421 dlUeCb = (PjDlUeCb *)cb;
422 tmr = &(dlUeCb->libInfo.obdTmr);
426 ulUeCb = (PjUlUeCb *)cb;
427 tmr = &(ulUeCb->libInfo.obdTmr);
429 maxTimers = PJ_MAX_OBD_TMR;
434 /* kw005.201 added support for L2 Measurement */
435 #ifdef LTE_L2_MEAS_COMMENT
438 measEvtCb = (PjL2MeasEvtCb *)cb;
439 tmr = &(measEvtCb->l2Tmr);
440 maxTimers = PJ_L2_MAX_TIMERS;
445 case PJ_EVT_L2_MEAS_TMR:
447 tPjMeasCb = (PjCb *)cb;
448 pjL2Cb = &tPjMeasCb->u.ulCb->pjL2Cb;
449 tmr = &(pjL2Cb->measTmr);
450 maxTimers = PJ_L2_MAX_TIMERS;
454 case PJ_EVT_UL_REORD_TMR:
456 pjUlRbCb = (PjUlRbCb *)cb;
457 tmr=&(pjUlRbCb->ulCb.tReordTmr);
458 maxTimers = PJ_MAX_UL_REORD_TMRS;
463 RLOG0(L_ERROR, "Invalid Stop tmr Evnt");
471 arg.tqCp = &gCb->pjTqCp;
488 * @brief Handler to invoke events on expiry of timer.
492 * This function is used to handle expiry of timer,it invokes relevant functions.
495 * @param[in] cb Transmission Buffer control block
496 * @param[in] tmrType Type of the timer to be stopped
504 PUBLIC S16 pjTmrExpiry
506 PTR cb, /* Parent control block */
507 S16 tmrEvnt /* Timer event */
510 PUBLIC S16 pjTmrExpiry (cb, tmrEvnt)
511 PTR cb; /* Parent control block */
512 S16 tmrEvnt; /* Timer event */
515 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
516 PjDlRbCb *dlRbCb = NULLP;
517 PjDlUeCb *dlUeCb = NULLP;
518 PjUlUeCb *ulUeCb = NULLP;
520 PjUlRbCb *ulRbCb = NULLP;
522 PjL2Cb *pjL2Cb = NULLP;
523 PjCb *tPjMeasCb = NULLP;
525 /* pj005.201 added support for L2 Measurement */
530 case PJ_EVT_WAIT_KWU_BNDCFM:
532 pjBndTmrExpiry(tmrEvnt,cb);
533 /* kw005.201 added missing break statement */
536 case PJ_EVT_WAIT_UDX_BNDCFM:
538 pjBndTmrExpiry(tmrEvnt,cb);
539 /* kw005.201 added missing break statement */
542 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
543 case PJ_EVT_DL_OBD_TMR:
546 dlRbCb = (PjDlRbCb *)cb;
548 if (dlRbCb->ueCb->inst >= PJ_MAX_PDCP_INSTANCES)
552 tPjCb = PJ_GET_PJCB(dlRbCb->ueCb->inst);
554 pjDlmObdTmrExp(tPjCb,dlRbCb);
557 case PJ_EVT_UL_OBD_TMR:
560 ulRbCb = (PjUlRbCb *)cb;
562 if (ulRbCb->ueCb->inst >= PJ_MAX_PDCP_INSTANCES)
566 tPjCb = PJ_GET_PJCB(ulRbCb->ueCb->inst);
567 pjUlmHdlObdTmrExpiry(tPjCb,ulRbCb);
570 case PJ_EVT_OBD_WAIT_TMR:
574 if (tPjCb->pjGenCfg.mode == LPJ_MODE_PDCP_UL)
576 ulUeCb = (PjUlUeCb *)cb;
577 if (ulUeCb->inst >= PJ_MAX_PDCP_INSTANCES)
581 tPjCb = PJ_GET_PJCB(ulUeCb->inst);
582 pjUtlUlHdlInitObdTmrExp(tPjCb,ulUeCb);
587 dlUeCb = (PjDlUeCb *)cb;
588 if (dlUeCb->inst >= PJ_MAX_PDCP_INSTANCES)
592 tPjCb = PJ_GET_PJCB(dlUeCb->inst);
593 pjUtlDlHdlInitObdTmrExp(tPjCb,dlUeCb);
600 case PJ_EVT_L2_MEAS_TMR:
602 tPjMeasCb = (PjCb *)cb;
603 pjL2Cb = &tPjMeasCb->u.ulCb->pjL2Cb;
604 pjUtlMemCpuHdlTmrExp((PjCb *)cb,pjL2Cb);
608 case PJ_EVT_UL_REORD_TMR:
611 ulRbCb = (PjUlRbCb *)cb;
612 if (ulRbCb->ueCb->inst >= PJ_MAX_PDCP_INSTANCES)
616 tPjCb = PJ_GET_PJCB(ulRbCb->ueCb->inst);
617 pjUlmHdlReordTmrExpiry(tPjCb, ulRbCb);
620 /* pj005.201 added support for L2 Measurement */
632 * @brief Handler to check if the timer is running
636 * This function is used to check if the timer is running at the given
640 * @param[in] cb Transmission Buffer control block
641 * @param[in] tmrType Type of the timer to be stopped
652 PTR cb, /* Parent control block */
653 S16 tmrEvnt /* Timer event */
656 PUBLIC Bool pjChkTmr(gCb, cb, tmrEvnt)
658 PTR cb; /* Parent control block */
659 S16 tmrEvnt; /* Timer event */
662 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
663 PjDlUeCb *dlUeCb = NULLP;
664 PjUlUeCb *ulUeCb = NULLP;
667 PjL2Cb *pjL2Cb = NULLP;
668 PjCb *tPjMeasCb = NULLP;
670 Bool tmrRunning = FALSE;
671 PjUlRbCb *ulRbCb = NULLP;
675 RLOG1(L_UNUSED, "pjChkTmr(cb, tmrEvnt(%d)) ", tmrEvnt);
679 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
680 case PJ_EVT_DL_OBD_TMR:
682 dlRbCb = (PjDlRbCb *)cb;
683 if (dlRbCb->dlCb.obdTmr.tmrEvnt == PJ_EVT_DL_OBD_TMR)
689 case PJ_EVT_UL_OBD_TMR:
691 ulRbCb = (PjUlRbCb *)cb;
692 if (ulRbCb->ulCb.obdTmr.tmrEvnt == PJ_EVT_UL_OBD_TMR)
698 case PJ_EVT_OBD_WAIT_TMR:
700 if(gCb->pjGenCfg.mode == LPJ_MODE_PDCP_UL)
702 ulUeCb = (PjUlUeCb *)cb;
703 if (ulUeCb->inst >= PJ_MAX_PDCP_INSTANCES)
707 if (ulUeCb->libInfo.obdTmr.tmrEvnt == PJ_EVT_OBD_WAIT_TMR)
714 dlUeCb = (PjDlUeCb *)cb;
715 if (dlUeCb->inst >= PJ_MAX_PDCP_INSTANCES)
719 if (dlUeCb->libInfo.obdTmr.tmrEvnt == PJ_EVT_OBD_WAIT_TMR)
728 case PJ_EVT_L2_MEAS_TMR:
730 tPjMeasCb = (PjCb *)cb;
731 pjL2Cb = &tPjMeasCb->u.ulCb->pjL2Cb;
732 if (pjL2Cb->measTmr.tmrEvnt == PJ_EVT_L2_MEAS_TMR)
739 case PJ_EVT_UL_REORD_TMR:
741 ulRbCb = (PjUlRbCb *)cb;
742 if(PJ_EVT_UL_REORD_TMR == ulRbCb->ulCb.tReordTmr.tmrEvnt)
751 RLOG0(L_ERROR, "Invalid Chk tmr Evnt");
756 RETVALUE(tmrRunning);
760 * @brief Private handler to invoke an event for bind timer expiry
764 * This function processes the RLC bind timer expiry. If the number of retry is
765 * less than the maximum retry counter, bind request is sent again, else an
766 * alarm is raised to the layer manager.
769 * @param[in] cb RB control block
776 PRIVATE Void pjBndTmrExpiry
779 PTR cb /* Parent control block */
782 PRIVATE Void pjBndTmrExpiry(tmrEvnt, cb)
784 PTR cb; /* Parent control block */
788 PjUdxUlSapCb *udxSap;
789 PjKwuSapCb *kwuSapCb;
793 if (tmrEvnt == PJ_EVT_WAIT_KWU_BNDCFM)
795 kwuSapCb = (PjKwuSapCb *) cb;
797 tPjCb = PJ_GET_PJCB(kwuSapCb->pst.srcInst);
798 if (kwuSapCb->state == PJ_SAP_BINDING)
800 if (kwuSapCb->retryCnt < PJ_MAX_SAP_BND_RETRY)
802 /* Send bind request */
803 kwuSapCb->retryCnt++;
805 /* start timer to wait for bind confirm */
806 pjStartTmr(tPjCb, (PTR)kwuSapCb, PJ_EVT_WAIT_KWU_BNDCFM);
808 PjLiKwuBndReq (&kwuSapCb->pst, kwuSapCb->suId, kwuSapCb->spId);
812 kwuSapCb->retryCnt = 0;
813 kwuSapCb->state = PJ_SAP_CFG;
815 /* Send alarm to the layer manager */
817 pjLmmSendAlarm(tPjCb,LCM_CATEGORY_INTERFACE, LCM_EVENT_BND_FAIL,
818 LCM_CAUSE_TMR_EXPIRED, 0, 0, 0);
820 pjLmmSendAlarm(tPjCb,LCM_CATEGORY_INTERFACE, LCM_EVENT_BND_FAIL,
821 LCM_CAUSE_TMR_EXPIRED, 0, 0);
828 udxSap = (PjUdxUlSapCb *)cb;
830 tPjCb = PJ_GET_PJCB (udxSap->pst.srcInst);
832 if (udxSap->state == PJ_SAP_BINDING)
834 if (udxSap->retryCnt < PJ_MAX_SAP_BND_RETRY)
836 /* Send bind request */
839 /* start timer to wait for bind confirm */
840 pjStartTmr(tPjCb, (PTR)udxSap, PJ_EVT_WAIT_UDX_BNDCFM);
842 PjUlUdxBndReq (&udxSap->pst, udxSap->suId, udxSap->spId);
846 udxSap->retryCnt = 0;
847 udxSap->state = PJ_SAP_CFG;
849 /* Send alarm to the layer manager */
851 pjLmmSendAlarm(tPjCb,LCM_CATEGORY_INTERFACE, LCM_EVENT_BND_FAIL,
852 LCM_CAUSE_TMR_EXPIRED, 0, 0, 0);
854 pjLmmSendAlarm(tPjCb,LCM_CATEGORY_INTERFACE, LCM_EVENT_BND_FAIL,
855 LCM_CAUSE_TMR_EXPIRED, 0, 0);
867 /********************************************************************30**
870 **********************************************************************/