* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fapi_5g / source / framework / workers / nr5g_fapi_mac2phy_thread.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 #include "nr5g_fapi_std.h"
19 #include "nr5g_fapi_mac2phy_thread.h"
20 #include "nr5g_fapi_fapi2mac_wls.h"
21 #include "nr5g_fapi_fapi2phy_api.h"
22 #include "nr5g_fapi_fapi2phy_p5_proc.h"
23 #include "nr5g_fapi_fapi2phy_p7_proc.h"
24 #include "nr5g_fapi_log.h"
25
26 //------------------------------------------------------------------------------
27 /** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
28  *
29  *  @param[in,out]   void
30  *
31  *  @return none
32  *
33  *  @description
34  *  DOXYGEN_TO_DO
35  *
36 **/
37 //------------------------------------------------------------------------------
38 void *nr5g_fapi_mac2phy_thread_func(
39     void *config)
40 {
41     p_fapi_api_queue_elem_t p_msg_list = NULL;
42     p_nr5g_fapi_phy_ctx_t p_phy_ctx = (p_nr5g_fapi_phy_ctx_t) config;
43     uint64_t start_tick;
44
45     NR5G_FAPI_LOG(INFO_LOG, ("[MAC2PHY] Thread %s launched LWP:%ld on "
46             "Core: %d\n", __func__, pthread_self(),
47             p_phy_ctx->mac2phy_worker_core_id));
48
49     nr5g_fapi_init_thread(p_phy_ctx->mac2phy_worker_core_id);
50
51     while (!p_phy_ctx->process_exit) {
52         p_msg_list = nr5g_fapi_fapi2mac_wls_recv();
53         if (p_msg_list)
54             nr5g_fapi_mac2phy_api_recv_handler(false, config, p_msg_list);
55
56         start_tick = __rdtsc();
57         NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] Send to PHY.."));
58         nr5g_fapi_fapi2phy_send_api_list(0);
59         tick_total_wls_send_per_tti_dl += __rdtsc() - start_tick;
60     }
61     pthread_exit(NULL);
62 }
63
64 //------------------------------------------------------------------------------
65 /** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
66  *
67  *  @param[in,out]   void
68  *
69  *  @return none
70  *
71  *  @description
72  *  DOXYGEN_TO_DO
73  *
74 **/
75 //------------------------------------------------------------------------------
76 void nr5g_fapi_mac2phy_api_recv_handler(
77     bool is_urllc,
78     void *config,
79     p_fapi_api_queue_elem_t p_msg_list)
80 {
81     p_fapi_api_queue_elem_t p_per_carr_api_list = NULL;
82     p_fapi_api_queue_elem_t p_prev_elm = NULL;
83     fapi_msg_t *p_fapi_msg = NULL;
84     p_fapi_msg_header_t p_fapi_msg_header = NULL;
85
86     p_nr5g_fapi_phy_ctx_t p_phy_ctx = NULL;
87     p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
88     uint8_t num_apis = 0;
89     uint8_t phy_id = 0;
90     uint64_t start_tick = __rdtsc();
91
92     NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] %s:", __func__));
93     p_phy_ctx = (p_nr5g_fapi_phy_ctx_t) config;
94     while (p_msg_list) {
95         p_per_carr_api_list = p_msg_list;
96         p_fapi_msg_header = (fapi_msg_header_t *) (p_per_carr_api_list + 1);
97         num_apis = p_fapi_msg_header->num_msg;
98         phy_id = p_fapi_msg_header->handle;
99
100         if (num_apis > 0 && p_msg_list->p_next) {   // likely
101             p_per_carr_api_list = p_per_carr_api_list->p_next;
102             p_msg_list = p_per_carr_api_list;
103             NR5G_FAPI_LOG(TRACE_LOG, ("\n[MAC2PHY] PHY_ID: %d NUM APIs: %d\n",
104                     phy_id, num_apis));
105         } else {                // unlikely
106             // skip to next carrier list. since current fapi message hearder
107             // has no apis
108             if (p_msg_list->p_next) {
109                 NR5G_FAPI_LOG(TRACE_LOG, ("\n[MAC2PHY] No APIs for PHY_ID: %d."
110                         " Skip...\n", phy_id));
111                 p_msg_list = p_msg_list->p_next;
112                 continue;
113             } else {
114                 NR5G_FAPI_LOG(ERROR_LOG, ("\n[MAC2PHY] PHY_ID: %d NUM APIs: %d\n",
115                         phy_id, num_apis));
116                 return;
117             }
118         }
119
120         // walk through the list and disconnet per carrier apis
121         if (p_msg_list->p_next) {
122             p_prev_elm = p_msg_list;
123             while (p_msg_list) {
124                 if (FAPI_VENDOR_MSG_HEADER_IND == p_msg_list->msg_type) {
125                     p_prev_elm->p_next = NULL;
126                     break;
127                 }
128                 p_prev_elm = p_msg_list;
129                 p_msg_list = p_msg_list->p_next;
130             }
131         } else {
132             p_msg_list = NULL;
133         }
134
135         if (phy_id > FAPI_MAX_PHY_INSTANCES) {
136             NR5G_FAPI_LOG(ERROR_LOG, ("[MAC2PHY]: Invalid Phy Id: %d\n",
137                     phy_id));
138             continue;
139         }
140
141         if (p_per_carr_api_list) {
142             p_fapi_msg = (fapi_msg_t *) (p_per_carr_api_list + 1);
143 #ifdef DEBUG_MODE
144             if ((p_fapi_msg->msg_id != FAPI_VENDOR_EXT_UL_IQ_SAMPLES) &&
145                 (p_fapi_msg->msg_id != FAPI_VENDOR_EXT_ADD_REMOVE_CORE)) {
146 #endif
147                 p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
148                 if (FAPI_STATE_IDLE == p_phy_instance->state) {
149                     if (p_fapi_msg->msg_id != FAPI_CONFIG_REQUEST) {
150                         NR5G_FAPI_LOG(ERROR_LOG,
151                             ("CONFIG.request is not received "
152                                 "for %d PHY Instance\n", phy_id));
153                         continue;
154                     }
155                     p_phy_instance->phy_id = phy_id;
156                 }
157 #ifdef DEBUG_MODE
158             }
159 #endif
160
161             nr5g_fapi_mac2phy_api_processing_handler(is_urllc, p_phy_instance,
162                 p_per_carr_api_list);
163             p_per_carr_api_list = NULL;
164         }
165     }
166     tick_total_parse_per_tti_dl += __rdtsc() - start_tick;
167 }
168
169 //------------------------------------------------------------------------------
170 /** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
171  *
172  *  @param[in,out]   void
173  *
174  *  @return none
175  *
176  *  @description
177  *  DOXYGEN_TO_DO
178  *
179 **/
180 //------------------------------------------------------------------------------
181 void nr5g_fapi_mac2phy_api_processing_handler(
182     bool is_urllc,
183     p_nr5g_fapi_phy_instance_t p_phy_instance,
184     p_fapi_api_queue_elem_t p_msg_list)
185 {
186     uint16_t msg_type;
187     p_fapi_api_queue_elem_t p_vendor_elm = NULL;
188     p_fapi_api_queue_elem_t p_prev_elm = NULL;
189     p_fapi_api_queue_elem_t p_curr_elm = NULL;
190     p_fapi_api_queue_elem_t p_tx_data_elm = NULL;
191     p_fapi_api_queue_elem_t p_tx_data_pdu_list = NULL;
192     p_fapi_api_queue_elem_t p_tx_data_pdu_list_tail = NULL;
193     fapi_msg_t *p_fapi_msg = NULL;
194     fapi_vendor_msg_t *p_vendor_msg = NULL;
195
196     // Get vendor body if present
197     p_prev_elm = p_vendor_elm = p_msg_list;
198     while (p_vendor_elm) {
199         p_fapi_msg = (fapi_msg_t *) (p_vendor_elm + 1);
200         if (p_fapi_msg->msg_id == FAPI_VENDOR_MESSAGE) {
201             if (p_prev_elm == p_vendor_elm) {
202                 NR5G_FAPI_LOG(ERROR_LOG,
203                     ("[MAC2PHY] Received only Vendor Message"));
204                 return;
205             }
206             p_vendor_msg = (fapi_vendor_msg_t *) p_fapi_msg;
207             NR5G_FAPI_LOG(DEBUG_LOG, ("[MAC2PHY] P7 Vendor Msg: %p",
208                     p_vendor_msg));
209             // disconnect the vendor element from the api list
210             p_prev_elm->p_next = NULL;
211             break;
212         }
213         p_prev_elm = p_vendor_elm;
214         p_vendor_elm = p_vendor_elm->p_next;
215     }
216
217     // split the tx_data_request pdus
218     p_curr_elm = p_msg_list;
219     while (p_curr_elm) {
220         msg_type = p_curr_elm->msg_type;
221         if (msg_type == FAPI_TX_DATA_REQUEST) {
222             p_tx_data_elm = p_curr_elm;
223         } else if (msg_type == FAPI_VENDOR_MSG_PHY_ZBC_BLOCK_REQ) {
224             if (p_tx_data_pdu_list) {
225                 p_tx_data_pdu_list_tail->p_next = p_curr_elm;
226                 p_tx_data_pdu_list_tail = p_tx_data_pdu_list_tail->p_next;
227             } else {
228                 p_tx_data_pdu_list_tail = p_tx_data_pdu_list = p_curr_elm;
229             }
230         } else {
231         }
232         p_curr_elm = p_curr_elm->p_next;
233     }
234
235     if (p_tx_data_pdu_list && p_tx_data_elm) {
236         p_tx_data_elm->p_tx_data_elm_list = p_tx_data_pdu_list;
237         p_tx_data_elm->p_next = NULL;
238     }
239
240     if (FAILURE == nr5g_fapi_check_api_ordering(p_phy_instance, p_msg_list)) {
241         NR5G_FAPI_LOG(ERROR_LOG, ("API Ordering is wrong."));
242         return;
243     }
244     // Walk through the API list
245     while (p_msg_list) {
246         p_fapi_msg = (fapi_msg_t *) (p_msg_list + 1);
247         switch (p_fapi_msg->msg_id) {
248                 /*  P5 Vendor Message Processing */
249 #ifdef DEBUG_MODE
250             case FAPI_VENDOR_EXT_ADD_REMOVE_CORE:
251                 nr5g_fapi_add_remove_core_message(is_urllc,
252                     (fapi_vendor_ext_add_remove_core_msg_t *) p_fapi_msg);
253                 break;
254             case FAPI_VENDOR_EXT_UL_IQ_SAMPLES:
255                 nr5g_fapi_ul_iq_samples_request(is_urllc,
256                     (fapi_vendor_ext_iq_samples_req_t *) p_fapi_msg);
257                 break;
258
259             case FAPI_VENDOR_EXT_DL_IQ_SAMPLES:
260                 nr5g_fapi_dl_iq_samples_request(is_urllc,
261                     (fapi_vendor_ext_iq_samples_req_t *) p_fapi_msg);
262                 break;
263
264 #endif
265             case FAPI_VENDOR_EXT_SHUTDOWN_REQUEST:
266                 {
267                     nr5g_fapi_shutdown_request(is_urllc, p_phy_instance,
268                         (fapi_vendor_ext_shutdown_req_t *) p_fapi_msg);
269                     nr5g_fapi_statistic_info_print();
270                     if (g_statistic_start_flag == 1)
271                         g_statistic_start_flag = 0;
272                 }
273                 break;
274
275                 /*  P5 Message Processing */
276
277             case FAPI_PARAM_REQUEST:
278                 {
279                     nr5g_fapi_param_response(p_phy_instance);
280                 }
281
282                 break;
283
284             case FAPI_CONFIG_REQUEST:
285                 {
286                     nr5g_fapi_config_request(is_urllc, p_phy_instance,
287                         (fapi_config_req_t *)
288                         p_fapi_msg, p_vendor_msg);
289                     nr5g_fapi_statistic_info_init();
290                 }
291
292                 break;
293
294             case FAPI_START_REQUEST:
295                 nr5g_fapi_start_request(is_urllc, p_phy_instance, (fapi_start_req_t *)
296                     p_fapi_msg, p_vendor_msg);
297                 break;
298
299             case FAPI_STOP_REQUEST:
300                 {
301                     nr5g_fapi_stop_request(is_urllc, p_phy_instance, (fapi_stop_req_t *)
302                         p_fapi_msg, p_vendor_msg);
303                     nr5g_fapi_statistic_info_print();
304                     if (g_statistic_start_flag == 1)
305                         g_statistic_start_flag = 0;
306                 }
307
308                 break;
309                 /*  P7 Message Processing */
310             case FAPI_DL_TTI_REQUEST:
311                 {
312                     nr5g_fapi_dl_tti_request(is_urllc, p_phy_instance,
313                         (fapi_dl_tti_req_t *)
314                         p_fapi_msg, p_vendor_msg);
315                     if (g_statistic_start_flag == 0)
316                         g_statistic_start_flag = 1;
317                 }
318                 break;
319
320             case FAPI_UL_TTI_REQUEST:
321                 nr5g_fapi_ul_tti_request(is_urllc, p_phy_instance, (fapi_ul_tti_req_t *)
322                     p_fapi_msg, p_vendor_msg);
323                 break;
324
325             case FAPI_UL_DCI_REQUEST:
326                 nr5g_fapi_ul_dci_request(is_urllc, p_phy_instance, (fapi_ul_dci_req_t *)
327                     p_fapi_msg, p_vendor_msg);
328                 break;
329
330             case FAPI_TX_DATA_REQUEST:
331                 nr5g_fapi_tx_data_request(is_urllc, p_phy_instance, (fapi_tx_data_req_t *)
332                     p_fapi_msg, p_vendor_msg);
333                 p_msg_list->p_tx_data_elm_list = NULL;
334                 break;
335
336             default:
337                 NR5G_FAPI_LOG(ERROR_LOG, ("[MAC2PHY THREAD] Received Unknown Message: [msg_id = 0x%x]",
338                     p_fapi_msg->msg_id));
339                 break;
340         }
341         p_msg_list = p_msg_list->p_next;
342     }
343 }
344
345 uint8_t nr5g_fapi_check_api_ordering(
346     p_nr5g_fapi_phy_instance_t p_phy_instance,
347     p_fapi_api_queue_elem_t p_msg_list)
348 {
349     uint16_t msg_id, api_order_check = FAPI_CONFIG_REQUEST;
350     p_fapi_api_queue_elem_t p_msg = p_msg_list;
351     fapi_msg_t *p_fapi_msg = NULL;
352
353     if (p_phy_instance && p_phy_instance->state == FAPI_STATE_RUNNING) {
354         p_fapi_msg = (fapi_msg_t *) (p_msg + 1);
355         msg_id = p_fapi_msg->msg_id;
356         // check if first msg is CONFIG.req
357         if (msg_id == FAPI_CONFIG_REQUEST) {
358             p_msg = p_msg->p_next;
359         }
360         api_order_check = FAPI_DL_TTI_REQUEST;
361         // Continue checking remaining APIs
362         while (p_msg) {
363             p_fapi_msg = (fapi_msg_t *) (p_msg + 1);
364             msg_id = p_fapi_msg->msg_id;
365             if ((msg_id == FAPI_DL_TTI_REQUEST) && (msg_id == api_order_check)) {
366                 api_order_check = FAPI_UL_TTI_REQUEST;
367             } else if ((msg_id == FAPI_UL_TTI_REQUEST) &&
368                 (msg_id == api_order_check)) {
369                 api_order_check = FAPI_UL_DCI_REQUEST;
370             } else {
371                 break;
372             }
373             p_msg = p_msg->p_next;
374         }
375         if (api_order_check != FAPI_UL_DCI_REQUEST) {
376             return FAILURE;
377         }
378     }
379
380     return SUCCESS;
381 }