pre_processor.c 46.9 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2
3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


nikaeinn's avatar
nikaeinn committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16
17
18
19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20
21

  Contact Information
nikaeinn's avatar
nikaeinn committed
22
23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

nikaeinn's avatar
nikaeinn committed
28
*******************************************************************************/
29
/*! \file pre_processor.c
30
 * \brief eNB scheduler preprocessing fuction prior to scheduling
31
 * \author Navid Nikaein and Ankit Bhamri
nikaeinn's avatar
nikaeinn committed
32
 * \date 2013 - 2014
33
 * \email navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
34
 * \version 1.0
35
36
37
38
 * @ingroup _mac

 */

39
#include "assertions.h"
40
41
42
43
44
45
46
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
47
#include "LAYER2/MAC/proto.h"
48
49
50
51
52
53
54
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
55
#include "rlc.h"
56
57


gauthier's avatar
gauthier committed
58

59
60
61
62
63
64
65
66
67
68
#define DEBUG_eNB_SCHEDULER 1
#define DEBUG_HEADER_PARSING 1
//#define DEBUG_PACKET_TRACE 1

//#define ICIC 0

/*
  #ifndef USER_MODE
  #define msg debug_msg
  #endif
knopp's avatar
   
knopp committed
69
*/
70
71


72
// This function stores the downlink buffer for all the logical channels
gauthier's avatar
gauthier committed
73
74
void store_dlsch_buffer (module_id_t Mod_id,
                         frame_t     frameP,
75
76
                         sub_frame_t subframeP)
{
Cedric Roux's avatar
Cedric Roux committed
77

knopp's avatar
   
knopp committed
78
  int                   UE_id,i;
gauthier's avatar
gauthier committed
79
  rnti_t                rnti;
80
  mac_rlc_status_resp_t rlc_status;
knopp's avatar
   
knopp committed
81
82
83
  UE_list_t             *UE_list = &eNB_mac_inst[Mod_id].UE_list;
  UE_TEMPLATE           *UE_template;

84
  for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
knopp's avatar
   
knopp committed
85
86

    UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id];
87
88

    // clear logical channel interface variables
knopp's avatar
   
knopp committed
89
90
    UE_template->dl_buffer_total = 0;
    UE_template->dl_pdus_total = 0;
91
92

    for(i=0; i< MAX_NUM_LCID; i++) {
knopp's avatar
   
knopp committed
93
94
95
96
97
      UE_template->dl_buffer_info[i]=0;
      UE_template->dl_pdus_in_buffer[i]=0;
      UE_template->dl_buffer_head_sdu_creation_time[i]=0;
      UE_template->dl_buffer_head_sdu_remaining_size_to_send[i]=0;
    }
98

knopp's avatar
   
knopp committed
99
    rnti = UE_RNTI(Mod_id,UE_id);
100
101
102

    for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels

103
      rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
knopp's avatar
   
knopp committed
104
105
106
      UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
      UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
      UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
107
108
      UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max,
          rlc_status.head_sdu_creation_time );
knopp's avatar
   
knopp committed
109
110
      UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send;
      UE_template->dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented;
111
112
      UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];//storing the total dlsch buffer
      UE_template->dl_pdus_total   += UE_template->dl_pdus_in_buffer[i];
113

Cedric Roux's avatar
Cedric Roux committed
114
#ifdef DEBUG_eNB_SCHEDULER
115

knopp's avatar
   
knopp committed
116
117
118
119
      /* note for dl_buffer_head_sdu_remaining_size_to_send[i] :
       * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
       */
      if (UE_template->dl_buffer_info[i]>0)
120
121
        LOG_D(MAC,
              "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
122
123
124
125
126
127
128
              Mod_id, frameP, subframeP, UE_id,
              i, UE_template->dl_pdus_in_buffer[i],UE_template->dl_buffer_info[i],
              UE_template->dl_buffer_head_sdu_creation_time[i],
              UE_template->dl_buffer_head_sdu_remaining_size_to_send[i],
              UE_template->dl_buffer_head_sdu_is_segmented[i]
             );

Cedric Roux's avatar
Cedric Roux committed
129
#endif
130

knopp's avatar
   
knopp committed
131
    }
132

133
    //#ifdef DEBUG_eNB_SCHEDULER
knopp's avatar
   
knopp committed
134
135
    if ( UE_template->dl_buffer_total>0)
      LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n",
136
137
138
139
140
141
            Mod_id, frameP, subframeP, UE_id,
            UE_template->dl_buffer_total,
            UE_template->dl_pdus_total
           );

    //#endif
142
143
144
  }
}

145

146
// This function returns the estimated number of RBs required by each UE for downlink scheduling
knopp's avatar
   
knopp committed
147
void assign_rbs_required (module_id_t Mod_id,
148
149
150
151
152
                          frame_t     frameP,
                          sub_frame_t subframe,
                          uint16_t    nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
                          int         min_rb_unit[MAX_NUM_CCs])
{
153

gauthier's avatar
gauthier committed
154

knopp's avatar
   
knopp committed
155
156
157
158
159
  rnti_t           rnti;
  uint16_t         TBS = 0;
  LTE_eNB_UE_stats *eNB_UE_stats[MAX_NUM_CCs];
  int              UE_id,n,i,j,CC_id,pCCid,tmp;
  UE_list_t        *UE_list = &eNB_mac_inst[Mod_id].UE_list;
160
  //  UE_TEMPLATE           *UE_template;
161
  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs];
162

knopp's avatar
   
knopp committed
163
  // clear rb allocations across all CC_ids
164
  for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
knopp's avatar
   
knopp committed
165
    pCCid = UE_PCCID(Mod_id,UE_id);
166
    rnti = UE_list->UE_template[pCCid][UE_id].rnti;
167

knopp's avatar
   
knopp committed
168
    //update CQI information across component carriers
169
    for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
gauthier's avatar
gauthier committed
170

knopp's avatar
   
knopp committed
171
      CC_id = UE_list->ordered_CCids[n][UE_id];
172
173
      frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
      eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
174
      /*
175
176
      DevCheck(((eNB_UE_stats[CC_id]->DL_cqi[0] < MIN_CQI_VALUE) || (eNB_UE_stats[CC_id]->DL_cqi[0] > MAX_CQI_VALUE)),
      eNB_UE_stats[CC_id]->DL_cqi[0], MIN_CQI_VALUE, MAX_CQI_VALUE);
177
178
      */
      eNB_UE_stats[CC_id]->dlsch_mcs1=cqi_to_mcs[eNB_UE_stats[CC_id]->DL_cqi[0]];
179

180
      eNB_UE_stats[CC_id]->dlsch_mcs1 = cmin(eNB_UE_stats[CC_id]->dlsch_mcs1,openair_daq_vars.target_ue_dl_mcs);
181

knopp's avatar
   
knopp committed
182
    }
183

knopp's avatar
   
knopp committed
184
    // provide the list of CCs sorted according to MCS
185
186
    for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
      for (j=i+1; j<UE_list->numactiveCCs[UE_id]; j++) {
187
        DevAssert( j < MAX_NUM_CCs );
188
189
190
191
192
193
194

        if (eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]]->dlsch_mcs1 >
            eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]]->dlsch_mcs1) {
          tmp = UE_list->ordered_CCids[i][UE_id];
          UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id];
          UE_list->ordered_CCids[j][UE_id] = tmp;
        }
gauthier's avatar
gauthier committed
195
      }
knopp's avatar
   
knopp committed
196
    }
197

198
    /*
knopp's avatar
   
knopp committed
199
200
201
202
    if ((mac_get_rrc_status(Mod_id,1,UE_id) < RRC_RECONFIGURED)){  // If we still don't have a default radio bearer
      nb_rbs_required[pCCid][UE_id] = PHY_vars_eNB_g[Mod_id][pCCid]->lte_frame_parms.N_RB_DL;
      continue;
    }
203
204
    */
    /* NN --> RK
205
206
     * check the index of UE_template"
     */
207
208
    //    if (UE_list->UE_template[UE_id]->dl_buffer_total> 0) {
    if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) {
209
      LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id);
210
211
212
213
214
215

      for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
        CC_id = UE_list->ordered_CCids[i][UE_id];
        frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
        eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);

