eNB_scheduler.c 30 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22

/*! \file eNB_scheduler.c
nikaeinn's avatar
nikaeinn committed
23
 * \brief eNB scheduler top level function operates on per subframe basis
24 25
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
26
 * \email: navid.nikaein@eurecom.fr
27 28
 * \version 0.5
 * @ingroup _mac
29

30
 */
31

32
#include "assertions.h"
33 34 35 36 37 38 39 40
#include "PHY/defs.h"
#include "PHY/extern.h"

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

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
gauthier's avatar
gauthier committed
41

42 43 44 45 46 47
#include "LAYER2/MAC/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
gauthier's avatar
gauthier committed
48

49 50
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
gauthier's avatar
gauthier committed
51

52 53
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
54

55
#if defined(FLEXRAN_AGENT_SB_IF)
56
//Agent-related headers
57 58 59
#include "flexran_agent_extern.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_mac_proto.h"
60
#endif
61

62 63
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
64 65
#endif

66 67
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
68

69
extern RAN_CONTEXT_t RC;
70

71 72
uint16_t pdcch_order_table[6] = {31,31,511,2047,2047,8191};

73

74 75
void schedule_SRS(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP)
{
76 77 78
  eNB_MAC_INST                   *eNB            = RC.mac[module_idP];
  UE_list_t                      *UE_list        = &eNB->UE_list;
  nfapi_ul_config_request_body_t *ul_req;
79
  int CC_id,UE_id;
80 81 82 83 84 85
  COMMON_channels_t                   *cc        = RC.mac[module_idP]->common_channels;
  SoundingRS_UL_ConfigCommon_t      *soundingRS_UL_ConfigCommon;
  struct SoundingRS_UL_ConfigDedicated     *soundingRS_UL_ConfigDedicated;
  uint8_t  TSFC;
  uint16_t deltaTSFC; // bitmap
  uint8_t  srs_SubframeConfig;
86

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
  // table for TSFC (Period) and deltaSFC (offset)
  const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} };      // Table 5.5.3.3-2 3GPP 36.211 FDD
  const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD

  uint16_t srsPeriodicity,srsOffset;

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
    soundingRS_UL_ConfigCommon = &cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon;
    // check if SRS is enabled in this frame/subframe
    if (soundingRS_UL_ConfigCommon) {
      srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
      if (cc[CC_id].tdd_Config == NULL) { // FDD
	deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
	TSFC      = deltaTSFCTabType1[srs_SubframeConfig][1];
      }
      else { // TDD
	deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
	TSFC      = deltaTSFCTabType2[srs_SubframeConfig][1];
      }
      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
      uint16_t tmp = (subframeP %  TSFC);

      if((1<<tmp) & deltaTSFC) {
	// This is an SRS subframe, loop over UEs
111 112
	for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
	  if (RC.mac[module_idP]->UE_list.active[UE_id]!=TRUE) continue;
113
	  ul_req        = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
114 115


116 117 118
          // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
          if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED) continue;

119
	  AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id);
120

121 122 123 124 125 126
	  if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) {
	    if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
	      get_srs_pos(&cc[CC_id], soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex, &srsPeriodicity, &srsOffset);
	      if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) {
		// Prorgram SRS
		ul_req->srs_present                                                 = 1;
127
		nfapi_ul_config_request_pdu_t* ul_config_pdu                        = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
128 129 130
		memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
		ul_config_pdu->pdu_type                                             = NFAPI_UL_CONFIG_SRS_PDU_TYPE;
		ul_config_pdu->pdu_size                                             = 2+(uint8_t)(2+sizeof(nfapi_ul_config_srs_pdu));
131 132
		ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag                          = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.size                            = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);
133 134 135 136 137
		ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti                            = UE_list->UE_template[CC_id][UE_id].rnti;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth                   = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position       = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth           = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb               = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
138 139
		ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs                           = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
140 141 142
		//		ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port                   = ;//
		//		ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs                = ;//
		RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP<<4)+subframeP;
143
		RC.mac[module_idP]->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
144
		ul_req->number_of_pdus++;
