Commit f14a401f authored by Cedric Roux's avatar Cedric Roux

Manage free downlink HARQ processes with a circular list.

The oldest PID (the PID that was used the longest
TTI ago) is at the head and is the next one that
will be used.

No test is done to check that when a process is
allocated it is at least N TTIs old, but some quick
thinking strongly leads to the 'conclusion' that N
won't be smaller than 8, which seems to be what
cat3 UEs require to function properly in the downlink
direction (from the eNodeB to the UE).
parent 68249569
......@@ -1102,8 +1102,12 @@ int generate_eNB_dlsch_params_from_dci(int frame,
dlsch[0]->harq_ids[subframe] = harq_pid;
if (dlsch0_harq->round == 0)
if (dlsch0_harq->round == 0) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch[0], harq_pid);
dlsch0_harq->status = ACTIVE;
}
break;
......@@ -1237,6 +1241,9 @@ int generate_eNB_dlsch_params_from_dci(int frame,
if (dlsch0_harq->round == 0) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch[0], harq_pid);
dlsch0_harq->status = ACTIVE;
// printf("Setting DLSCH process %d to ACTIVE\n",harq_pid);
// MCS and TBS don't change across HARQ rounds
......@@ -1605,10 +1612,16 @@ int generate_eNB_dlsch_params_from_dci(int frame,
// reset HARQ process if this is the first transmission
if (dlsch0_harq->round == 0) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch0, harq_pid);
dlsch0_harq->status = ACTIVE;
}
if (dlsch1_harq->round == 0) {
/* necessary test? */
if (dlsch1_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch1, harq_pid);
dlsch1_harq->status = ACTIVE;
}
......@@ -1986,10 +1999,16 @@ int generate_eNB_dlsch_params_from_dci(int frame,
// reset HARQ process if this is the first transmission
if ((dlsch0->active==1) && (dlsch0_harq->round == 0)) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch0, harq_pid);
dlsch0_harq->status = ACTIVE;
}
if ((dlsch1->active==1) && (dlsch1_harq->round == 0)) {
/* necessary test? */
if (dlsch1_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch1, harq_pid);
dlsch1_harq->status = ACTIVE;
}
......@@ -2131,16 +2150,23 @@ int generate_eNB_dlsch_params_from_dci(int frame,
// check if either TB is disabled (see 36-213 V8.6 p. 26)
if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0))
if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) {
LOG_W(PHY, "what to do with respect to get_harq_pid_from_freelist?\n");
dlsch0_harq->status = DISABLED;
}
if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0))
if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) {
LOG_W(PHY, "what to do with respect to get_harq_pid_from_freelist?\n");
dlsch1_harq->status = DISABLED;
}
dlsch0_harq->Nl = 1;
if (dlsch0_harq->round == 0) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch0, harq_pid);
dlsch0_harq->status = ACTIVE;
// printf("Setting DLSCH process %d to ACTIVE\n",harq_pid);
}
......@@ -2305,11 +2331,17 @@ int generate_eNB_dlsch_params_from_dci(int frame,
if ((dlsch0_harq->round == 0) && (dlsch0->active == 1) ) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch0, harq_pid);
dlsch0_harq->status = ACTIVE;
dlsch0_harq->mcs = mcs1;
}
if ((dlsch1_harq->round == 0) && (dlsch1->active == 1) ) {
/* necessary test? */
if (dlsch1_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch1, harq_pid);
dlsch1_harq->status = ACTIVE;
dlsch1_harq->mcs = mcs2;
}
......@@ -2473,6 +2505,9 @@ int generate_eNB_dlsch_params_from_dci(int frame,
if (dlsch0_harq->round == 0) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch0, harq_pid);
dlsch0_harq->status = ACTIVE;
// printf("Setting DLSCH process %d to ACTIVE\n",harq_pid);
}
......@@ -2602,6 +2637,9 @@ int generate_eNB_dlsch_params_from_dci(int frame,
// dlsch0_harq->Ndi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi;
if (dlsch0_harq->round == 0) {
/* necessary test? */
if (dlsch0_harq->status == SCH_IDLE)
get_harq_pid_from_freelist(dlsch0, harq_pid);
dlsch0_harq->status = ACTIVE;
// printf("Setting DLSCH process %d to ACTIVE\n",harq_pid);
}
......
......@@ -258,6 +258,13 @@ typedef struct {
uint8_t error_threshold;
/// Pointers to 8 HARQ processes for the DLSCH
LTE_DL_eNB_HARQ_t *harq_processes[8];
/// circular list of free harq PIDs (the oldest come first)
/// (10 is arbitrary value, must be > to max number of DL HARQ processes in LTE)
int harq_pid_freelist[10];
/// the head position of the free list (if list is free then head=tail)
int head_freelist;
/// the tail position of the free list
int tail_freelist;
/// Number of soft channel bits
uint32_t G;
/// Codebook index for this dlsch (0,1,2,3)
......
......@@ -152,6 +152,9 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigne
for (i=0; i<10; i++)
dlsch->harq_ids[i] = Mdlharq;
dlsch->head_freelist = 0;
dlsch->tail_freelist = 0;
for (i=0; i<Mdlharq; i++) {
dlsch->harq_processes[i] = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t));
LOG_T(PHY, "Required mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n",
......@@ -192,6 +195,8 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigne
msg("Can't get harq_p %d\n",i);
exit_flag=3;
}
put_harq_pid_in_freelist(dlsch, i);
}
if (exit_flag==0) {
......
......@@ -401,6 +401,8 @@ uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1);
int get_nCCE_offset(unsigned char L, int nCCE, int common_dci, unsigned short rnti, unsigned char subframe);
void put_harq_pid_in_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid);
void get_harq_pid_from_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid);
int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
......
......@@ -136,6 +136,21 @@ uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t sched_su
return(0);
}
void put_harq_pid_in_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid)
{
DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->tail_freelist] = harq_pid;
DLSCH_ptr->tail_freelist = (DLSCH_ptr->tail_freelist + 1) % 10;
}
void get_harq_pid_from_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid)
{
if (DLSCH_ptr->head_freelist == DLSCH_ptr->tail_freelist) {
LOG_E(PHY, "%s:%d: you cannot read this!\n", __FILE__, __LINE__);
abort();
}
DLSCH_ptr->head_freelist = (DLSCH_ptr->head_freelist + 1) % 10;
}
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB)
{
uint8_t i;
......@@ -178,6 +193,7 @@ int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB)
int32_t remove_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB, uint8_t abstraction_flag)
{
uint8_t i;
int j;
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if ((phy_vars_eNB->dlsch_eNB[i]==NULL) || (phy_vars_eNB->ulsch_eNB[i]==NULL)) {
......@@ -196,6 +212,13 @@ int32_t remove_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB, uint8_t abstraction
//phy_vars_eNB->eNB_UE_stats[i].crnti = 0;
memset(&phy_vars_eNB->eNB_UE_stats[i],0,sizeof(LTE_eNB_UE_stats));
// mac_exit_wrapper("Removing UE");
/* clear the harq pid freelist */
phy_vars_eNB->dlsch_eNB[i][0]->head_freelist = 0;
phy_vars_eNB->dlsch_eNB[i][0]->tail_freelist = 0;
for (j = 0; j < 8; j++)
put_harq_pid_in_freelist(phy_vars_eNB->dlsch_eNB[i][0], j);
return(i);
}
}
......@@ -248,18 +271,7 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
for (i=0; i<DLSCH_ptr->Mdlharq; i++) {
if (DLSCH_ptr->harq_processes[i]!=NULL) {
if (DLSCH_ptr->harq_processes[i]->status != ACTIVE) {
// store first inactive process
if (hp2sf[i] == subframe && first_proc_found == 0) {
first_proc_found = 1;
*harq_pid = i;
*round = 0;
LOG_D(PHY,"process %d is first free process\n",i);
}
else {
LOG_D(PHY,"process %d is free\n",i);
}
} else {
if (DLSCH_ptr->harq_processes[i]->status == ACTIVE) {
sf2 = (DLSCH_ptr->harq_processes[i]->frame*10) + DLSCH_ptr->harq_processes[i]->subframe;
if (sf2<=sf1)
sfdiff = sf1-sf2;
......@@ -279,6 +291,14 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
return(-1);
}
}
/* if no active harq pid, get the oldest in the freelist, if any */
if (*harq_pid == 255 && DLSCH_ptr->head_freelist != DLSCH_ptr->tail_freelist) {
*harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
*round = 0;
LOG_D(PHY,"process %d is first free process\n", *harq_pid);
}
LOG_D(PHY,"get_ue_active_harq_pid DL => Frame %d, Subframe %d : harq_pid %d\n",
frame,subframe,*harq_pid);
} else { // This is a UL request
......@@ -297,7 +317,6 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
return(0);
}
int CCE_table[800];
void init_nCCE_table(void)
......@@ -2869,6 +2888,7 @@ void process_HARQ_feedback(uint8_t UE_id,
dlsch_harq_proc->round = 0;
ue_stats->dlsch_l2_errors[dl_harq_pid[m]]++;
dlsch_harq_proc->status = SCH_IDLE;
put_harq_pid_in_freelist(dlsch, dl_harq_pid[m]);
dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;
}
} else {
......@@ -2881,6 +2901,7 @@ void process_HARQ_feedback(uint8_t UE_id,
// Received ACK so set round to 0 and set dlsch_harq_pid IDLE
dlsch_harq_proc->round = 0;
dlsch_harq_proc->status = SCH_IDLE;
put_harq_pid_in_freelist(dlsch, dl_harq_pid[m]);
dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;
ue_stats->total_TBS = ue_stats->total_TBS +
......@@ -3950,6 +3971,9 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_
phy_vars_eNB->eNB_UE_stats[i].sr_received++;
if (phy_vars_eNB->first_sr[i] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
/* is this test necessary? */
if (phy_vars_eNB->dlsch_eNB[i][0]->harq_processes[0]->status != SCH_IDLE)
put_harq_pid_in_freelist(phy_vars_eNB->dlsch_eNB[i][0], 0);
phy_vars_eNB->first_sr[i] = 0;
phy_vars_eNB->dlsch_eNB[i][0]->harq_processes[0]->round=0;
phy_vars_eNB->dlsch_eNB[i][0]->harq_processes[0]->status=SCH_IDLE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment