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