145 146 147
	      } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
	    } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
	  } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
148 149 150 151 152 153 154
	} // for (UE_id ...
      } // if((1<<tmp) & deltaTSFC)

    }// SRS config
  }
}

155 156
void schedule_CSI(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP)
{
157 158 159 160
  eNB_MAC_INST                   *eNB          = RC.mac[module_idP];
  UE_list_t                      *UE_list      = &eNB->UE_list;
  COMMON_channels_t              *cc;
  nfapi_ul_config_request_body_t *ul_req;
161
  int CC_id,UE_id;
162 163 164 165 166 167 168
  struct CQI_ReportPeriodic *cqi_ReportPeriodic;
  uint16_t Npd,N_OFFSET_CQI;
  int H;

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

    cc = &eNB->common_channels[CC_id];
169 170
    for (UE_id=0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
      if (UE_list->active[UE_id] != TRUE) continue;
171 172 173

      ul_req        = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;

Cedric Roux's avatar
Cedric Roux committed
174 175 176
      // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
      if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED) continue;

177 178 179 180 181 182 183 184
      AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id);

      if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) {
	if ((cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic)!=NULL &&
	    (cqi_ReportPeriodic->present!=CQI_ReportPeriodic_PR_release)) {
	  //Rel8 Periodic CQI/PMI/RI reporting

	  get_csi_params(cc,cqi_ReportPeriodic,&Npd,&N_OFFSET_CQI,&H);
185

186 187 188
	  if ((((frameP*10)+subframeP)%Npd) == N_OFFSET_CQI) {  // CQI opportunity
	    UE_list->UE_sched_ctrl[UE_id].feedback_cnt[CC_id]=(((frameP*10)+subframeP)/Npd)%H;
	    // Program CQI
189
	    nfapi_ul_config_request_pdu_t* ul_config_pdu                                     = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
190 191 192
	    memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
	    ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
	    ul_config_pdu->pdu_size                                                          = 2+(uint8_t)(2+sizeof(nfapi_ul_config_uci_cqi_pdu));
193
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
194
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
195
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
196 197 198 199 200 201 202
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id],
															CC_id,
															cc,
															get_tmode(module_idP,CC_id,UE_id),
															cqi_ReportPeriodic);
	    ul_req->number_of_pdus++;
203
	    ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
204 205 206

#if defined(Rel10) || defined(Rel14)
	    // PUT rel10-13 UCI options here
207
#endif
208 209 210 211 212
	  }
	  else if ((cqi_ReportPeriodic->choice.setup.ri_ConfigIndex) &&
		   ((((frameP*10)+subframeP)%((H*Npd)<<(*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex/161)))==
		    N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex%161))) {  // RI opportunity
	    // Program RI
213
	    nfapi_ul_config_request_pdu_t* ul_config_pdu                                     = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
214 215 216
	    memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
	    ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
	    ul_config_pdu->pdu_size                                                          = 2+(uint8_t)(2+sizeof(nfapi_ul_config_uci_cqi_pdu));
217
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
218
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
219
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
220 221 222 223
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = (cc->p_eNB==2)?1:2;
	    RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP<<4)+subframeP;
	    ul_req->number_of_pdus++;
224
	    ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
225 226 227 228 229 230 231 232
	  }

	} // if ((cqi_ReportPeriodic = cqi_ReportConfig->cqi_ReportPeriodic)!=NULL) {
      } // if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig)
    } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
  } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
}