216
217
218
219
220
        if (eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
          nb_rbs_required[CC_id][UE_id] = 4;  // don't let the TBS get too small
        } else {
          nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id];
        }
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

        TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);

        LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
              UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
              nb_rbs_required[CC_id][UE_id],eNB_UE_stats[CC_id]->dlsch_mcs1,TBS);

        /* calculating required number of RBs for each UE */
        while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total)  {
          nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id];

          if (nb_rbs_required[CC_id][UE_id] > frame_parms[CC_id]->N_RB_DL) {
            TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,frame_parms[CC_id]->N_RB_DL);
            nb_rbs_required[CC_id][UE_id] = frame_parms[CC_id]->N_RB_DL;
            break;
          }

          TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
        } // end of while

        LOG_D(MAC,"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d,  nb_required RB %d (TBS %d, mcs %d)\n",
              Mod_id, frameP,UE_id, CC_id,  min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats[CC_id]->dlsch_mcs1);
knopp's avatar
   
knopp committed
243
244
245
246
      }
    }
  }
}
gauthier's avatar
gauthier committed
247
248


knopp's avatar
   
knopp committed
249
// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes
gauthier's avatar
gauthier committed
250

251
252
int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag )
{
gauthier's avatar
gauthier committed
253

254
  uint8_t round,round_max=0,UE_id;
knopp's avatar
   
knopp committed
255
  int CC_id;
256
  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
gauthier's avatar
gauthier committed
257

258
259
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {

260
261
    UE_id = find_UE_id(Mod_id,rnti);
    round    = UE_list->UE_sched_ctrl[UE_id].round[CC_id];
262
    if (round > round_max) {
knopp's avatar
   
knopp committed
263
      round_max = round;
264
    }
265
266
  }

267
  return round_max;
knopp's avatar
   
knopp committed
268
}
gauthier's avatar
gauthier committed
269

knopp's avatar
   
knopp committed
270
// This function scans all CC_ids for a particular UE to find the maximum DL CQI
gauthier's avatar
gauthier committed
271

272
273
int maxcqi(module_id_t Mod_id,int32_t UE_id)
{
gauthier's avatar
gauthier committed
274

knopp's avatar
   
knopp committed
275
  LTE_eNB_UE_stats *eNB_UE_stats = NULL;
276
277
  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
  int CC_id,n;
knopp's avatar
   
knopp committed
278
  int CQI = 0;
gauthier's avatar
gauthier committed
279

280
  for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
281
282
    CC_id = UE_list->ordered_CCids[n][UE_id];
    eNB_UE_stats = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,UE_RNTI(Mod_id,UE_id));
283

284
    if (eNB_UE_stats==NULL) {
285
      mac_xface->macphy_exit("maxcqi: could not get eNB_UE_stats\n");
286
287
      return 0; // not reached
    }
288

289
    if (eNB_UE_stats->DL_cqi[0] > CQI) {
knopp's avatar
   
knopp committed
290
      CQI = eNB_UE_stats->DL_cqi[0];
291
    }
292
  }
gauthier's avatar
gauthier committed
293

knopp's avatar
   
knopp committed
294
295
  return(CQI);
}
gauthier's avatar
gauthier committed
296
297
298



knopp's avatar
   
knopp committed
299
// This fuction sorts the UE in order their dlsch buffer and CQI
knopp's avatar
   
knopp committed
300
void sort_UEs (module_id_t Mod_idP,
301
302
303
               int         frameP,
               sub_frame_t subframeP)
{
gauthier's avatar
gauthier committed
304
305


knopp's avatar
   
knopp committed
306
307
308
  int               UE_id1,UE_id2;
  int               pCC_id1,pCC_id2;
  int               cqi1,cqi2,round1,round2;
309
  int               i=0,ii=0;//,j=0;
knopp's avatar
   
knopp committed
310
  rnti_t            rnti1,rnti2;
gauthier's avatar
gauthier committed
311

knopp's avatar
   
knopp committed
312
  UE_list_t *UE_list = &eNB_mac_inst[Mod_idP].UE_list;
gauthier's avatar
gauthier committed
313

314
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
gauthier's avatar
gauthier committed
315

316
    for(ii=UE_list->next[i]; ii>=0; ii=UE_list->next[ii]) {
gauthier's avatar
gauthier committed
317

318
319
      UE_id1  = i;
      rnti1 = UE_RNTI(Mod_idP,UE_id1);
320
321
322
323
324
      if(rnti1 == NOT_A_RNTI)
	continue;
      pCC_id1 = UE_PCCID(Mod_idP,UE_id1);
      cqi1    = maxcqi(Mod_idP,UE_id1); //
      round1  = maxround(Mod_idP,rnti1,frameP,subframeP,0);
325

326
327
      UE_id2 = ii;
      rnti2 = UE_RNTI(Mod_idP,UE_id2);
328
329
      if(rnti2 == NOT_A_RNTI)
        continue;
330
      cqi2    = maxcqi(Mod_idP,UE_id2);
331
      round2  = maxround(Mod_idP,rnti2,frameP,subframeP,0);  //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0);
knopp's avatar
   
knopp committed
332
      pCC_id2 = UE_PCCID(Mod_idP,UE_id2);
333

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
      if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order
        swap_UEs(UE_list,UE_id1,UE_id2,0);
      } else if (round2 == round1) {
        // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels.  This should be done on the sum of all information that has to be sent.  And still it wouldn't ensure fairness.  It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service.
        //  for(j=0;j<MAX_NUM_LCID;j++){
        //    if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] <
        //      eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){

        // first check the buffer status for SRB1 and SRB2

        if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) <
             (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (cqi1 < cqi2) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        }
knopp's avatar
   
knopp committed
356
357
      }
    }
358
359
360
  }
}

gauthier's avatar
gauthier committed
361

knopp's avatar
   
knopp committed
362
363


364
// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
knopp's avatar
   
knopp committed
365
void dlsch_scheduler_pre_processor (module_id_t   Mod_id,
366
367
368
369
370
                                    frame_t       frameP,
                                    sub_frame_t   subframeP,
                                    int           N_RBG[MAX_NUM_CCs],
                                    int           *mbsfn_flag)
{
knopp's avatar
   
knopp committed
371

372
  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,round=0,total_ue_count;
knopp's avatar
   
knopp committed
373
  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
374
  int                     UE_id, i; 
gauthier's avatar
gauthier committed
375
  uint16_t                ii,j;
knopp's avatar
   
knopp committed
376
377
378
  uint16_t                nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
379
  uint16_t                average_rbs_per_user[MAX_NUM_CCs] = {0};
380
  rnti_t             rnti;
knopp's avatar
   
knopp committed
381
  int                min_rb_unit[MAX_NUM_CCs];
382
  uint16_t r1=0;
383
  uint8_t CC_id;
knopp's avatar
   
knopp committed
384
  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
385
  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs] = {0};
386

387
  int transmission_mode = 0;
388
389
390
391
392
393
394
395
396
397
398
399
400
  UE_sched_ctrl *ue_sched_ctl;
  //  int rrc_status           = RRC_IDLE;

#ifdef TM5
  int harq_pid1=0,harq_pid2=0;
  int round1=0,round2=0;
  int UE_id2;
  uint16_t                i1,i2,i3;
  rnti_t             rnti1,rnti2;
  LTE_eNB_UE_stats  *eNB_UE_stats1 = NULL;
  LTE_eNB_UE_stats  *eNB_UE_stats2 = NULL;
  UE_sched_ctrl *ue_sched_ctl1,*ue_sched_ctl2;
#endif
401
402

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
   
knopp committed
403
404
405

    if (mbsfn_flag[CC_id]>0)  // If this CC is allocated for MBSFN skip it here
      continue;
406
407
408

    frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);

knopp's avatar
   
knopp committed
409

410
    min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id);
411
412

    for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
knopp's avatar
   
knopp committed
413
      UE_id = i;
414
      // Initialize scheduling information for all active UEs
415
416
      

417

418
      dlsch_scheduler_pre_processor_reset(Mod_id,
419
420
        UE_id,
        CC_id,
421
422
        frameP,
        subframeP,
423
424
425
426
427
        N_RBG[CC_id],
        nb_rbs_required,
        nb_rbs_required_remaining,
        rballoc_sub,
        MIMO_mode_indicator);
