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