233 234 235 236
void schedule_SR(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
{
  eNB_MAC_INST                   *eNB        = RC.mac[module_idP];
  UE_list_t                      *UE_list    = &eNB->UE_list;
237 238
  nfapi_ul_config_request_t      *ul_req;
  nfapi_ul_config_request_body_t *ul_req_body;
239 240
  int                             CC_id;
  int                             UE_id;
241
  SchedulingRequestConfig_t      *SRconfig;
242 243 244 245
  int                             skip_ue;
  int                             is_harq;
  nfapi_ul_config_sr_information  sr;
  int                             i;
246

247 248
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
249

250 251
    for (UE_id = 0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
      if (RC.mac[module_idP]->UE_list.active[UE_id]!=TRUE) continue;
252

253 254
      ul_req        = &RC.mac[module_idP]->UL_req[CC_id];
      ul_req_body   = &ul_req->ul_config_request_body;
255

256
      //LOG_D(MAC, "UE active UE_id:%d ul_req_body->number_of_pdus:%d\n", UE_id, ul_req_body->number_of_pdus);
257

258 259
      AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id);

260 261 262
      // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
      if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED) continue;

263
      if ((SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) {
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
        if (SRconfig->present == SchedulingRequestConfig_PR_setup) {
          if (SRconfig->choice.setup.sr_ConfigIndex <= 4) {        // 5 ms SR period
            if ((subframeP%5) != SRconfig->choice.setup.sr_ConfigIndex)
              continue;
          } else if (SRconfig->choice.setup.sr_ConfigIndex <= 14) { // 10 ms SR period
            if (subframeP!=(SRconfig->choice.setup.sr_ConfigIndex-5))
              continue;
          } else if (SRconfig->choice.setup.sr_ConfigIndex <= 34) { // 20 ms SR period
            if ((10*(frameP&1)+subframeP) != (SRconfig->choice.setup.sr_ConfigIndex-15))
              continue;
          } else if (SRconfig->choice.setup.sr_ConfigIndex <= 74) { // 40 ms SR period
            if ((10*(frameP&3)+subframeP) != (SRconfig->choice.setup.sr_ConfigIndex-35))
              continue;
          } else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) { // 80 ms SR period
            if ((10*(frameP&7)+subframeP) != (SRconfig->choice.setup.sr_ConfigIndex-75))
              continue;
          }
        } // SRconfig->present == SchedulingRequestConfig_PR_setup)
      } // SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL)
283 284 285

      // if we get here there is some PUCCH1 reception to schedule for SR

286 287
      skip_ue=0;
      is_harq = 0;
288
      // check that there is no existing UL grant for ULSCH which overrides the SR
289 290 291 292 293 294
      for (i = 0; i < ul_req_body->number_of_pdus; i++) {
        if (((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE)||
             (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE)||
             (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE)||
             (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE))&&
            (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) {
295 296 297 298
            skip_ue=1;
            break;
        }
        /* if there is already an HARQ pdu, convert to SR_HARQ */
299 300
        else if ((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE)&&
                 (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) {
301 302 303 304
          is_harq = 1;
          break;
        }
      }
305 306

      // drop the allocation because ULSCH with handle it with BSR
307
      if (skip_ue==1) continue;
308

309
      LOG_D(MAC,"Frame %d, Subframe %d : Scheduling SR for UE %d/%x is_harq:%d\n",frameP,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].rnti, is_harq);
310 311 312 313

      // check Rel10 or Rel8 SR
#if defined(Rel10) || defined(Rel14)
      if ((UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) &&
314
          (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) {
315 316
        sr.sr_information_rel8.tl.tag = 0;
        sr.sr_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG;
317 318
        sr.sr_information_rel10.number_of_pucch_resources = 1;
        sr.sr_information_rel10.pucch_index_p1 = *UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10;
319 320

        LOG_D(MAC,"REL10 PUCCH INDEX P1:%d\n", sr.sr_information_rel10.pucch_index_p1);
321
      } else
322
#endif
323
      {
324
        sr.sr_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG;
325
        sr.sr_information_rel8.pucch_index = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
326 327 328
        sr.sr_information_rel10.tl.tag = 0;

        LOG_D(MAC,"REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index);
329 330 331 332
      }

      /* if there is already an HARQ pdu, convert to SR_HARQ */
      if (is_harq) {
333 334 335 336
        nfapi_ul_config_harq_information h = ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.harq_information;
        ul_req_body->ul_config_pdu_list[i].pdu_type                         = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
        ul_req_body->ul_config_pdu_list[i].uci_sr_harq_pdu.sr_information   = sr;
        ul_req_body->ul_config_pdu_list[i].uci_sr_harq_pdu.harq_information = h;
337
      } else {
338 339 340 341 342 343 344
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].pdu_type                                             = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE;
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti   = UE_list->UE_template[CC_id][UE_id].rnti;
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel11.tl.tag = 0;
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel13.tl.tag = 0;
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.sr_information                            = sr;
        ul_req_body->number_of_pdus++;
345
      } /* if (is_harq) */
346 347
      ul_req_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;

348 349 350 351
    } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id])
  } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
}