428

knopp's avatar
   
knopp committed
429
    }
430
  }
knopp's avatar
   
knopp committed
431
432


433
  // Store the DLSCH buffer for each logical channel
gauthier's avatar
gauthier committed
434
  store_dlsch_buffer (Mod_id,frameP,subframeP);
435

knopp's avatar
   
knopp committed
436
437


438
  // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
knopp's avatar
   
knopp committed
439
  assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit);
440

knopp's avatar
   
knopp committed
441
442


443
  // Sorts the user on the basis of dlsch logical channel buffer and CQI
knopp's avatar
   
knopp committed
444
445
446
  sort_UEs (Mod_id,frameP,subframeP);


knopp's avatar
   
knopp committed
447

448
  total_ue_count =0;
449

knopp's avatar
   
knopp committed
450
  // loop over all active UEs
451
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
452
    rnti = UE_RNTI(Mod_id,i);
453

454
    if(rnti == NOT_A_RNTI)
knopp's avatar
   
knopp committed
455
      continue;
456

457
    UE_id = i;
458

459
460
461
462
    // if there is no available harq_process, skip the UE
    if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0)
      continue;

463
    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
knopp's avatar
   
knopp committed
464
      CC_id = UE_list->ordered_CCids[ii][UE_id];
465
466
467
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
      harq_pid = ue_sched_ctl->harq_pid[CC_id];
      round    = ue_sched_ctl->round[CC_id];
knopp's avatar
   
knopp committed
468
469
470

      average_rbs_per_user[CC_id]=0;

471
      frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
knopp's avatar
   
knopp committed
472

473
      //      mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
474

475
      if(round>0) {
476
        nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
477
      }
478

knopp's avatar
   
knopp committed
479
480
      //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id];
      if (nb_rbs_required[CC_id][UE_id] > 0) {
481
        total_ue_count = total_ue_count + 1;
knopp's avatar
   
knopp committed
482
      }
483
484
485
486
487
488
489
490
491
492
493
494


      // hypotetical assignement
      /*
       * If schedule is enabled and if the priority of the UEs is modified
       * The average rbs per logical channel per user will depend on the level of
       * priority. Concerning the hypothetical assignement, we should assign more
       * rbs to prioritized users. Maybe, we can do a mapping between the
       * average rbs per user and the level of priority or multiply the average rbs
       * per user by a coefficient which represents the degree of priority.
       */

495
      if (total_ue_count == 0) {
496
        average_rbs_per_user[CC_id] = 0;
497
      } else if( (min_rb_unit[CC_id] * total_ue_count) <= (frame_parms[CC_id]->N_RB_DL) ) {
498
        average_rbs_per_user[CC_id] = (uint16_t) floor(frame_parms[CC_id]->N_RB_DL/total_ue_count);
499
      } else {
500
        average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
501
      }
knopp's avatar
   
knopp committed
502
503
    }
  }
504

505
506
  // note: nb_rbs_required is assigned according to total_buffer_dl
  // extend nb_rbs_required to capture per LCID RB required
507
  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
508
    rnti = UE_RNTI(Mod_id,i);
509

510
    for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
511
      CC_id = UE_list->ordered_CCids[ii][i];
512

gauthier's avatar
gauthier committed
513
      // control channel
514
      if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED) {
515
        nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
516
      } else {
517
518
        nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);

519
      }
knopp's avatar
   
knopp committed
520
    }
521
  }
gauthier's avatar
gauthier committed
522

523
  //Allocation to UEs is done in 2 rounds,
524
525
  // 1st stage: average number of RBs allocated to each UE
  // 2nd stage: remaining RBs are allocated to high priority UEs
526
527
528
529
530
531
  for(r1=0; r1<2; r1++) {

    for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
      for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
        CC_id = UE_list->ordered_CCids[ii][i];

532
        if(r1 == 0) {
533
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
534
        } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
535
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i];
536
        }
537
538
539
540
541
542
543

        if (nb_rbs_required[CC_id][i]> 0 )
          LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d,  pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n",
                r1, CC_id, i,
                nb_rbs_required_remaining[CC_id][i],
                nb_rbs_required_remaining_1[CC_id][i],
                nb_rbs_required[CC_id][i],
