Merge "Documentation updates"
[o-du/l2.git] / src / 5gnrmac / rg_dhm.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     LTE-MAC layer
22   
23      Type:     C source file
24   
25      Desc:     C source code for Entry point fucntions
26   
27      File:     rg_dhm.c
28   
29 **********************************************************************/
30
31 /** @file rg_dhm.c
32 @brief APIs related to Downlink HARQ.
33 */
34
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_FILE_ID=279;
37 static int RLOG_MODULE_ID=4096;
38 /* header include files -- defines (.h) */
39 #include "common_def.h"
40 #ifdef L2_OPTMZ
41 #include "ss_strm.h"
42 #endif
43 #include "lrg.h"
44 #include "crg.h"
45 #include "tfu.h"
46 #include "rgu.h"
47 #include "rg_sch_inf.h"
48 #include "rg_env.h"
49 #include "rg_err.h"
50 #include "rg.h"
51 #include "du_app_mac_inf.h"
52
53 /* header/extern include files (.x) */
54 #ifdef L2_OPTMZ
55 #include "ss_strm.x"
56 #endif
57 #include "lrg.x"
58 #include "crg.x"
59 #include "tfu.x"
60 #include "rgu.x"
61 #include "rg_sch_inf.x"
62 #include "rg_prg.x"        /* PRG interface typedefs */
63 #include "rg.x"
64
65 #ifdef L2_OPTMZ
66 #include "ss_queue.h"
67 #include "ss_queue.x"
68 #include "ss_task.x"
69 #include "ss_msg.x"            /* MAC includes */
70 /* local defines */
71 // S16 ssGetDBufOfSize(Region region,Size size,Buffer **dBuf);
72 //void prc_trace_format_string(UINT32 group_mask, UINT16 level, const char *format, ...);
73 #endif
74
75 /* local typedefs */
76  
77 /* local externs */
78 S16 SIncMsgRef(Buffer *srcBuf,Region dstRegion, Pool dstPool,Buffer **dstBuf);
79
80 static Void rgDHMBldTfuDatReq ARGS((RgCellCb *cellCb, RgDlSf *dlSf, RgDlHqProcCb *hqP,
81                            RgTfuDatReqPduInfo *datReq));
82
83 #ifdef L2_OPTMZ
84 S16 rgDHMFreeHqProcTB
85 (
86 RgDlHqProcCb *hqP,
87 uint8_t      tbIndex
88 );
89
90 #endif
91
92 /* forward references */
93
94 /**
95  * @brief This function initializes the DL HARQ Entity of UE
96  *
97  * @details
98  *
99  *     Function: rgDHMHqEntInit
100  *     Purpose:  This function initializes the DL HARQ entity of 
101  *               UE control block. This is performed at the time
102  *               of creating UE control block.
103  *     
104  *     Invoked by: configuration module
105  *     
106  *  @param[in]  Inst        inst
107  *  @param[in]  RgCellCb*  cell
108  *  @param[in]  RgUeCb*    ue
109  *  @return  S16
110  *           -# ROK
111  *           -# RFAILED
112  *
113  **/
114 S16 rgDHMHqEntInit(Inst  inst, RgDlHqEnt *hqE, uint8_t maxHqProcs)
115 {
116    uint8_t idx1,idx2;
117 #ifdef L2_OPTMZ
118    Buffer  *hdrDBuf = NULLP;
119    Buffer  *ceDBuf = NULLP;
120 #endif
121
122    hqE->numHqProcs = maxHqProcs;
123    /* for each harq process */
124    for (idx1 = 0; idx1 < hqE->numHqProcs; idx1++)
125    {
126       if (rgAllocSBuf(inst,(Data **)&(hqE->procs[idx1]),sizeof(RgDlHqProcCb)) != ROK) 
127       {
128          while(idx1--)
129          {
130             rgFreeSBuf(inst,(Data **)&(hqE->procs[idx1]), sizeof(RgDlHqProcCb));
131          }
132          RLOG0(L_ERROR, "Memory Alloc Failure for RgDlHqProcCb");        
133          return RFAILED;
134       }
135
136       hqE->procs[idx1]->procId      = idx1;
137       for(idx2 = 0; idx2 < RG_MAX_TB_PER_UE; idx2++)
138       {
139 #ifndef L2_OPTMZ
140          hqE->procs[idx1]->tbInfo[idx2].tb = NULLP;
141 #else
142          Buffer *tmpMBuf;
143          /* L2 optimization for mUe/Tti: Allocating buffers for macHdr, macCes
144           * and macPadding. These buffers shall not be released by MAC/CL.
145           * However, Only rPtr and wPtr will be reset while release of hq proc
146           */
147          tmpMBuf = hqE->procs[idx1]->tbInfo[idx2].tb.macHdr;
148          rgGetMsg(inst, &tmpMBuf);
149          RG_ADD_DBuf(hdrDBuf, RG_MAC_HDR_SIZE, tmpMBuf);
150          hqE->procs[idx1]->tbInfo[idx2].tb.macHdr = tmpMBuf;
151          macHeader[idx2] = MacPtrAddress;
152
153          tmpMBuf = hqE->procs[idx1]->tbInfo[idx2].tb.macCes;
154          rgGetMsg(inst, &tmpMBuf);
155          RG_ADD_DBuf(ceDBuf, RG_MAC_CE_SIZE, tmpMBuf);
156          hqE->procs[idx1]->tbInfo[idx2].tb.macCes = tmpMBuf;
157
158          hqE->procs[idx1]->tbInfo[idx2].tb.padSize = 0;
159 #endif
160 #ifdef LTE_L2_MEAS
161          hqE->procs[idx1]->tbId[idx2] = RGU_INVALID_TBID;
162 #endif
163       }
164
165       cmLListInit(&hqE->savedProcLst[idx1]);
166    }
167
168
169    return ROK;
170 } /* rgDHMHqEntInit */
171
172 /**
173  * @brief This function releases a HARQ process
174  *
175  * @details
176  *
177  *     Function: rgDHMUeReset
178  *     Purpose:  This function resets TB in each HarqProc.
179  *     
180  *     Invoked by: CFG UE Reset 
181  *     
182  *  @param[in]  RgDlHqProc    *hqP
183  *  @return  Void      
184  *
185  **/
186 Void rgDHMUeReset(RgCellCb *cell, RgDlHqEnt  *hqE)
187 {
188    uint8_t       i = 0;
189
190    if(hqE->procs[0])
191    {
192       /* Free all the TB memory associated with HARQ */
193       for (i=0; i < hqE->numHqProcs; i++)
194       {
195          rgDHMRlsHqProcTB(cell, hqE->procs[i], 1);
196          rgDHMRlsHqProcTB(cell, hqE->procs[i], 2);
197
198 #ifdef LTE_ADV
199          rgDHMFreeSavedHqP((cell->macInst - RG_INST_START), hqE, i);
200 #endif
201       }
202    }
203    return;
204 } /* rgDHMUeReset*/
205
206 /**
207  * @brief This function defers shared memory buffer
208  *        freeing out of the critical RT path.
209  *
210  * @details
211  *
212  *     Function: rgDHMHdlBufFree
213  *     Purpose: To defer shared memory freeing post 
214  *              critical path. Defer as many if defer queue 
215  *              is full then release instantly.
216  *     
217  *     Invoked by: HARQ TB Release. 
218  *     
219  *  @return  Void      
220  *
221  **/
222 Void rgDHMHdlBufFree(Inst inst, Buffer **mBuf)
223 {
224    RgCb *rgCbP = &rgCb[inst];
225
226    if (rgCbP->bufCnt < RG_MAX_DFRD_FREE_BUFS)
227    {
228       if (*mBuf)
229       {
230          rgCbP->bufToFree[rgCbP->bufCnt] = *mBuf;
231          rgCbP->bufCnt++;
232          *mBuf = NULLP;
233       }
234    }
235    else
236    {
237       RG_FREE_MSG(*mBuf);
238    }
239    return;
240 }
241 /**
242  * @brief This function is called to release the 
243  *        shared memory of the HARQ TBs outside 
244  *        the critical RT path.
245  *
246  * @details
247  *
248  *     Function: rgDHMFreeTbBufs
249  *     Purpose: This function is called to release the 
250  *        shared memory of the HARQ TBs outside 
251  *        the critical RT path.
252  *     
253  *     1. Job of releasing TBs is shared across TTIs
254  *     Invoked by: MAC every TTI 
255  *     
256  *  @return  Void      
257  *
258  **/
259 Void rgDHMFreeTbBufs(Inst inst)
260 {
261    RgCb *rgCbP = &rgCb[inst];
262    uint8_t start = rgCbP->bufCnt;
263    uint8_t end = 0;
264
265    if (rgCbP->bufCnt < RG_MAX_FREE_BUFS_PERTTI)
266    {
267       end = 0;
268    }
269    else
270    {
271       end = rgCbP->bufCnt - RG_MAX_FREE_BUFS_PERTTI;
272    }
273    while (start != end)
274    {
275       start--;
276       SPutMsg(rgCbP->bufToFree[start]);
277    }
278    rgCbP->bufCnt = end;
279    return;
280 } /* rgDHMFreeTbBufs */
281
282 Void rgDHMFreeAllTbBufs(Inst inst)
283 {
284    RgCb *rgCbP = &rgCb[inst];
285    uint8_t start = rgCbP->bufCnt;
286    uint8_t end = 0;
287
288    while (start != end)
289    {
290       start--;
291       SPutMsg(rgCbP->bufToFree[start]);
292    }
293    rgCbP->bufCnt = end;
294    return;
295 } /* rgDHMFreeTbBufs */
296
297
298 /**
299  * @brief This function releases a HARQ process
300  *
301  * @details
302  *
303  *     Function: rgDHMRlsHqProcTB
304  *     Purpose:  This function returns a HARQ process to HARQ Entity 
305  *               in the DL direction.
306  *     
307  *               1. Add the HARQ process to the free queue.
308  *     Invoked by: scheduler and HARQ processing
309  *     
310  *  @param[in]  RgDlHqProc    *hqP
311  *  @return  Void      
312  *
313  **/
314 S16 rgDHMRlsHqProcTB(RgCellCb  *cell, RgDlHqProcCb *hqP, uint8_t tbIndex)
315 {
316     uint8_t          idx;
317 #ifdef L2_OPTMZ
318     RgTfuDatReqTbInfo     *tb;   /* TB to be sent to CL/PHY*/
319    // uint32_t lchIdx, pduIdx;
320 #endif
321
322    if((tbIndex > RG_MAX_TB_PER_UE) ||
323       (tbIndex == 0))
324    {
325       return RFAILED;
326    }
327
328    hqP->tbInfo[tbIndex-1].numSchLch = 0;
329 #ifndef L2_OPTMZ
330    if (hqP->tbInfo[tbIndex-1].tb)
331    {
332       rgDHMHdlBufFree(cell->macInst - RG_INST_START, &hqP->tbInfo[tbIndex-1].tb);
333    }
334 #else
335    /* L2 Optimization for mUe/Tti:  macHdr, macCes and macPad mBuf pointers
336     * shall not be released. However, Inorder to release harq info/TB info,
337     * just Resetting rPtr and wPtr of these mbufs to db_base
338     */
339    tb = &(hqP->tbInfo[tbIndex-1].tb);
340    if (tb->tbPres == TRUE)
341    {
342       RG_FREE_TB(tb);
343    }
344 #endif
345    hqP->tbInfo[tbIndex-1].schdTa.pres = FALSE;
346 #ifdef LTE_ADV
347    hqP->tbInfo[tbIndex -1].sCellActCe.pres = FALSE;
348 #endif
349
350    /* Decrementing might lead to roundoff error in case of say UE reset
351     * where all the HqProcs irrespective whether in use are called for rls.
352     * Hence to avoid the same shift operator is being used. */
353    hqP->numOfTBs = hqP->numOfTBs >> 1;
354    for(idx = 0; idx < 2; idx++)
355    {
356       if (hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sfLnk.node != NULLP)
357    {
358          cmLListDelFrm(&hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sf->tbs,
359                &(hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sfLnk));
360          hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sfLnk.node  = (PTR)NULLP;
361       printf("\nrgDHMRlsHqProcTB:: hqP %p \n", (Void *)hqP);
362    }
363       hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sf = NULLP;
364    }
365    /* Fix : syed It is better to reset these feilds
366     * corruption avoidance */
367    hqP->tbInfo[tbIndex-1].tbSz = 0;
368    hqP->tbInfo[tbIndex-1].contResCe = NOTPRSNT;
369    hqP->tbInfo[tbIndex-1].contResId = NULLP;
370
371    return ROK;
372 } /* rgDHMRlsHqProc */
373
374 /**
375  * @brief This function gets HARQ process with the given Id
376  *
377  * @details
378  *
379  *     Function: rgDHMGetHqProcFrmId
380  *     Purpose:  This function returns the HARQ process with the given ID.
381  *     Invoked by: ROM
382  *     
383  *  @param[in]  RgUeCb        *ue
384  *  @param[in]  uint8_t            idx
385  *  @param[in]  RgDlHqProc    **hqP
386  *  @return  S16       
387  *         -#   ROK     if successful
388  *         -#   RFAILED otherwise
389  *
390  **/
391 S16 rgDHMGetHqProcFrmId(RgUeCb *ue, uint8_t  idx, RgDlHqProcCb **hqP)
392 {
393    /* Pick the proc based on the index provided */
394    *hqP = (ue->dl.hqEnt.procs[idx]);
395
396    return ROK;
397 } /* rgDHMGetHqProcFrmId */
398
399 /*static uint32_t dataAvl; */
400 /**
401  * @brief Handler for sending data to PHY
402  *
403  * @details
404  *
405  *     Function : rgDHMSndDatReq
406  *     
407  *     This function shall send the MAC PDU built for the UE to TOM
408  *     when invoked as part of TTI processing and keep track of the number of
409  *     transmissions for this TB.
410  *     
411  *           
412  *  @param[in]  RgCellCb      *cell
413  *  @param[in]  RgDlHqProcCb  *hqE 
414  *  @param[out] RgErrInfo     *err 
415  *  @return     S16
416  *      -#ROK 
417  *      -#RFAILED 
418  **/
419 S16 rgDHMSndDatReq
420 (
421 RgCellCb        *cellCb,
422 RgDlSf          *dlSf,
423 RgTfuDatReqInfo *datInfo,
424 RgDlHqProcCb   *hqP,
425 RgErrInfo      *err 
426 )
427 {
428    uint8_t i;
429    Inst    inst = cellCb->macInst - RG_INST_START;
430    RgTfuDatReqPduInfo   *datReq;
431    RgBldPduInfo      bldPdu;
432    /*Added this variable to figure out that whether this UE data
433      has to be inclueded in the TFU Data request.*/
434    Bool  dataAvlblUe;
435
436    dataAvlblUe = TRUE;
437    for(i=0;i< RG_MAX_TB_PER_UE;i++)
438    {
439          /* printf("\nDHMSndDatReq1: Rnti %d dlSfSchdTime(sfn sf) : (%d %d)\n"
440                 "macCell(sfn sf): (%d %d) tbTimingInfo(sfn sf): (%d %d)\n"
441                 "dlSf %p dlSf->tbs.count %d hqp %p tb %p\n",
442                              hqP->tbInfo[i].pdcch.rnti,
443                              dlSf->schdTime.sfn, dlSf->schdTime.slot,
444                              cellCb->crntTime.sfn, cellCb->crntTime.slot,
445                              hqP->tbInfo[i].timingInfo.sfn, 
446                              hqP->tbInfo[i].timingInfo.slot,
447                              (Void *)dlSf, dlSf->tbs.count,
448                              (Void *)hqP,
449                              (Void *)hqP->tbInfo[i].tb);*/
450       /* Mukesh :: in case of rpepetiton this is not rerd*/
451       if (hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sf == dlSf)
452       {
453          /* Check if data from RLC had been received and got muxed. */
454 #ifndef L2_OPTMZ
455          if (hqP->tbInfo[i].tb == NULLP) 
456 #else
457          if (!(hqP->tbInfo[i].tb.tbPres)) 
458 #endif
459          {
460 #ifndef LTE_ADV
461             if (hqP->tbInfo[i].schdTa.pres == TRUE ||
462                   hqP->tbInfo[i].contResCe == PRSNT_NODEF)
463 #else
464             if ((hqP->tbInfo[i].schdTa.pres == TRUE) ||
465                  (hqP->tbInfo[i].contResCe == PRSNT_NODEF) ||
466                  (hqP->tbInfo[i].sCellActCe.pres == TRUE))
467 #endif
468             {
469                /* Data not received but ta needs to be sent. */
470                /* MUX TA and send it */
471                bldPdu.datReq    =  NULLP;
472                //bldPdu.reqType   =  EVENT_SLOT_IND_TO_MAC;
473                bldPdu.schdTbSz  =  hqP->tbInfo[i].tbSz;
474                bldPdu.ta        =  hqP->tbInfo[i].schdTa;
475 #ifdef LTE_ADV
476                bldPdu.sCellActCe= hqP->tbInfo[i].sCellActCe;
477 #endif
478                /* changes for CR timer implementation*/
479                bldPdu.contResId =  hqP->tbInfo[i].contResId;
480                if (ROK != rgMUXBldPdu(inst,&bldPdu, &(hqP->tbInfo[i].tb), err))  
481                {
482                   RLOG1(L_ERROR, "MUXing failed for:  MacInst %d", inst);
483                   RLOG4(L_ERROR, "MUXing failed for:  time: %d/%d\
484                   procId %d ueId %d", hqP->tbInfo[i].timingInfo.sfn,
485                   hqP->tbInfo[i].timingInfo.slot, hqP->procId, 
486                   hqP->tbInfo[i].pdcch.rnti);
487
488                   return RFAILED;
489                }
490             }
491             else   
492             {
493 #ifdef LTEMAC_RGU_PAD
494                /* Data not received from RLC. Padding at MAC */
495                bldPdu.datReq    =  NULLP;
496                //bldPdu.reqType   =  EVENT_SLOT_IND_TO_MAC;
497                bldPdu.schdTbSz  =  hqP->tbInfo[i].tbSz;
498                bldPdu.ta        =  hqP->tbInfo[i].schdTa;
499 #ifdef LTE_ADV
500                bldPdu.sCellActCe= hqP->tbInfo[i].sCellActCe;
501 #endif
502                bldPdu.ta.val    =  0;
503                bldPdu.contResId =  NULLP;
504
505                if (ROK != rgMUXBldPdu(inst,&bldPdu, &(hqP->tbInfo[i].tb), err))  
506                {
507                   RLOG1(L_ERROR, "MUXing failed for:  MacInst %d", inst);
508                   RLOG4(L_ERROR, "MUXing failed for:  time: %d/%d\
509                   procId %d ueId %d", hqP->tbInfo[i].timingInfo.sfn,
510                   hqP->tbInfo[i].timingInfo.slot, hqP->procId, 
511                   hqP->tbInfo[i].pdcch.rnti);
512                   
513                   return RFAILED;
514                }
515 #else
516                /*Padding is not done so data for this UE will not be
517                  included.*/
518                dataAvlblUe = FALSE;
519 #endif
520             }
521          }
522          else
523          {
524          }
525       }
526       //else
527       {
528       }
529    }
530
531    /*If Data/Padding is not available for UE, then we can not include
532      any Data for this UE in TFU Data Request.*/
533    if(!dataAvlblUe)
534    {
535       /*Free up the HARQ process for this allocation.*/
536       /* Release First TB, as this would be anyway there*/
537       rgDHMRlsHqProcTB(cellCb, hqP, 1);
538       if(2 == hqP->numOfTBs)
539       {
540          rgDHMRlsHqProcTB(cellCb, hqP, 2);
541       }
542       
543       return ROK;
544    }
545
546    if (rgGetEventMem(inst,(Ptr *)&datReq, sizeof(TfuDatReqPduInfo),
547             &(datInfo->memCp)) != ROK)
548    {
549       return RFAILED;
550    }
551    /* Fill the TFU Dat Req with information from Harq Proc */
552   
553    rgDHMBldTfuDatReq(cellCb, dlSf, hqP, datReq);
554
555    /* MS_WORKAROUND for ccpu00122894 */
556    for(i=0;i< RG_MAX_TB_PER_UE;i++)
557    {
558       if (hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sf == dlSf)
559       {
560          cmLListDelFrm(&dlSf->tbs, &(hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sfLnk));
561          hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sfLnk.node = NULLP;
562          
563         
564         hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sf = NULLP;
565       }
566    }
567    cmLListAdd2Tail(&datInfo->pdus, &(datReq->lnk));
568    datReq->lnk.node = (PTR)datReq;
569
570    return ROK;
571 }  /* rgDHMSndDatReq */
572
573 /**
574  * @brief Function to handle RGU datReq received from ROM
575  *
576  * @details
577  *
578  *     Function : rgDHMHndlDedDatReq
579  *     
580  *     This function shall act on the datReq received on RGU. It shall 
581  *     store the data IDs for all the logical channels and get the MAC 
582  *     PDU built.
583  *     
584  *           
585  *  @param[in]  Inst        inst
586  *  @param[in]  RgDlHqProcCb   *hqProc 
587  *  @param[in]  RgRguDedDatReq *datReq
588  *  @param[out] RgErrInfo      *err
589  *  @return     S16
590  *      -# ROK 
591  *      -# RFAILED 
592  **/
593 S16 rgDHMHndlDedDatReq
594 (
595 Inst           inst,
596 RgDlHqProcCb   *hqProc,
597 RgRguDDatReqPerUe *datReq,
598 RgDlSf            *dlSf,
599 RgErrInfo      *err
600 )
601 {
602 //   uint32_t            len;
603    uint8_t        i;
604    uint8_t        j;
605    RgBldPduInfo   bldPdu;
606    uint8_t        tbIndex;
607 #ifdef L2_OPTMZ
608    RgTfuDatReqTbInfo     *tb;
609 #endif
610
611
612    tbIndex = (uint8_t)(datReq->transId & 0x03);
613    /* Accept all the data requests even if delayed in case nothing
614     * has been sent earlier on the harq proc.
615     */
616    if((datReq->nmbOfTbs > RG_MAX_TB_PER_UE) ||
617          (tbIndex == 0))
618    {
619       /* release corresponding TBs from SF tbs List */
620       for(j=0;j<datReq->nmbOfTbs;j++)
621       {
622          if (!(tbIndex & (j+1)))
623          {
624             j++;
625          } 
626          rgDHMRlsHqProcTB(rgCb[inst].cell, hqProc, (uint8_t)(j+1));
627       }
628       return RFAILED;
629    }
630
631    for(i=0;i<datReq->nmbOfTbs;i++)
632    {
633       /* tbIndex 01 corresponds to presence of 1st TB
634        * 10 corresponds 2nd TB
635        * 11 corresponds two TBs of UE */
636       if (!(tbIndex & (i+1)))
637       {
638           continue;
639       }
640       if (hqProc->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sfLnk.node == NULLP)
641       {
642          /* release corresponding TBs from SF tbs List */
643          for(j=0;j<datReq->nmbOfTbs;j++)
644          {
645             if (!(tbIndex & (j+1)))
646             {
647                j++;
648             }
649             rgDHMRlsHqProcTB(rgCb[inst].cell, hqProc, (uint8_t)(j+1));
650             printf("\nrgDHMHndlDedDatReq:: hqP %p \n", (Void *)hqProc);
651          }
652          return RFAILED;
653
654       }
655 #ifndef L2_OPTMZ
656       RG_FREE_MSG(hqProc->tbInfo[i].tb);
657       /* L2 optimization for mUe/Tti: Pre-allocated mBuf pointers(macHdr, 
658        * macCes and MacPad) of harq TB need to be reset to db_base
659        */
660 #else
661       tb = &hqProc->tbInfo[i].tb;
662       if (tb->tbPres == TRUE)
663       {
664          RG_FREE_TB(tb);
665       }
666 #endif
667       bldPdu.datReq    =  datReq;
668       bldPdu.reqType   =  EVTRGUDDATREQ;
669       bldPdu.schdTbSz  =  hqProc->tbInfo[i].tbSz;
670       bldPdu.tbIndex   =  i+1;
671       bldPdu.ta        =  hqProc->tbInfo[i].schdTa;
672 #ifdef LTE_ADV
673       bldPdu.sCellActCe= hqProc->tbInfo[i].sCellActCe;
674 #endif
675       bldPdu.contResId =  NULLP;
676 #ifdef LTE_L2_MEAS
677       /* Store tbId from RLC in DDatRequest */
678       hqProc->tbId[i] = datReq->datReqTb[i].tbId;
679
680
681       hqProc->status[i] =  FALSE;
682 #endif 
683       if(rgMUXBldPdu(inst,&bldPdu, &(hqProc->tbInfo[i].tb), err) != ROK)
684       {
685          RLOG1(L_ERROR, "MUXing failed for:  MacInst %d", inst);
686          RLOG4(L_ERROR, "MUXing failed for:  time: %d/%d\
687                procId %d ueId %d", hqProc->tbInfo[i].timingInfo.sfn,
688                hqProc->tbInfo[i].timingInfo.slot, hqProc->procId, 
689                hqProc->tbInfo[i].pdcch.rnti);
690
691          /* release corresponding TBs from SF tbs List */
692          for(j=0;j<datReq->nmbOfTbs;j++)
693          {
694             if (!(tbIndex & (j+1)))
695             {
696                j++;
697             }
698             rgDHMRlsHqProcTB(rgCb[inst].cell, hqProc, (uint8_t)(j+1));
699          }
700          return RFAILED;
701       }
702       /*
703       SFndLenMsg(hqProc->tbInfo[i].tb, &len);
704       */
705    }
706    return ROK;
707 }  /* rgDHMHndlDedDatReq */
708
709 /**
710  * @brief Function to handle RGU datReq received from ROM
711  *
712  * @details
713  *
714  *     Function : rgDHMHndlCmnDatReq
715  *     
716  *     This function shall act on the datReq received on RGU. It shall 
717  *     store the data IDs for all the logical channels and get the MAC 
718  *     PDU built.
719  *     
720  *           
721  *  @param[in]  Inst        inst
722  *  @param[in]  RgDlHqProcCb   *hqProc 
723  *  @param[in]  RgRguCmnDatReq *datReq
724  *  @param[out] RgErrInfo      *err
725  *  @return     S16
726  *      -# ROK 
727  *      -# RFAILED 
728  **/
729 S16 rgDHMHndlCmnDatReq
730 (
731 Inst           inst,
732 RgDlHqProcCb   *hqProc,
733 RgRguCmnDatReq *datReq,
734 RgErrInfo      *err
735 )
736 {
737    RgUstaDgn      dgn;
738    RgBldPduInfo   bldPdu;
739
740 #ifndef L2_OPTMZ
741       if (hqProc->tbInfo[0].tb != NULLP)
742 #else
743       /* If numLch is non zero means HQ Proc is busy*/
744       if (hqProc->tbInfo[0].tb.tbPres)
745 #endif
746       {
747          /* datReq discarded. Generate an alarm */
748          rgFillDgnParams(inst,&dgn, LRG_USTA_DGNVAL_HARQ); 
749          rgLMMStaInd(inst,LCM_CATEGORY_PROTOCOL, LCM_EVENT_UI_INV_EVT,
750                LRG_CAUSE_HQ_PROC_BUSY, &dgn);
751          return RFAILED;
752       }
753
754    bldPdu.datReq    =  datReq;
755    bldPdu.reqType   =  EVTRGUCDATREQ;
756    bldPdu.schdTbSz  =  hqProc->tbInfo[0].tbSz;
757    bldPdu.ta        =  hqProc->tbInfo[0].schdTa;
758 #ifdef LTE_ADV
759    bldPdu.sCellActCe= hqProc->tbInfo[0].sCellActCe;
760 #endif
761
762    bldPdu.contResId  =  hqProc->tbInfo[0].contResId;
763
764    if(rgMUXBldPdu(inst,&bldPdu, &(hqProc->tbInfo[0].tb), err) != ROK)
765    {
766       RLOG1(L_ERROR, "MUXing failed for:  MacInst %d", inst); 
767       RLOG4(L_ERROR, "MUXing failed for: time: %d/%d\
768                procId %d ueId %d", hqProc->tbInfo[0].timingInfo.sfn,
769             hqProc->tbInfo[0].timingInfo.slot, hqProc->procId, 
770             hqProc->tbInfo[0].pdcch.rnti);
771
772       RG_FREE_MSG(datReq->pdu);
773       return RFAILED;
774    }
775
776    return ROK;
777 }  /* rgDHMHndlCmnDatReq */
778
779 /**
780  * @brief Function to get consolidate grants and send consolidated grant to RLC
781  *
782  * @details
783  *
784  *     Function : rgDHMSndConsolidatedStaInd
785  *     
786  *     This function shall be invoked by Scheduler to trigger DHM to send a
787  *     consolidated status indication of all UE scheduled in a TTI as well as
788  *     send consolidated CStaInd for MSG4 and for all common channels(PCCH,
789  *     if RGR_SI_SCH is not defined then it includes BCH and BCCH also)
790  *     
791  *           
792  *  @param[in]  RgCellCb       *cell
793  *  @param[in]  RgInfUeInfo   *ueInfo,
794  *  @param[in]  CmLteTimingInfo timingInfo,
795  *  @param[out] RgErrInfo      err
796  *  @param[in]  RguCStaIndInfo   *cStaInd
797  *  @return     S16
798  *      -# ROK 
799  *      -# RFAILED 
800  **/
801  RgUeCb  *gUe =NULLP;
802 S16 rgDHMSndConsolidatedStaInd
803 (
804 RgCellCb        *cell,
805 RgInfUeInfo     *ueInfo,
806 CmLteTimingInfo timingInfo,
807 RgErrInfo       *err
808 )
809 {
810    SuId            rguDlSpId;/*need to use spID instead of suID*/
811    uint8_t         idx;
812    uint8_t         ueIdx;
813    uint8_t         lcIdx;
814    uint8_t         tbIndex=0,idx1;
815    RgDlSf          *dlSf = &cell->subFrms[(timingInfo.slot % RG_NUM_SUB_FRAMES)];
816    Inst            inst = cell->macInst - RG_INST_START;
817 //   Bool            isDStaReqrd = FALSE;
818    RgRguDedStaInd  *dStaInd[rgCb[inst].numRguSaps] ;
819    RgUpSapCb      *rguDlSap[rgCb[inst].numRguSaps];
820
821    int lchBufSize =0;
822    RgUeCb         *ue;
823    RgDlHqProcCb   *hqP;
824    RgInfUeAlloc   *allocInfo;
825    uint8_t        activeSapCnt = 0;
826    uint8_t        staIndCnt    = 0;
827 #ifdef LTE_ADV
828    Bool           hqPAdded     = FALSE;
829 #endif
830 #ifdef L2_OPTMZ
831    RgTfuDatReqTbInfo     *tb;   /* TB to be sent to CL/PHY*/
832 #endif
833
834    memset (dStaInd, 0, (sizeof(RgRguDedStaInd *) * rgCb[inst].numRguSaps));
835    memset (rguDlSap, 0, (sizeof(RgUpSapCb  *) * rgCb[inst].numRguSaps));
836
837    /* Send StaInd for the scheduled UEs */
838    for(ueIdx = 0; ueIdx < ueInfo->numUes; ueIdx++)
839    {
840 #ifdef LTE_ADV
841       hqPAdded = FALSE;
842 #endif
843       if((ue=rgDBMGetUeCb (cell, ueInfo->allocInfo[ueIdx].rnti)) == NULLP)
844       {
845          /* Check in RachLst */
846          if((ue=rgDBMGetUeCbFromRachLst (cell, 
847                      ueInfo->allocInfo[ueIdx].rnti)) == NULLP)
848          {
849             RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"CRNTI:%d No ueCb found", 
850                       ueInfo->allocInfo[ueIdx].rnti);
851             /*Fix: If one UE is not present dont return, look for the next.*/
852             continue;
853          }
854       }
855
856
857       rgDHMGetHqProcFrmId(ue,ueInfo->allocInfo[ueIdx].hqProcId,&hqP);
858       allocInfo = &ueInfo->allocInfo[ueIdx];
859       gUe = ue;
860
861       /* Fix : syed Avoid sending data for a RETX
862        * if initial TX data processing was unsuccessful */
863       if((allocInfo->tbInfo[0].isReTx == TRUE) &&
864             (hqP->tbInfo[0].tbSz == 0)) 
865       {
866          RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,
867                "CRNTI:%d RETX hqP(%d) tb(0) for a failed New Tx", 
868                   allocInfo->rnti, hqP->procId);        
869          continue;
870       }
871       if((allocInfo->tbInfo[1].isReTx == TRUE) &&
872             (hqP->tbInfo[1].tbSz == 0)) 
873       {
874          RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,
875                    "CRNTI:%d RETX hqP(%d) tb(1) for a failed New Tx", 
876                   allocInfo->rnti, hqP->procId);        
877          continue;
878       }
879
880       if(ue->rguDlSap != NULLP)
881       {
882           rguDlSpId = ue->rguDlSap->sapCfg.spId;
883       }else
884       {/* UeCb is from rachList */
885           rguDlSpId = cell->rguDlSap->sapCfg.spId;
886       }
887
888
889       for(idx=allocInfo->tbStrtIdx;((idx-allocInfo->tbStrtIdx) <\
890                allocInfo->nmbOfTBs); idx++)
891       {
892          RguCStaIndInfo  *cStaInd;
893 #ifdef TFU_UPGRADE
894          /* LTE_ADV_FLAG_REMOVED_START */
895          hqP->tbInfo[idx].isEnbSFR = allocInfo->isEnbSFR;
896          /* update pA value */
897          hqP->tbInfo[idx].pa = allocInfo->pa;
898          /* LTE_ADV_FLAG_REMOVED_END */
899 #endif
900
901          hqP->numOfTBs =  allocInfo->nmbOfTBs;
902          hqP->tbInfo[idx].sfLnkInfo[dlSf->schdTime.slot % 2].sfLnk.node = (PTR)hqP;
903          hqP->tbInfo[idx].sfLnkInfo[dlSf->schdTime.slot % 2].sf = dlSf;
904          cmLListAdd2Tail(&dlSf->tbs,&(hqP->tbInfo[idx].sfLnkInfo[dlSf->schdTime.slot % 2].sfLnk));
905          /* Changes as part of performance testing*/
906          /*   hqP->numOfTBs++;*/
907          hqP->tbInfo[idx].doa = allocInfo->doa;
908          hqP->tbInfo[idx].txMode = allocInfo->txMode;
909          hqP->tbInfo[idx].puschRptUsd = allocInfo->puschRptUsd;
910          hqP->tbInfo[idx].puschPmiInfo = allocInfo->puschPmiInfo;
911 #ifdef LTEMAC_SPS
912          hqP->tbInfo[idx].pdcch.rnti = allocInfo->pdcchRnti;
913 #else
914          hqP->tbInfo[idx].pdcch.rnti = allocInfo->rnti;
915 #endif
916          if(allocInfo->tbInfo[idx].isReTx == TRUE)
917          {
918             hqP->tbInfo[idx].pdcch.dci = allocInfo->dciInfo;
919             continue;
920          }
921
922          hqP->tbInfo[idx].timingInfo = timingInfo;
923          hqP->tbInfo[idx].pdcch.dci = allocInfo->dciInfo;
924 #ifndef L2_OPTMZ
925          RG_FREE_MSG(hqP->tbInfo[idx].tb);
926 #else
927          /* L2 optimization for mUe/Tti: Pre-allocated mBuf pointers(macHdr, 
928           * macCes and MacPad) of harq TB need to be reset to db_base
929           */
930          tb = &(hqP->tbInfo[idx].tb);
931          if (tb->tbPres == TRUE)
932          {
933             RG_FREE_TB(tb);
934          }
935 #endif
936          hqP->tbInfo[idx].tbSz = allocInfo->tbInfo[idx].schdTbSz; 
937
938          hqP->tbInfo[idx].schdTa.pres = allocInfo->tbInfo[idx].ta.pres;
939          hqP->tbInfo[idx].schdTa.val  = allocInfo->tbInfo[idx].ta.val;
940
941 #ifdef LTE_ADV
942          hqP->tbInfo[idx].sCellActCe.pres = allocInfo->tbInfo[idx].sCellActCe.pres;
943          hqP->tbInfo[idx].sCellActCe.val  = allocInfo->tbInfo[idx].sCellActCe.val;
944 #endif
945
946 #ifdef LTE_ADV 
947          if(( hqPAdded == TRUE) || (ROK == rgLaaPushHqPToScellLst(allocInfo,cell,timingInfo)))
948          {
949             hqPAdded = TRUE;
950             continue;
951          }
952 #endif
953          if (allocInfo->tbInfo[idx].schdDat[0].lcId == RG_CCCH_LCID)        
954          {
955 #ifndef L2_OPTMZ
956             RG_FREE_MSG(hqP->tbInfo[idx].tb);
957 #else
958            /* L2 optimization for mUe/Tti: Pre-allocated mBuf pointers(macHdr, 
959             * macCes and MacPad) of harq TB need to be reset to db_base
960             */
961            tb = &(hqP->tbInfo[idx].tb);
962
963            if (tb->tbPres == TRUE)
964            {
965               RG_FREE_TB(tb);
966            }
967 #endif
968             hqP->tbInfo[0].contResCe  = allocInfo->tbInfo[0].contResCe;
969             if(allocInfo->tbInfo[0].contResCe)
970             {
971                hqP->tbInfo[0].contResId = &ue->contResId;
972             }
973
974
975             if(allocInfo->tbInfo[idx].numSchLch == 0)
976             {
977                RLOG_ARG2(L_DEBUG,DBG_CELLID,cell->cellId,
978                         "UEID:%d MSG4 with only contResId hqP(%d)",
979                                 allocInfo->rnti,
980                         hqP->procId);
981                hqP->tbInfo[idx].numSchLch = 0;
982                continue;
983             }
984
985             /* Increamenting the tbIndex instead of
986                assigning it to constant */
987             tbIndex++;
988
989
990             hqP->tbInfo[idx].numSchLch = 1;
991             hqP->tbInfo[idx].schdData[0].lcId = 
992                allocInfo->tbInfo[idx].schdDat[0].lcId;
993             hqP->tbInfo[idx].schdData[0].schdSz = 
994                allocInfo->tbInfo[idx].schdDat[0].numBytes;
995
996            // if(cStaInd == NULLP)
997             {
998                if ((rgAllocShrablSBuf(inst,(Data**)&cStaInd, sizeof(RguCStaIndInfo))) != ROK)
999                {
1000                   err->errType  = RGERR_DHM_SND_STA_IND;
1001                   err->errCause = RG_DHM_MEM_ALLOC_FAIL;
1002                   return RFAILED; 
1003                }
1004             }
1005
1006             idx1 = (hqP->procId << 2) | tbIndex;
1007             
1008             cStaInd->cellId    = cell->cellId;
1009             cStaInd->rnti      = allocInfo->rnti;
1010             cStaInd->lcId      = cell->dlCcchId;
1011             cStaInd->transId   = (timingInfo.sfn << 16) | 
1012                                  (timingInfo.slot << 8) | idx1;
1013                /* ADD Changes for Downlink UE Timing Optimization */
1014 #ifdef LTEMAC_DLUE_TMGOPTMZ
1015             dlSf->remDatReqCnt++;
1016 #endif
1017             RLOG_ARG3(L_DEBUG,DBG_CELLID,cell->cellId,
1018                                "RNTI:%d UE:MSG4 grant for CCCH hqP(%d) LCID:%d",
1019                      allocInfo->rnti, 
1020                      hqP->procId,
1021                                cStaInd->lcId);       
1022             /* Fix : syed Avoid return param for interface prim and
1023              * proceed for other UEs. For the failed UE, MAC shall
1024              * do padding. */
1025             rgUIMSndCmnStaInd(cell->macInst,cell->rguDlSap,cStaInd);
1026             break;
1027          }
1028          else
1029          {
1030             tbIndex+=idx+1;
1031 #ifndef L2_OPTMZ
1032             RG_FREE_MSG(hqP->tbInfo[idx].tb);
1033 #else
1034             /* L2 optimization for mUe/Tti: Pre-allocated mBuf pointers(macHdr, 
1035              * macCes and MacPad) of harq TB need to be reset to db_base
1036              */
1037             tb = &(hqP->tbInfo[idx].tb);
1038             if (tb->tbPres == TRUE)
1039             {  
1040                RG_FREE_TB(tb);
1041             }
1042 #endif
1043
1044             if((NULLP == dStaInd[rguDlSpId]) && (allocInfo->tbInfo[idx].numSchLch))
1045             {
1046                if ((rgAllocShrablSBuf (inst,(Data**)&dStaInd[rguDlSpId], sizeof(RguDStaIndInfo))) != ROK)
1047                {
1048                   err->errType  = RGERR_DHM_SND_STA_IND;
1049                   err->errCause = RG_DHM_MEM_ALLOC_FAIL;
1050                   /* Need to return as memory allocation will fail for other UEs also*/
1051                   return RFAILED;
1052                }
1053                dStaInd[rguDlSpId]->nmbOfUeGrantPerTti = 0;
1054                rguDlSap[rguDlSpId] = ue->rguDlSap;
1055                activeSapCnt++;
1056             }
1057
1058             for (lcIdx = 0; 
1059                   lcIdx < allocInfo->tbInfo[idx].numSchLch; lcIdx++)
1060             {
1061                hqP->tbInfo[idx].schdData[lcIdx].lcId = 
1062                   allocInfo->tbInfo[idx].schdDat[lcIdx].lcId;
1063                if (hqP->tbInfo[idx].schdData[lcIdx].lcId == 0)
1064                {
1065                   RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, 
1066                         "CCCH grant in DStaInd for LCID:%d CRNTI:%d",
1067                         hqP->tbInfo[idx].schdData[lcIdx].lcId,allocInfo->rnti);
1068                }
1069                hqP->tbInfo[idx].schdData[lcIdx].schdSz = 
1070                   allocInfo->tbInfo[idx].schdDat[lcIdx].numBytes;
1071                if(dStaInd[rguDlSpId])
1072                {
1073                   dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].staIndTb[idx].\
1074                   lchStaInd[lcIdx].lcId = allocInfo->tbInfo[idx].\
1075                   schdDat[lcIdx].lcId;
1076                   dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].staIndTb[idx].\
1077                   lchStaInd[lcIdx].totBufSize = allocInfo->tbInfo[idx].\
1078                   schdDat[lcIdx].numBytes;
1079                }
1080
1081                lchBufSize+=allocInfo->tbInfo[idx].schdDat[lcIdx].numBytes;
1082             }
1083             hqP->tbInfo[idx].numSchLch = 
1084                allocInfo->tbInfo[idx].numSchLch;
1085             if(dStaInd[rguDlSpId])
1086             {
1087                dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].staIndTb[idx].nmbLch =
1088                   allocInfo->tbInfo[idx].numSchLch;
1089 #ifdef LTE_L2_MEAS
1090                dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].staIndTb[idx].tbId =
1091                   hqP->tbId[idx]; 
1092 #endif
1093             }
1094             lchBufSize=0;
1095          }
1096       }
1097       //if((dStaInd) && (tbIndex) && (isDStaReqrd == TRUE))
1098       if((dStaInd[rguDlSpId]) && (tbIndex))
1099       {
1100          idx1 = (hqP->procId << 2) | tbIndex;
1101          /* Create RguDStaInd struct and send to UIM */
1102          dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].rnti    = allocInfo->rnti;
1103          /*
1104             dStaInd->transId = (hqP->timingInfo.sfn << 16) | 
1105             (hqP->timingInfo.slot << 8) | hqP->procId;
1106           */
1107          dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].transId = (timingInfo.sfn << 16) | 
1108             (timingInfo.slot << 8) | idx1;
1109          dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].nmbOfTbs = hqP->numOfTBs;
1110 #ifdef LTE_ADV
1111          dStaInd[rguDlSpId]->staInd[dStaInd[rguDlSpId]->nmbOfUeGrantPerTti].fillCtrlPdu = allocInfo->fillCtrlPdu;
1112 #endif        
1113          /*increment num of UE as staInd is prepared for it */
1114          dStaInd[rguDlSpId]->nmbOfUeGrantPerTti++;
1115          /* ADD Changes for Downlink UE Timing Optimization */
1116 #ifdef LTEMAC_DLUE_TMGOPTMZ
1117          dlSf->remDatReqCnt++;
1118 #endif
1119       }
1120       //isDStaReqrd = FALSE;
1121       tbIndex = 0;
1122    }
1123
1124    for(idx = 0; idx < rgCb[inst].numRguSaps ; idx++)
1125    {
1126       if(dStaInd[idx] != NULLP)
1127       {
1128          dStaInd[idx]->cellId  = cell->cellId;
1129          /* Fix : syed Avoid return param for interface prim and
1130           * proceed for other UEs. For the failed UE, MAC shall
1131           * do padding. */
1132          rgUIMSndDedStaInd(inst,rguDlSap[idx],dStaInd[idx]);
1133    
1134          staIndCnt++;
1135          if(staIndCnt == activeSapCnt)
1136             break;/* all valid staind are considered */
1137       }
1138
1139    }
1140    return ROK;
1141 }  /* rgDHMSndConsolidatedStaInd */
1142
1143
1144 /**
1145  * @brief Function to handle building the TFU Data Request
1146  *
1147  * @details
1148  *
1149  *     Function : rgDHMBldTfuDatReq
1150  *     
1151  *     This function builds the TFU Data Request with the details 
1152  *     present in HARQ Process.
1153  *           
1154  *  @param[in]  RgDlHqProcCb     *hqP 
1155  *  @param[out] TfuDatReqPduInfo  *datReq 
1156  *  @return     Void
1157  *              None 
1158  **/
1159 //uint8_t crashFlag = 0;
1160 static Void rgDHMBldTfuDatReq
1161 (
1162 RgCellCb           *cellCb,
1163 RgDlSf             *dlSf,
1164 RgDlHqProcCb       *hqP,
1165 RgTfuDatReqPduInfo *datReq
1166 )
1167 {
1168
1169 #ifndef L2_OPTMZ
1170 #if !(!(defined TENB_ACC) && !(defined LTE_PAL_ENB))
1171    Inst inst;
1172 #elif defined(TENB_T2K3K_SPECIFIC_CHANGES) && defined(LTE_TDD)
1173    Inst inst;
1174 #endif
1175 #endif
1176
1177    uint8_t i;
1178
1179 #ifdef L2_OPTMZ
1180    uint32_t lchIdx, pduIdx;
1181 #endif
1182  
1183    datReq->nmbOfTBs = 0;
1184 #ifndef L2_OPTMZ
1185 #if !(!(defined TENB_ACC) && !(defined LTE_PAL_ENB))
1186    inst = cellCb->macInst - RG_INST_START;
1187 #elif defined(TENB_T2K3K_SPECIFIC_CHANGES) && defined(LTE_TDD)
1188    inst = cellCb->macInst - RG_INST_START;
1189 #endif
1190 #endif
1191    /*MS_WORKAROUND  for ccpu00123904*/
1192    datReq->isTApres = FALSE;
1193 #ifdef TFU_ALLOC_EVENT_NO_INIT
1194 #ifndef L2_OPTMZ   
1195    datReq->mBuf[0] = 0;
1196    datReq->mBuf[1] = 0;
1197 #endif    
1198 #endif
1199  
1200    for(i=0;i<RG_MAX_TB_PER_UE;i++)
1201    {
1202 #ifndef L2_OPTMZ
1203       if ((hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sf == dlSf) &&
1204           (hqP->tbInfo[i].tb != NULLP))
1205 #else
1206       if ((hqP->tbInfo[i].sfLnkInfo[dlSf->schdTime.slot % 2].sf == dlSf) &&
1207            RgUtlIsTbMuxed(&(hqP->tbInfo[i].tb)))
1208 #endif
1209       {
1210
1211          datReq->rnti           =  hqP->tbInfo[i].pdcch.rnti;
1212          datReq->dciInfo        =  hqP->tbInfo[i].pdcch.dci;
1213          datReq->doa            =  hqP->tbInfo[i].doa;
1214          datReq->transMode      =  hqP->tbInfo[i].txMode;
1215          datReq->puschRptUsd    =  hqP->tbInfo[i].puschRptUsd;
1216          datReq->puschPmiInfo   =  hqP->tbInfo[i].puschPmiInfo;
1217          /*MS_WORKAROUND  for ccpu00123904*/
1218          if (hqP->tbInfo[i].schdTa.pres)
1219          {
1220             datReq->isTApres       =  TRUE; 
1221          }
1222 #ifdef   TFU_UPGRADE
1223          /* update pA value */
1224          datReq->pa             =  hqP->tbInfo[i].pa;
1225 #endif
1226          /* LTE_ADV_FLAG_REMOVED_START */
1227          datReq->isEnbSFR       =  hqP->tbInfo[i].isEnbSFR;
1228          /* LTE_ADV_FLAG_REMOVED_END */
1229 #ifndef L2_OPTMZ
1230 #if (!(defined TENB_ACC) && !(defined LTE_PAL_ENB))  /* ABHI */ /* This is only temp fix. It needs to be removed
1231                                 after rebasing to MAC CCB */
1232 #ifdef BRDCM
1233          datReq->mBuf[i] = hqP->tbInfo[i].tb;
1234 #else
1235          /* Intel Tdd- Commenting out the Optimization for direct Access of 
1236           * mBuf Index */
1237          /*Proper clean-up needed as this needs long stability tests
1238           * in all SoCs*/
1239 #if defined(TENB_T2K3K_SPECIFIC_CHANGES) && defined(LTE_TDD)
1240          SIncMsgRef(hqP->tbInfo[i].tb, RG_GET_MEM_REGION(rgCb[inst]),
1241                RG_GET_MEM_POOL(rgCb[inst]), &datReq->mBuf[i]); 
1242 #else
1243          datReq->mBuf[i] = hqP->tbInfo[i].tb;
1244 #endif
1245 #endif/*BRDCM*/
1246 #else
1247          SIncMsgRef(hqP->tbInfo[i].tb, RG_GET_MEM_REGION(rgCb[inst]),
1248                RG_GET_MEM_POOL(rgCb[inst]), &datReq->mBuf[i]);
1249 #endif
1250          {
1251             MsgLen   dbgBufLen;
1252             if(SFndLenMsg(datReq->mBuf[i], &dbgBufLen))
1253             {
1254                if(dbgBufLen == 0)
1255                {              
1256                   RLOG_ARG4(L_ERROR,DBG_CELLID,cellCb->cellId,
1257                                           "RNTI:%d SFN:%d slot:%d tbIdx:%d Sdu Length 0 ",
1258                               datReq->rnti,
1259                                       hqP->tbInfo[i].timingInfo.sfn,
1260                                           hqP->tbInfo[i].timingInfo.slot,i);
1261                   RLOG_ARG3(L_ERROR,DBG_CELLID,cellCb->cellId,
1262                               "taPres [%d] numOfTbs [%d] format[%d]",
1263                               datReq->isTApres, 
1264                            hqP->numOfTBs, 
1265                            datReq->dciInfo.format);  
1266                }              
1267             }  
1268          }
1269 #else
1270          /* L2 optimization for mUe/Tti: Removing SIncMsgRef to avoid additional
1271           * mBuf allocation. MAC header, MAC Ces, MAC PDU per LCH per TB Per UE
1272           * and MAC padding Mbufs are being sent to CL. Populating these Ptrs
1273           * From TB Info to TfuDatReq
1274           */
1275          datReq->tbInfo[i].tbPres =  TRUE;
1276          datReq->tbInfo[i].tbSize =  hqP->tbInfo[i].tbSz;
1277          datReq->tbInfo[i].macHdr =  hqP->tbInfo[i].tb.macHdr;
1278          datReq->tbInfo[i].macCes =  hqP->tbInfo[i].tb.macCes;
1279          datReq->tbInfo[i].numLch =  hqP->tbInfo[i].tb.numLch;
1280          for(lchIdx = 0; lchIdx < hqP->tbInfo[i].tb.numLch; lchIdx++)
1281          {
1282             datReq->tbInfo[i].lchInfo[lchIdx].numPdu = hqP->tbInfo[i].tb.\
1283                                                        lchInfo[lchIdx].numPdu;
1284             for(pduIdx = 0; pduIdx < hqP->tbInfo[i].tb.lchInfo[lchIdx].numPdu;\
1285                   pduIdx++)
1286             {
1287                datReq->tbInfo[i].lchInfo[lchIdx].mBuf[pduIdx] =
1288                   hqP->tbInfo[i].tb.lchInfo[lchIdx].mBuf[pduIdx];
1289             }
1290          }
1291         // datReq->tbInfo[i].macPad  =  hqP->tbInfo[i].tb.macPad;
1292          datReq->tbInfo[i].padSize =  hqP->tbInfo[i].tb.padSize;
1293         // prc_trace_format_string(0x40,3,"TfuDatReq:RNTI=%d TbIdx=%d TbSize=%d PdSz=(%d) macHdraddr: (%p) macCEAddr: (%p) noLch=(%d)",datReq->rnti, i,
1294           //     hqP->tbInfo[i].tbSz, datReq->tbInfo[i].padSize, datReq->tbInfo[i].macHdr, datReq->tbInfo[i].macCes, datReq->tbInfo[i].numLch);
1295
1296 #endif
1297          datReq->nmbOfTBs++;
1298       }
1299    }
1300    return;
1301 }  /* rgDHMBldTfuDatReq */
1302
1303
1304 #ifdef L2_OPTMZ
1305 /**
1306  * @brief This function releases a HARQ process
1307  *
1308  * @details
1309  *
1310  *     Function: rgDHMFreeHqProcTB
1311  *     Purpose:  This function returns a HARQ process to HARQ Entity 
1312  *               in the DL direction.
1313  *     
1314  *               1. Add the HARQ process to the free queue.
1315  *     Invoked by: scheduler and HARQ processing
1316  *     
1317  *  @param[in]  RgDlHqProc    *hqP
1318  *  @return  Void      
1319  *
1320  **/
1321 S16 rgDHMFreeHqProcTB(RgDlHqProcCb *hqP, uint8_t tbIndex)
1322 {
1323    RgTfuDatReqTbInfo     *tb;   /* TB to be sent to CL/PHY*/
1324    uint8_t               idx;
1325
1326    if((tbIndex > RG_MAX_TB_PER_UE) ||
1327       (tbIndex == 0))
1328    {
1329       return RFAILED;
1330    }
1331
1332    tb = &(hqP->tbInfo[tbIndex-1].tb);
1333    RG_FREE_MSG(tb->macHdr);
1334    RG_FREE_MSG(tb->macCes);
1335
1336    for(idx = 0; idx < 2; idx++)
1337    {
1338       if (hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sfLnk.node != NULLP)
1339    {
1340          cmLListDelFrm(&hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sf->tbs,
1341                &(hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sfLnk));
1342          hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sfLnk.node  = (PTR)NULLP;
1343       printf("\nrgDHMFreeHqProcTB:: hqP %p \n", (Void *)hqP);
1344    }
1345       hqP->tbInfo[tbIndex-1].sfLnkInfo[idx].sf = NULLP;
1346    }
1347    return ROK;
1348 }
1349 #endif
1350
1351
1352
1353 /**
1354  * @brief Handler for freeing up the harq related information from ueCb
1355  *
1356  * @details
1357  *
1358  *     Function : rgDHMFreeUe
1359  *     
1360  *     This function shall free up the HARQ specific information from ueCb.
1361  *           
1362  *  @param[in]  Inst        inst
1363  *  @param[in]  RgDlHqEnt     *hqE 
1364  *
1365  *  @return     None.
1366  *
1367  **/
1368 Void rgDHMFreeUe(Inst  inst, RgDlHqEnt *hqE)
1369 {
1370    uint8_t             i;
1371
1372    if(hqE->procs)
1373    {
1374       /* Free all the memory associated with HARQ */
1375       for (i=0; i < hqE->numHqProcs; i++)
1376       {
1377 #ifndef L2_OPTMZ
1378          rgDHMRlsHqProcTB(rgCb[inst].cell, hqE->procs[i], 1);
1379          rgDHMRlsHqProcTB(rgCb[inst].cell, hqE->procs[i], 2);
1380 #else
1381          rgDHMFreeHqProcTB(hqE->procs[i], 1);
1382          rgDHMFreeHqProcTB(hqE->procs[i], 2);
1383 #endif
1384          
1385          rgFreeSBuf(inst,(Data **)&(hqE->procs[i]), sizeof(RgDlHqProcCb));
1386 #ifdef LTE_ADV
1387          rgDHMFreeSavedHqP(inst,hqE,i);
1388 #endif
1389       }
1390
1391       /*ccpu00117052 - MOD - Passing double pointer for proper NULLP
1392                             assignment */
1393    }
1394
1395    return;
1396
1397 }  /* rgDHMFreeUe */
1398 /**
1399  * @brief Function for handling RaResp request received from scheduler to MAC
1400  *
1401  * @details
1402  *
1403  *     Function : RgSchMacRstHqEntReq
1404  *     
1405  *     This function shall be invoked whenever a sec cell of an ue
1406  *     is deactivated. MAC needs to reset the harqentity associated 
1407  *     with the deactivated scell of the ue
1408  *     
1409  *           
1410  *  @param[in] Pst             *pst
1411  *  @param[in] RgInfResetHqEnt *hqEntInfo
1412  *  @return  S16
1413  *      -# ROK 
1414  **/
1415 S16 RgSchMacRstHqEntReq(Pst* pst, RgInfResetHqEnt* hqEntInfo)
1416 {
1417    Inst      inst;
1418    RgCellCb  *cell;
1419    RgUeCb    *ue;
1420
1421    inst = pst->dstInst - RG_INST_START;
1422
1423    if (((cell = rgCb[inst].cell) == NULLP) ||
1424        (rgCb[inst].cell->cellId != hqEntInfo->cellId))
1425    {
1426       RGDBGERRNEW(inst,(rgPBuf(inst), "For user [%d]Cell does not exist %d\n",
1427                 hqEntInfo->crnti,hqEntInfo->cellId));
1428       return RFAILED;
1429    }
1430
1431    if ((ue = rgDBMGetUeCb(cell, hqEntInfo->crnti)) == NULLP)
1432    {
1433       RGDBGERRNEW(inst,(rgPBuf(inst), "[%d]UE does not exist for this hqEntInfo\n",
1434                        hqEntInfo->crnti));
1435       return RFAILED;
1436    }
1437
1438    rgDHMUeReset(cell, &ue->dl.hqEnt);
1439
1440    return ROK;
1441 }
1442 uint32_t gSaveVal;
1443 \f
1444 /**
1445  * @brief Function for handling RaResp request received from scheduler to MAC
1446  *
1447  * @details
1448  *
1449  *     Function : RgSchMacRlsHqReq
1450  *     
1451  *     This function shall be invoked whenever scheduler is done with the
1452  *     allocations of random access responses for a slot.
1453  *     This shall invoke RAM to create ueCbs for all the rapIds allocated and 
1454  *     shall invoke MUX to create RAR PDUs for raRntis allocated.
1455  *     
1456  *           
1457  *  @param[in] CmLteCellId         cellId,
1458  *  @param[in] CmLteTimingInfo     timingInfo,
1459  *  @param[in] RaRespInfo          *rarInfo
1460  *  @return  S16
1461  *      -# ROK 
1462  **/
1463 S16 RgSchMacRlsHqReq(Pst *pst, RgInfRlsHqInfo *rlshqUeInfo)
1464 {
1465    Inst           inst;
1466    RgCellCb       *cell = NULLP;
1467    RgUeCb         *ue;
1468    RgDlHqProcCb   *hqP;
1469    uint8_t        idx1,idx2;
1470 #ifdef LTE_L2_MEAS
1471    uint8_t           tbId;
1472    RguHarqStatusInd  hqStaInd;
1473    Bool              isValidTbId = FALSE;
1474 #endif
1475    uint32_t        startTime=0;
1476    
1477    RG_IS_INST_VALID(pst->dstInst);
1478    inst = pst->dstInst - RG_INST_START;
1479    cell  = rgCb[inst].cell;
1480    /*starting Task*/
1481    SStartTask(&startTime, PID_MAC_AM_HARQ_RLS);
1482
1483    if(NULLP == rlshqUeInfo)
1484    {
1485       return RFAILED;
1486    }
1487
1488    if((cell  == NULLP)
1489       ||( cell->cellId != rlshqUeInfo->cellId))
1490    {
1491        
1492       RLOG_ARG0(L_ERROR,DBG_CELLID,rlshqUeInfo->cellId,
1493                 "No cellCb found with cellId");
1494       return RFAILED;
1495    }
1496
1497    if(NULLP == rlshqUeInfo->ueHqInfo)
1498    {
1499       return RFAILED;
1500    }
1501
1502    for(idx1 = 0; idx1 < rlshqUeInfo->numUes; idx1++)
1503    {
1504       if((ue=rgDBMGetUeCb (cell, rlshqUeInfo->ueHqInfo[idx1].rnti)) == NULLP)
1505       {
1506          /* Check in RachLst */
1507          if((ue=rgDBMGetUeCbFromRachLst (cell, 
1508                      rlshqUeInfo->ueHqInfo[idx1].rnti)) == NULLP)
1509          {
1510             RLOG_ARG1(L_ERROR,DBG_CELLID,rlshqUeInfo->cellId, "CRNTI:%d No ueCb found",
1511                      rlshqUeInfo->ueHqInfo[idx1].rnti);
1512             continue;
1513          }
1514       }
1515 #ifdef LTE_ADV
1516 #ifdef LAA_DBG
1517      if ((rlshqUeInfo->ueHqInfo[idx1].rlsOperationType && !gSaveVal) || (rlshqUeInfo->ueHqInfo[idx1].hqProcId > 8))
1518       {
1519          int *p = NULL;
1520          RLOG_ARG1(L_INFO," SPURIOUS CALLL !!!! procId %d \n", rlshqUeInfo->ueHqInfo[idx1].hqProcId);
1521
1522
1523        printf ("RgSchMacRlsHqReq cell %d : numUes %d idx %d rnti %d hqProc %d numTbs %d tbid[0] %d tbid[1] %d rlsopr %d \n",
1524       cell->cellId,
1525        rlshqUeInfo->numUes,
1526        idx1,
1527        rlshqUeInfo->ueHqInfo[idx1].rnti,
1528        rlshqUeInfo->ueHqInfo[idx1].hqProcId,
1529        rlshqUeInfo->ueHqInfo[idx1].numOfTBs,
1530        rlshqUeInfo->ueHqInfo[idx1].tbId[0],
1531        rlshqUeInfo->ueHqInfo[idx1].tbId[1],
1532        rlshqUeInfo->ueHqInfo[idx1].rlsOperationType);
1533       
1534          *p = 10; 
1535       }
1536 #endif
1537       gSaveVal = 0;
1538
1539
1540       RgSchMacHndlRelReq(cell, ue, &rlshqUeInfo->ueHqInfo[idx1]);
1541
1542       if (RGINF_RLS_HQ_DEL_TB == rlshqUeInfo->ueHqInfo[idx1].rlsOperationType)
1543       {
1544          /* If REQ is to DEL the saved TBs no need to free the HqP as it's already
1545             freed up earlier */
1546          continue;
1547       }
1548 #endif /* LTE_ADV */
1549       rgDHMGetHqProcFrmId(ue,rlshqUeInfo->ueHqInfo[idx1].hqProcId,&hqP);
1550       if(rlshqUeInfo->ueHqInfo[idx1].status[0] != TRUE)
1551       {
1552          rgCb[inst].genSts.numHarqFail++;
1553       }
1554      
1555 #ifdef LTE_L2_MEAS
1556       hqStaInd.cellId = cell->cellId;
1557       hqStaInd.ueId = rlshqUeInfo->ueHqInfo[idx1].rnti;
1558       hqStaInd.numTbs = rlshqUeInfo->ueHqInfo[idx1].numOfTBs;
1559 #endif
1560
1561       for(idx2=0; idx2 < rlshqUeInfo->ueHqInfo[idx1].numOfTBs; idx2++)
1562       {
1563 #ifdef LTE_L2_MEAS
1564          /* Fill the hq sta Ind stucture. Need to send the Status Ind for only
1565           those TBID's reported by Scheduler*/
1566             tbId = rlshqUeInfo->ueHqInfo[idx1].tbId[idx2];
1567             if (hqP->tbId[tbId-1] != RGU_INVALID_TBID)
1568             {
1569             /* Fill the correct Sn Map corresponding to the TBID */
1570             hqStaInd.tbId[idx2] = hqP->tbId[tbId-1];
1571             hqStaInd.status[idx2] = rlshqUeInfo->ueHqInfo[idx1].status[idx2];
1572                isValidTbId = TRUE;
1573             }
1574 #endif
1575          if(rgDHMRlsHqProcTB(cell, hqP, 
1576                rlshqUeInfo->ueHqInfo[idx1].tbId[idx2]) != ROK)
1577          {
1578             RLOG_ARG1(L_ERROR,DBG_CELLID,rlshqUeInfo->cellId,
1579                   "CRNTI:%d Failure in releasing hq TB",
1580                   rlshqUeInfo->ueHqInfo[idx1].rnti);
1581             continue;
1582          }
1583       }
1584
1585 #ifdef LTE_L2_MEAS
1586
1587          if (isValidTbId)
1588          {
1589             if(ue->rguDlSap)
1590             {
1591                RgUiRguHqStaInd(&(ue->rguDlSap->sapCfg.sapPst),
1592                      ue->rguDlSap->sapCfg.suId,
1593                      &hqStaInd);
1594             }
1595             else
1596             {/* Ue is from rach list*/
1597                RgUiRguHqStaInd(&(cell->rguDlSap->sapCfg.sapPst),
1598                      cell->rguDlSap->sapCfg.suId,
1599                      &hqStaInd);
1600             }
1601          }
1602 #endif
1603    } /* end of ues loop */
1604
1605    /*starting Task*/
1606    SStopTask(startTime,PID_MAC_AM_HARQ_RLS);
1607
1608    return ROK;
1609 } /* end of RgSchMacRlsHqReq */
1610
1611
1612 /**********************************************************************
1613  
1614          End of file
1615 **********************************************************************/