352
void check_ul_failure(module_id_t module_idP,int CC_id,int UE_id,
353 354
		      frame_t frameP, sub_frame_t subframeP)
{
355
  UE_list_t                           *UE_list      = &RC.mac[module_idP]->UE_list;
356
  nfapi_dl_config_request_t           *DL_req       = &RC.mac[module_idP]->DL_req[0];
357 358 359 360 361 362
  uint16_t                            rnti          = UE_RNTI(module_idP,UE_id);
  COMMON_channels_t                   *cc           = RC.mac[module_idP]->common_channels;

  // check uplink failure
  if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer>0)&&
      (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync==0)) {
363
    LOG_I(MAC,"UE %d rnti %x: UL Failure timer %d \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);
364 365
    if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent==0) {
      UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=1;
366

367
      // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
368
      nfapi_dl_config_request_pdu_t* dl_config_pdu                    = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu];
369
      memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
370
      dl_config_pdu->pdu_type                                         = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
371
      dl_config_pdu->pdu_size                                         = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
372
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
373
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format            = NFAPI_DL_DCI_FORMAT_1A;
Cedric Roux's avatar
Cedric Roux committed
374
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level     = get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format1A);
375 376 377
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                  = rnti;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type             = 1;    // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power    = 6000; // equal to RS power
378

379 380 381
      AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >=0) && (cc[CC_id].mib->message.dl_Bandwidth<6),
		  "illegal dl_Bandwidth %d\n",(int)cc[CC_id].mib->message.dl_Bandwidth);
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth];
382
      DL_req[CC_id].dl_config_request_body.number_dci++;
383 384
      LOG_E(MAC, "%s() number_dci:%u\n", __FUNCTION__, DL_req[CC_id].dl_config_request_body.number_dci);

385
      DL_req[CC_id].dl_config_request_body.number_pdu++;
386
      DL_req[CC_id].dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
387
     
388
      LOG_I(MAC,"UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding);
389 390
    }
    else { // ra_pdcch_sent==1
391
      LOG_I(MAC,"UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);
392
      if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0)
393
	UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=0; // resend every 4 frames
394
    }
395

396 397 398 399
    UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++;
    // check threshold
    if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 200) {
      // inform RRC of failure and clear timer
400
      LOG_I(MAC,"UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti);
401 402 403 404 405 406
      mac_eNB_rrc_ul_failure(module_idP,CC_id,frameP,subframeP,rnti);
      UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0;
      UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=1;
    }
  } // ul_failure_timer>0

407
}
408

409 410
extern uint8_t nfapi_mode;