544
                UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id],
545
546
547
                N_RBG[CC_id],
                min_rb_unit[CC_id]);

548
      }
knopp's avatar
   
knopp committed
549
    }
550

551
    if (total_ue_count > 0 ) {
552
553
554
555
556
      for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
        UE_id = i;

        for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
          CC_id = UE_list->ordered_CCids[ii][UE_id];
557
558
559
	  ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
	  harq_pid = ue_sched_ctl->harq_pid[CC_id];
	  round    = ue_sched_ctl->round[CC_id];
560
561
562
563

          rnti = UE_RNTI(Mod_id,UE_id);

          // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
564
          if(rnti == NOT_A_RNTI)
565
566
567
            continue;

          transmission_mode = mac_xface->get_transmission_mode(Mod_id,CC_id,rnti);
568
569
	  //          mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
          //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
          /* 1st allocate for the retx */

          // retransmission in data channels
          // control channel in the 1st transmission
          // data channel for all TM
          LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
          dlsch_scheduler_pre_processor_allocate (Mod_id,
                                                  UE_id,
                                                  CC_id,
                                                  N_RBG[CC_id],
                                                  transmission_mode,
                                                  min_rb_unit[CC_id],
                                                  frame_parms[CC_id]->N_RB_DL,
                                                  nb_rbs_required,
                                                  nb_rbs_required_remaining,
                                                  rballoc_sub,
                                                  MIMO_mode_indicator);

588
#ifdef TM5
589
590
591
592

          // data chanel TM5: to be revisted
          if ((round == 0 )  &&
              (transmission_mode == 5)  &&
593
              (ue_sched_ctl->dl_pow_off[CC_id] != 1)) {
594
595
596

            for(j=0; j<N_RBG[CC_id]; j+=2) {

597
598
              if( (((j == (N_RBG[CC_id]-1))&& (rballoc_sub[CC_id][j] == 0) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 0))  ||
                   ((j < (N_RBG[CC_id]-1)) && (rballoc_sub[CC_id][j+1] == 0) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] == 0)) ) &&
599
600
601
602
603
604
                  (nb_rbs_required_remaining[CC_id][UE_id]>0)) {

                for (ii = UE_list->next[i+1]; ii >=0; ii=UE_list->next[ii]) {

                  UE_id2 = ii;
                  rnti2 = UE_RNTI(Mod_id,UE_id2);
605
606
607
		  ue_sched_ctl2 = &UE_list->UE_sched_ctrl[UE_id2];
		  harq_pid2 = ue_sched_ctl2->harq_pid[CC_id];
		  round2    = ue_sched_ctl2->round[CC_id];
608
                  if(rnti2 == NOT_A_RNTI)
609
610
611
                    continue;

                  eNB_UE_stats2 = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti2);
612
                  //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0);
613

614
                  if ((mac_eNB_get_rrc_status(Mod_id,rnti2) >= RRC_RECONFIGURED) &&
615
616
                      (round2==0) &&
                      (mac_xface->get_transmission_mode(Mod_id,CC_id,rnti2)==5) &&
617
                      (ue_sched_ctl->dl_pow_off[CC_id] != 1)) {
618

619
620
                    if( (((j == (N_RBG[CC_id]-1)) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 0)) ||
                         ((j < (N_RBG[CC_id]-1)) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] == 0))  ) &&
621
622
623
624
625
                        (nb_rbs_required_remaining[CC_id][UE_id2]>0)) {

                      if((((eNB_UE_stats2->DL_pmi_single^eNB_UE_stats1->DL_pmi_single)<<(14-j))&0xc000)== 0x4000) { //MU-MIMO only for 25 RBs configuration

                        rballoc_sub[CC_id][j] = 1;
626
627
                        ue_sched_ctl->rballoc_sub_UE[CC_id][j] = 1;
                        ue_sched_ctl2->rballoc_sub_UE[CC_id][j] = 1;
628
629
630
631
                        MIMO_mode_indicator[CC_id][j] = 0;

                        if (j< N_RBG[CC_id]-1) {
                          rballoc_sub[CC_id][j+1] = 1;
632
633
                          ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] = 1;
                          ue_sched_ctl2->rballoc_sub_UE[CC_id][j+1] = 1;
634
635
636
                          MIMO_mode_indicator[CC_id][j+1] = 0;
                        }

637
638
                        ue_sched_ctl->dl_pow_off[CC_id] = 0;
                        ue_sched_ctl2->dl_pow_off[CC_id] = 0;
639
640
641
642
643


                        if ((j == N_RBG[CC_id]-1) &&
                            ((PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL == 25) ||
                             (PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL == 50))) {
644
			  
645
                          nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit[CC_id]+1;
646
                          ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1;
647
                          nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - min_rb_unit[CC_id]+1;
648
                          ue_sched_ctl2->pre_nb_available_rbs[CC_id] = ue_sched_ctl2->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1;
649
                        } else {
650
651
                          
			  nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - 4;
652
                          ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + 4;
653
                          nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - 4;
654
                          ue_sched_ctl2->pre_nb_available_rbs[CC_id] = ue_sched_ctl2->pre_nb_available_rbs[CC_id] + 4;
655
656
657
658
659
660
661
662
663
664
665
666
667
                        }

                        break;
                      }
                    }
                  }
                }
              }
            }
          }

#endif
        }
knopp's avatar
   
knopp committed
668
      }
669
    } // total_ue_count
670
  } // end of for for r1 and r2
671
672
673

#ifdef TM5

knopp's avatar
   
knopp committed
674
  // This has to be revisited!!!!
675
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
   
knopp committed
676
677
678
    i1=0;
    i2=0;
    i3=0;
679
680

    for (j=0; j<N_RBG[CC_id]; j++) {
681
      if(MIMO_mode_indicator[CC_id][j] == 2) {
682
        i1 = i1+1;
683
      } else if(MIMO_mode_indicator[CC_id][j] == 1) {
684
        i2 = i2+1;
685
      } else if(MIMO_mode_indicator[CC_id][j] == 0) {
686
        i3 = i3+1;
687
      }
knopp's avatar
   
knopp committed
688
    }
689

690
    if((i1 < N_RBG[CC_id]) && (i2>0) && (i3==0)) {
knopp's avatar
   
knopp committed
691
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions + 1;
692
    }
693

694
    if(i3 == N_RBG[CC_id] && i1==0 && i2==0) {
knopp's avatar
   
knopp committed
695
      PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + 1;
696
    }
697

698
    if((i1 < N_RBG[CC_id]) && (i3 > 0)) {
knopp's avatar
   
knopp committed
699
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions + 1;
700
    }
701

knopp's avatar
   
knopp committed
702
    PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + 1;
703

704
705
  }

706
707
708
#endif

  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
709
    UE_id = i;
710
    ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
711
712

    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
knopp's avatar
   
knopp committed
713
      CC_id = UE_list->ordered_CCids[ii][UE_id];
gauthier's avatar
gauthier committed
714
      //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
715

716
      if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) {
717
        LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id);
718
        LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,ue_sched_ctl->dl_pow_off[CC_id]);
719
720
721
722
        LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id);

        for(j=0; j<N_RBG[CC_id]; j++) {
          //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i];
723
          LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,ue_sched_ctl->rballoc_sub_UE[CC_id][j]);
724
725
726
        }

        //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
727
        LOG_D(MAC,"Total RBs allocated for UE%d = %d\n",UE_id,ue_sched_ctl->pre_nb_available_rbs[CC_id]);
gauthier's avatar
gauthier committed
728
      }
knopp's avatar
   
knopp committed
729
    }
730
731
732
  }
}

733
#define SF05_LIMIT 1
734

735
void dlsch_scheduler_pre_processor_reset (int module_idP,
736
737
738
739
740
741
742
743
744
745
					  int UE_id,
					  uint8_t  CC_id,
					  int frameP,
					  int subframeP,					  
					  int N_RBG,
					  uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
					  uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
					  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
					  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX])
  
