* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fapi_5g / source / api / fapi2mac / p7 / nr5g_fapi_proc_rx_data_ind.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2021 Intel.
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  * @file
21  * This file consist of implementation of FAPI CRC.indication message.
22  *
23  **/
24
25 #include "nr5g_mac_phy_api.h"
26 #include "nr5g_fapi_framework.h"
27 #include "nr5g_fapi_fapi2mac_api.h"
28 #include "nr5g_fapi_fapi2mac_p7_proc.h"
29 #include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
30
31  /** @ingroup group_source_api_p7_fapi2mac_proc
32  *
33  *  @param[in]  p_phy_ctx Pointer to PHY Context.
34  *  @param[in]  p_phy_rx_data_ind Pointer to FAPI RX_DATA.indication message structure.
35  *  
36  *  @return     Returns ::SUCCESS and ::FAILURE.
37  *
38  *  @description
39  *  This message includes RX_DATA to be sent to L2.
40  *
41 **/
42 uint8_t nr5g_fapi_rx_data_indication(
43     bool is_urllc,
44     p_nr5g_fapi_phy_ctx_t p_phy_ctx,
45     p_fapi_api_stored_vendor_queue_elems vendor_extension_elems,
46     PRXULSCHIndicationStruct p_phy_rx_ulsch_ind)
47 {
48     uint8_t phy_id;
49     fapi_rx_data_indication_t *p_fapi_rx_data_ind;
50     p_fapi_api_queue_elem_t p_list_elem;
51     p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
52     nr5g_fapi_stats_t *p_stats;
53
54     if (NULL == p_phy_ctx) {
55         NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] Invalid "
56                 "Phy Context"));
57         return FAILURE;
58     }
59
60     if (NULL == p_phy_rx_ulsch_ind) {
61         NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] Invalid "
62                 "RX_USLCH indication"));
63         return FAILURE;
64     }
65
66     phy_id = p_phy_rx_ulsch_ind->sSFN_Slot.nCarrierIdx;
67     p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
68     if (p_phy_instance->phy_id != phy_id) {
69         NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] Invalid "
70                 "handle to phy instance"));
71         return FAILURE;
72     }
73
74     p_stats = &p_phy_instance->stats;
75     p_stats->iapi_stats.iapi_rx_data_ind++;
76
77     p_list_elem =
78         nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_RX_DATA_INDICATION, 1,
79         sizeof(fapi_rx_data_indication_t));
80
81     if (!p_list_elem) {
82         NR5G_FAPI_LOG(ERROR_LOG,
83             ("[NR5G_FAPI][RX_DATA.indication] Unable to create "
84                 "list element. Out of memory!!!"));
85         return FAILURE;
86     }
87
88     p_fapi_rx_data_ind = (fapi_rx_data_indication_t *) (p_list_elem + 1);
89     p_fapi_rx_data_ind->header.msg_id = FAPI_RX_DATA_INDICATION;
90     p_fapi_rx_data_ind->header.length =
91         (uint16_t) sizeof(fapi_rx_data_indication_t);
92
93     fapi_vendor_p7_ind_msg_t* p_fapi_vend_p7 =
94         nr5g_fapi_proc_vendor_p7_msg_get(vendor_extension_elems, phy_id);
95     fapi_vendor_ext_rx_data_ind_t* p_fapi_vend_rx_data_ind =
96         p_fapi_vend_p7 ? &p_fapi_vend_p7->rx_data_ind : NULL;
97         
98     if (p_fapi_vend_rx_data_ind) {
99         p_fapi_vend_rx_data_ind->carrier_idx = phy_id;
100         p_fapi_vend_rx_data_ind->sym = p_phy_rx_ulsch_ind->sSFN_Slot.nSym;
101     }
102
103     if (nr5g_fapi_rx_data_indication_to_fapi_translation(is_urllc, p_phy_instance,
104             p_phy_rx_ulsch_ind, p_fapi_rx_data_ind)) {
105         NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] L1 to FAPI "
106                 "translation failed"));
107         return FAILURE;
108     }
109
110     nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem, is_urllc);
111
112     p_stats->fapi_stats.fapi_rx_data_ind++;
113     NR5G_FAPI_LOG(DEBUG_LOG, ("[RX_DATA.indication][%u][%u,%u,%u] is_urllc %u",
114             p_phy_instance->phy_id,
115         p_phy_rx_ulsch_ind->sSFN_Slot.nSFN, p_phy_rx_ulsch_ind->sSFN_Slot.nSlot,
116         p_phy_rx_ulsch_ind->sSFN_Slot.nSym, is_urllc));
117
118     return SUCCESS;
119 }
120
121  /** @ingroup group_source_api_p7_fapi2mac_proc
122  *
123  *  @param[in]   ue_id  Variable holding ue_id received in RX_DATA.Indication..
124  *  @param[in]   p_ul_slot_info Pointer to ul slot info structure that stores the 
125  *               UL_TTI.request PDU info.
126  *  
127  *  @return     Returns Pointer to pusch info, if handle of p_ul_slot_info matches ue_id.
128                         NULL, if handle of p_ul_slot_info not matches ue_id
129  *
130  *  @description
131  *  This function retrieves the pusch info stored during corresponding UL_TTI.request processing.  
132  *  based on ue_id.
133  *
134 **/
135 nr5g_fapi_pusch_info_t *nr5g_fapi_get_pusch_info(
136     uint16_t ue_id,
137     nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
138 {
139     uint8_t i, num_ulsch;
140
141     nr5g_fapi_pusch_info_t *p_pusch_info;
142
143     num_ulsch = p_ul_slot_info->num_ulsch;
144     for (i = 0; i < num_ulsch; i++) {
145         p_pusch_info = &p_ul_slot_info->pusch_info[i];
146         if (p_pusch_info->handle == ue_id) {
147             return p_pusch_info;
148         }
149     }
150     return NULL;
151 }
152
153  /** @ingroup group_source_api_p7_fapi2mac_proc
154  *
155  *  @param[in]   p_phy_instance Pointer to PHY instance.
156  *  @param[in]   p_phy_rx_ulsch_ind Pointer to IAPI RX_ULSCH.indication structure.
157  *  @param[out]  p_fapi_rx_data_ind Pointer to FAPI RX_DATA.indication structure.
158  *  
159  *  @return     Returns ::SUCCESS and ::FAILURE.
160  *
161  *  @description
162  *  This function converts IAPI RX_DATA.indication to FAPI CRC.indication
163  *  structure.
164  *
165 **/
166 uint8_t nr5g_fapi_rx_data_indication_to_fapi_translation(
167     bool is_urllc,
168     p_nr5g_fapi_phy_instance_t p_phy_instance,
169     PRXULSCHIndicationStruct p_phy_rx_ulsch_ind,
170     fapi_rx_data_indication_t * p_fapi_rx_data_ind)
171 {
172     uint8_t num_ulsch, i;
173     uint8_t symbol_no;
174     uint16_t slot_no, frame_no;
175
176     nr5g_fapi_pusch_info_t *p_pusch_info;
177     fapi_pdu_ind_info_t *p_fapi_pdu_ind_info;
178     nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
179     nr5g_fapi_stats_t *p_stats;
180     ULSCHPDUDataStruct *p_rx_ulsch_pdu_data;
181
182     p_stats = &p_phy_instance->stats;
183
184     frame_no = p_fapi_rx_data_ind->sfn = p_phy_rx_ulsch_ind->sSFN_Slot.nSFN;
185     slot_no = p_fapi_rx_data_ind->slot = p_phy_rx_ulsch_ind->sSFN_Slot.nSlot;
186     symbol_no = p_phy_rx_ulsch_ind->sSFN_Slot.nSym;
187
188     p_ul_slot_info =
189         nr5g_fapi_get_ul_slot_info(is_urllc, frame_no, slot_no, symbol_no, p_phy_instance);
190
191     if (p_ul_slot_info == NULL) {
192         NR5G_FAPI_LOG(ERROR_LOG,
193             ("[NR5G_FAPI] [RX_DATA.indication] No Valid data available "
194                 "for frame :%d and slot: %d", frame_no, slot_no));
195         return FAILURE;
196     }
197
198     num_ulsch = p_fapi_rx_data_ind->numPdus = p_phy_rx_ulsch_ind->nUlsch;
199     for (i = 0; i < num_ulsch; i++) {
200         p_stats->iapi_stats.iapi_rx_data_ind_pdus++;
201         p_fapi_pdu_ind_info = &p_fapi_rx_data_ind->pdus[i];
202         p_rx_ulsch_pdu_data = &p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i];
203         p_pusch_info =
204             nr5g_fapi_get_pusch_info(p_rx_ulsch_pdu_data->nUEId,
205             p_ul_slot_info);
206         if (p_pusch_info == NULL) {
207             NR5G_FAPI_LOG(ERROR_LOG,
208                 ("[NR5G_FAPI] [RX_DATA.indication] No Valid data available "
209                     "nUEId:%d, frame_no:%d, slot_no:%d, urllc %u",
210                     p_rx_ulsch_pdu_data->nUEId, frame_no, slot_no, is_urllc));
211             return FAILURE;
212         }
213
214         p_fapi_pdu_ind_info->handle = p_pusch_info->handle;
215         p_fapi_pdu_ind_info->rnti = p_rx_ulsch_pdu_data->nRNTI;
216         // upper nibble of pdu_length is passed in upper nibble in harqId (which only takes up to 4 bits)
217         // this way, pdu_length has 20-bits (up to 1048576)
218         p_fapi_pdu_ind_info->harqId = ((p_rx_ulsch_pdu_data->nPduLen & 0x000F0000) >> 12) | (p_pusch_info->harq_process_id & 0x0F);
219         p_fapi_pdu_ind_info->ul_cqi = p_pusch_info->ul_cqi;
220         p_fapi_pdu_ind_info->timingAdvance = p_pusch_info->timing_advance;
221         p_fapi_pdu_ind_info->rssi = 880;
222         p_fapi_pdu_ind_info->pdu_length = 0xFFFF & p_rx_ulsch_pdu_data->nPduLen;
223         p_fapi_pdu_ind_info->pduData = (void *)p_rx_ulsch_pdu_data->pPayload;
224
225         p_stats->fapi_stats.fapi_rx_data_ind_pdus++;
226     }
227     return SUCCESS;
228 }