411 412
void clear_nfapi_information(eNB_MAC_INST *eNB,int CC_idP,frame_t frameP,sub_frame_t subframeP)
{
413 414 415 416
  nfapi_dl_config_request_t *DL_req         = &eNB->DL_req[0];
  nfapi_ul_config_request_t *UL_req         = &eNB->UL_req[0];
  nfapi_hi_dci0_request_t   *HI_DCI0_req    = &eNB->HI_DCI0_req[0];
  nfapi_tx_request_t        *TX_req         = &eNB->TX_req[0];
417

418
  eNB->pdu_index[CC_idP]                                     = 0;
419

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
  if (nfapi_mode==0 || nfapi_mode == 1)   // monolithic or PNF
  {
    DL_req[CC_idP].dl_config_request_body.number_pdcch_ofdm_symbols           = 1;
    DL_req[CC_idP].dl_config_request_body.number_dci                          = 0;
    DL_req[CC_idP].dl_config_request_body.number_pdu                          = 0;
    DL_req[CC_idP].dl_config_request_body.number_pdsch_rnti                   = 0;
    DL_req[CC_idP].dl_config_request_body.transmission_power_pcfich           = 6000;

    HI_DCI0_req[CC_idP].hi_dci0_request_body.sfnsf                            = subframeP + (frameP<<4);
    HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci                    = 0;


    UL_req[CC_idP].ul_config_request_body.number_of_pdus                      = 0;
    UL_req[CC_idP].ul_config_request_body.rach_prach_frequency_resources      = 0; // ignored, handled by PHY for now
    UL_req[CC_idP].ul_config_request_body.srs_present                         = 0; // ignored, handled by PHY for now


    TX_req[CC_idP].tx_request_body.number_of_pdus                 = 0;

    LOG_D(MAC,"%s() SFN_SF:%d%d ZERO PDUs of TX_req:(SFN_SF:%d):%d UL_req:(SFN_SF:%d):%d HI_DCI0_req:(SFN_SF:%d):dci:%d hi:%d DL:(SFN_SF:%d):dci:%d DL:pdu:%d\n", 
        __FUNCTION__,
        frameP, subframeP,
        NFAPI_SFNSF2DEC(TX_req[CC_idP].sfn_sf),
        TX_req[CC_idP].tx_request_body.number_of_pdus,
        NFAPI_SFNSF2DEC(UL_req[CC_idP].sfn_sf),
        UL_req[CC_idP].ul_config_request_body.number_of_pdus,
        NFAPI_SFNSF2DEC(HI_DCI0_req[CC_idP].sfn_sf),
        HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci,
        HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_hi,
        NFAPI_SFNSF2DEC(DL_req[CC_idP].sfn_sf),
        DL_req[CC_idP].dl_config_request_body.number_dci,
        DL_req[CC_idP].dl_config_request_body.number_pdu);
  }
453 454
}

455 456
void copy_ulreq(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP)
{
457 458
  int CC_id;
  eNB_MAC_INST *eNB;
459 460
  nfapi_ul_config_request_body_t *ul_req_body_tmp;
  nfapi_ul_config_request_body_t *ul_req_body;
461 462 463 464 465

  eNB = RC.mac[module_idP];

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

466 467
    ul_req_body_tmp       = &eNB->UL_req_tmp[CC_id][subframeP].ul_config_request_body;
    ul_req_body           = &eNB->UL_req[CC_id].ul_config_request_body;
468

469
    eNB->UL_req[CC_id].sfn_sf   = (frameP<<4) + subframeP;
470 471 472 473 474 475
    eNB->UL_req[CC_id].header   = eNB->UL_req_tmp[CC_id][subframeP].header;
    ul_req_body->number_of_pdus                     = ul_req_body_tmp->number_of_pdus;
    ul_req_body_tmp->number_of_pdus = 0;

    if (ul_req_body->number_of_pdus>0)
    {
476
      LOG_E(PHY, "%s() Copying stored UL_req_tmp to UL_req for activation NOW (frameP:%d subframeP:%d) ul_req_body->number_of_pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req_body->number_of_pdus);
477
    }
478

479 480 481
    memcpy((void*)ul_req_body->ul_config_pdu_list,
	   (void*)ul_req_body_tmp->ul_config_pdu_list,
	   ul_req_body->number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t));
482

483
  }
484 485
}

486
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
487
{
488

489
  int mbsfn_status[MAX_NUM_CCs];
490
  protocol_ctxt_t   ctxt;
491

492
  int CC_id,i; //,next_i;
493
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
494
  rnti_t rnti;
495

496
  COMMON_channels_t         *cc             = RC.mac[module_idP]->common_channels;
497

498
#if defined(FLEXRAN_AGENT_SB_IF)
499
  Protocol__FlexranMessage *msg;
500
#endif
501

502

503
  start_meas(&RC.mac[module_idP]->eNB_scheduler);
gauthier's avatar
gauthier committed
504
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
505

506
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
507
    mbsfn_status[CC_id]=0;
508 509

    // clear vrb_maps
knopp's avatar
knopp committed
510
    memset(cc[CC_id].vrb_map,0,100);
511
    memset(cc[CC_id].vrb_map_UL,0,100);
512

513

Cedric Roux's avatar
Cedric Roux committed
514
#if defined(Rel10) || defined(Rel14)
knopp's avatar
knopp committed
515
    cc[CC_id].mcch_active =0;
516
#endif
517 518
    RC.mac[module_idP]->frame    = frameP;
    RC.mac[module_idP]->subframe = subframeP;
519 520
  }