746
{
747
  int i,j;
748
749
750
  UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list;
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  rnti_t rnti = UE_RNTI(module_idP,UE_id);
Cedric Roux's avatar
Cedric Roux committed
751
  uint8_t *vrb_map = eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map;
752
  int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL/N_RBG;
753
#ifdef SF05_LIMIT
754
  //int subframe05_limit=0;
755
756
  int sf05_upper=-1,sf05_lower=-1;
#endif
757
  LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
758
759
760
761
762
763
  // initialize harq_pid and round
  mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,
				    frameP,subframeP,
				    &ue_sched_ctl->harq_pid[CC_id],
				    &ue_sched_ctl->round[CC_id],
				    0);
764
  if (ue_sched_ctl->ta_timer == 0) {
765

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
    // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...

    ue_sched_ctl->ta_timer = 20;  // wait 20 subframes before taking TA measurement from PHY
    switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) {
    case 6:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update;
      break;
      
    case 15:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2;
      break;
      
    case 25:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4;
      break;
      
    case 50:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8;
      break;
      
    case 75:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12;
      break;
      
    case 100:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16;
      break;
    }
    // clear the update in case PHY does not have a new measurement after timer expiry
    eNB_UE_stats->timing_advance_update =  0;
  }
  else {
    ue_sched_ctl->ta_timer--;
    ue_sched_ctl->ta_update =0; // don't trigger a timing advance command
  }
801
  nb_rbs_required[CC_id][UE_id]=0;
802
803
  ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0;
  ue_sched_ctl->dl_pow_off[CC_id] = 2;
804
  nb_rbs_required_remaining[CC_id][UE_id] = 0;
805

806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
#ifdef SF05_LIMIT  
  switch (N_RBG) {
  case 6:
    sf05_lower=0;
    sf05_upper=5;
    break;
  case 8:
    sf05_lower=2;
    sf05_upper=5;
    break;
  case 13:
    sf05_lower=4;
    sf05_upper=7;
    break;
  case 17:
    sf05_lower=7;
    sf05_upper=9;
    break;
  case 25:
    sf05_lower=11;
    sf05_upper=13;
    break;
  }
#endif
830
  // Initialize Subbands according to VRB map
831
  for (i=0; i<N_RBG; i++) {
832
    ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0;
833
    rballoc_sub[CC_id][i] = 0;
834
835
836
837
838
839
840
841
#ifdef SF05_LIMIT
    // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors)

    if ((subframeP==0 || subframeP==5) && 
	(i>=sf05_lower && i<=sf05_upper))
      rballoc_sub[CC_id][i]=1;
#endif
    // for SI-RNTI,RA-RNTI and P-RNTI allocations
842
    for (j=0;j<RBGsize;j++) {
843
      if (vrb_map[j+(i*RBGsize)]!=0)  {
844
	rballoc_sub[CC_id][i] = 1;
845
	LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize));
846
847
848
849
	break;
      }
    }
    LOG_D(MAC,"Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n",frameP,subframeP,CC_id,i,rballoc_sub[CC_id][i]);
850
    MIMO_mode_indicator[CC_id][i] = 2;
851
852
853
854
855
  }
}


void dlsch_scheduler_pre_processor_allocate (module_id_t   Mod_id,
856
857
858
859
860
861
862
863
864
865
866
867
    int           UE_id,
    uint8_t       CC_id,
    int           N_RBG,
    int           transmission_mode,
    int           min_rb_unit,
    uint8_t       N_RB_DL,
    uint16_t      nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
    uint16_t      nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
    unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
    unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX])
{

868
  int i;
869
870
  UE_list_t *UE_list=&eNB_mac_inst[Mod_id].UE_list;
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
871
872
873
874

  for(i=0; i<N_RBG; i++) {

    if((rballoc_sub[CC_id][i] == 0)           &&
875
        (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) &&
876
        (nb_rbs_required_remaining[CC_id][UE_id]>0)   &&
877
        (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) {
878

879
      // if this UE is not scheduled for TM5
880
      if (ue_sched_ctl->dl_pow_off[CC_id] != 0 )  {
881

882
883
	if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
	  rballoc_sub[CC_id][i] = 1;
884
	  ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
885
886
	  MIMO_mode_indicator[CC_id][i] = 1;
	  if (transmission_mode == 5 ) {
887
	    ue_sched_ctl->dl_pow_off[CC_id] = 1;
888
889
	  }   
	  nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1;
890
          ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
891
        } else {
892
</