521
  // refresh UE list based on UEs dropped by PHY in previous subframe
522 523
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] != TRUE) continue;
524

525 526 527
    rnti         = UE_RNTI(module_idP, i);
    CC_id        = UE_PCCID(module_idP, i);

528
    if ((frameP==0)&&(subframeP==0)) {
knopp's avatar
knopp committed
529
      LOG_I(MAC,"UE  rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", rnti,
530 531
            UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync",
            UE_list->UE_template[CC_id][i].phr_info,
knopp's avatar
knopp committed
532 533
            UE_list->UE_sched_ctrl[i].dl_cqi[CC_id],
	    (UE_list->UE_sched_ctrl[i].pusch_snr[CC_id]-128)/2,
534
	    (UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id]-128)/2);
535
    }
536

537
    RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63;
538
    if (i==UE_list->head)
539
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]);
540
    // increment this, it is cleared when we receive an sdu
541
    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer++;
542

543
    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer++;
544
    LOG_D(MAC,"UE %d/%x : ul_inactivity %d, cqi_req %d\n",i,rnti,
knopp's avatar
knopp committed
545 546
	  RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer,
	  RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer);
547 548
    check_ul_failure(module_idP,CC_id,i,frameP,subframeP);

549
  }
550

551
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP);
552
  pdcp_run(&ctxt);
553

554 555
  rrc_rx_tx(&ctxt,
            0, // eNB index, unused in eNB
556
            CC_id);
557

Cedric Roux's avatar
Cedric Roux committed
558
#if defined(Rel10) || defined(Rel14)
559 560

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
knopp committed
561
    if (cc[CC_id].MBMS_flag >0) {
562
      start_meas(&RC.mac[module_idP]->schedule_mch);
563
      mbsfn_status[CC_id] = schedule_MBMS(module_idP,CC_id,frameP,subframeP);
564
      stop_meas(&RC.mac[module_idP]->schedule_mch);
565
    }
566
  }
567

568
#endif
569

570
  // This schedules MIB
571 572
  //if ((subframeP==0) && (frameP&3) == 0) schedule_mib(module_idP,frameP,subframeP);
  if (subframeP==0) schedule_mib(module_idP,frameP,subframeP);
573
  // This schedules SI for legacy LTE and eMTC starting in subframeP
574
  schedule_SI(module_idP,frameP,subframeP);
575
  // This schedules Random-Access for legacy LTE and eMTC starting in subframeP
576
  schedule_RA(module_idP,frameP,subframeP);
577 578 579 580 581
  // copy previously scheduled UL resources (ULSCH + HARQ)
  copy_ulreq(module_idP,frameP,subframeP);
  // This schedules SRS in subframeP
  schedule_SRS(module_idP,frameP,subframeP);
  // This schedules ULSCH in subframeP (dci0)
582
  schedule_ulsch(module_idP,frameP,subframeP);
583 584 585 586
  // This schedules UCI_SR in subframeP
  schedule_SR(module_idP,frameP,subframeP);
  // This schedules UCI_CSI in subframeP
  schedule_CSI(module_idP, frameP, subframeP);
587

588
  // This schedules DLSCH in subframeP
589 590
  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);

591
  // Allocate CCEs for good after scheduling is done
592

593 594
  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) allocate_CCEs(module_idP,CC_id,subframeP,0);
  
595

596
  stop_meas(&RC.mac[module_idP]->eNB_scheduler);
597

gauthier's avatar
gauthier committed
598
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);
599
}