1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /**
8 * @brief File containing event specific definitions in the
9 * Radio test mode for the FMAC IF Layer of the Wi-Fi driver.
10 */
11
12 #include "queue.h"
13 #include "radio_test/phy_rf_params.h"
14 #include "host_rpu_umac_if.h"
15 #include "radio_test/fmac_structs.h"
16 #include "common/hal_mem.h"
17 #include "common/fmac_util.h"
18
umac_event_rt_stats_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * event)19 static enum nrf_wifi_status umac_event_rt_stats_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
20 void *event)
21 {
22 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
23 struct nrf_wifi_rt_umac_event_stats *stats = NULL;
24
25 if (!event) {
26 nrf_wifi_osal_log_err("%s: Invalid parameters",
27 __func__);
28 goto out;
29 }
30
31 if (!fmac_dev_ctx->stats_req) {
32 nrf_wifi_osal_log_err("%s: Stats recd when req was not sent!",
33 __func__);
34 goto out;
35 }
36
37 stats = ((struct nrf_wifi_rt_umac_event_stats *)event);
38
39 nrf_wifi_osal_mem_cpy(fmac_dev_ctx->fw_stats,
40 &stats->fw,
41 sizeof(*fmac_dev_ctx->fw_stats));
42
43 fmac_dev_ctx->stats_req = false;
44
45 status = NRF_WIFI_STATUS_SUCCESS;
46
47 out:
48 return status;
49 }
50
51
umac_event_rt_rf_test_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * event)52 static enum nrf_wifi_status umac_event_rt_rf_test_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
53 void *event)
54 {
55 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
56 struct nrf_wifi_event_rftest *rf_test_event = NULL;
57 struct nrf_wifi_temperature_params rf_test_get_temperature;
58 struct nrf_wifi_rf_get_rf_rssi rf_get_rf_rssi;
59 struct nrf_wifi_rf_test_xo_calib xo_calib_params;
60 struct nrf_wifi_rf_get_xo_value rf_get_xo_value_params;
61 struct nrf_wifi_rt_fmac_dev_ctx *def_dev_ctx;
62 struct nrf_wifi_rf_test_capture_params rf_test_capture_params;
63
64 def_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
65
66 if (!event) {
67 nrf_wifi_osal_log_err("%s: Invalid parameters",
68 __func__);
69 goto out;
70 }
71
72 rf_test_event = ((struct nrf_wifi_event_rftest *)event);
73
74 if (rf_test_event->rf_test_info.rfevent[0] != def_dev_ctx->rf_test_type) {
75 nrf_wifi_osal_log_err("%s: Invalid event type (%d) recd for RF test type (%d)",
76 __func__,
77 rf_test_event->rf_test_info.rfevent[0],
78 def_dev_ctx->rf_test_type);
79 goto out;
80 }
81
82 switch (rf_test_event->rf_test_info.rfevent[0]) {
83 case NRF_WIFI_RF_TEST_EVENT_RX_ADC_CAP:
84 case NRF_WIFI_RF_TEST_EVENT_RX_STAT_PKT_CAP:
85 case NRF_WIFI_RF_TEST_EVENT_RX_DYN_PKT_CAP:
86 status = hal_rpu_mem_read(fmac_dev_ctx->hal_dev_ctx,
87 def_dev_ctx->rf_test_cap_data,
88 RPU_MEM_RF_TEST_CAP_BASE,
89 def_dev_ctx->rf_test_cap_sz);
90
91 nrf_wifi_osal_mem_cpy(&rf_test_capture_params,
92 (const unsigned char *)&rf_test_event->rf_test_info.rfevent[0],
93 sizeof(rf_test_capture_params));
94
95 def_dev_ctx->capture_status = rf_test_capture_params.capture_status;
96
97 break;
98 case NRF_WIFI_RF_TEST_EVENT_TX_TONE_START:
99 case NRF_WIFI_RF_TEST_EVENT_DPD_ENABLE:
100 break;
101
102 case NRF_WIFI_RF_TEST_GET_TEMPERATURE:
103 nrf_wifi_osal_mem_cpy(&rf_test_get_temperature,
104 (const unsigned char *)&rf_test_event->rf_test_info.rfevent[0],
105 sizeof(rf_test_get_temperature));
106
107 if (rf_test_get_temperature.readTemperatureStatus) {
108 nrf_wifi_osal_log_err("Temperature reading failed");
109 } else {
110 nrf_wifi_osal_log_info("The temperature is = %d degree celsius",
111 rf_test_get_temperature.temperature);
112 }
113 break;
114 case NRF_WIFI_RF_TEST_EVENT_RF_RSSI:
115 nrf_wifi_osal_mem_cpy(&rf_get_rf_rssi,
116 (const unsigned char *)&rf_test_event->rf_test_info.rfevent[0],
117 sizeof(rf_get_rf_rssi));
118
119 nrf_wifi_osal_log_info("RF RSSI value is = %d",
120 rf_get_rf_rssi.agc_status_val);
121 break;
122 case NRF_WIFI_RF_TEST_EVENT_XO_CALIB:
123 nrf_wifi_osal_mem_cpy(&xo_calib_params,
124 (const unsigned char *)&rf_test_event->rf_test_info.rfevent[0],
125 sizeof(xo_calib_params));
126
127 nrf_wifi_osal_log_info("XO value configured is = %d",
128 xo_calib_params.xo_val);
129 break;
130 case NRF_WIFI_RF_TEST_XO_TUNE:
131 nrf_wifi_osal_mem_cpy(&rf_get_xo_value_params,
132 (const unsigned char *)&rf_test_event->rf_test_info.rfevent[0],
133 sizeof(rf_get_xo_value_params));
134
135 nrf_wifi_osal_log_info("Best XO value is = %d",
136 rf_get_xo_value_params.xo_value);
137 break;
138 default:
139 break;
140 }
141
142 def_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
143 status = NRF_WIFI_STATUS_SUCCESS;
144
145 out:
146 return status;
147 }
148
149
umac_event_rt_proc_events(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct host_rpu_msg * rpu_msg)150 static enum nrf_wifi_status umac_event_rt_proc_events(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
151 struct host_rpu_msg *rpu_msg)
152 {
153 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
154 unsigned char *sys_head = NULL;
155
156 struct nrf_wifi_rt_fmac_dev_ctx *def_dev_ctx_rt;
157 struct nrf_wifi_umac_event_err_status *umac_status;
158
159 if (!fmac_dev_ctx || !rpu_msg) {
160 return status;
161 }
162
163
164 def_dev_ctx_rt = wifi_dev_priv(fmac_dev_ctx);
165 sys_head = (unsigned char *)rpu_msg->msg;
166
167 switch (((struct nrf_wifi_sys_head *)sys_head)->cmd_event) {
168 case NRF_WIFI_EVENT_STATS:
169 status = umac_event_rt_stats_process(fmac_dev_ctx,
170 sys_head);
171 break;
172 case NRF_WIFI_EVENT_INIT_DONE:
173 fmac_dev_ctx->fw_init_done = 1;
174 status = NRF_WIFI_STATUS_SUCCESS;
175 break;
176 case NRF_WIFI_EVENT_DEINIT_DONE:
177 fmac_dev_ctx->fw_deinit_done = 1;
178 status = NRF_WIFI_STATUS_SUCCESS;
179 break;
180 case NRF_WIFI_EVENT_RF_TEST:
181 status = umac_event_rt_rf_test_process(fmac_dev_ctx,
182 sys_head);
183 break;
184 case NRF_WIFI_EVENT_RADIOCMD_STATUS:
185 umac_status = ((struct nrf_wifi_umac_event_err_status *)sys_head);
186 def_dev_ctx_rt->radio_cmd_status = umac_status->status;
187 def_dev_ctx_rt->radio_cmd_done = true;
188 status = NRF_WIFI_STATUS_SUCCESS;
189 break;
190 default:
191 nrf_wifi_osal_log_err("%s: Unknown event recd: %d",
192 __func__,
193 ((struct nrf_wifi_sys_head *)sys_head)->cmd_event);
194 break;
195 }
196 return status;
197 }
198
199
umac_event_ctrl_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * event_data,unsigned int event_len)200 static enum nrf_wifi_status umac_event_ctrl_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
201 void *event_data,
202 unsigned int event_len)
203 {
204 enum nrf_wifi_status status = NRF_WIFI_STATUS_SUCCESS;
205 struct nrf_wifi_umac_hdr *umac_hdr = NULL;
206 struct nrf_wifi_reg *get_reg_event = NULL;
207 struct nrf_wifi_event_regulatory_change *reg_change_event = NULL;
208 unsigned char if_id = 0;
209 unsigned int event_num = 0;
210
211 if (!fmac_dev_ctx || !event_data) {
212 nrf_wifi_osal_log_err("%s: Invalid parameters",
213 __func__);
214 goto out;
215 }
216
217 umac_hdr = event_data;
218 if_id = umac_hdr->ids.wdev_id;
219 event_num = umac_hdr->cmd_evnt;
220
221 if (if_id >= MAX_NUM_VIFS) {
222 nrf_wifi_osal_log_err("%s: Invalid wdev_id recd from UMAC %d",
223 __func__,
224 if_id);
225
226 goto out;
227 }
228
229 #ifdef NRF_WIFI_CMD_EVENT_LOG
230 nrf_wifi_osal_log_info("%s: Event %d received from UMAC\n",
231 __func__,
232 event_num);
233 #else
234 nrf_wifi_osal_log_dbg("%s: Event %d received from UMAC",
235 __func__,
236 event_num);
237 #endif /* NRF_WIFI_CMD_EVENT_LOG */
238
239 switch (umac_hdr->cmd_evnt) {
240 case NRF_WIFI_UMAC_EVENT_GET_REG:
241 get_reg_event = (struct nrf_wifi_reg *)event_data;
242
243 nrf_wifi_osal_mem_cpy(&fmac_dev_ctx->alpha2,
244 &get_reg_event->nrf_wifi_alpha2,
245 sizeof(get_reg_event->nrf_wifi_alpha2));
246 fmac_dev_ctx->alpha2_valid = true;
247 break;
248 case NRF_WIFI_UMAC_EVENT_REG_CHANGE:
249 reg_change_event = (struct nrf_wifi_event_regulatory_change *)event_data;
250
251 fmac_dev_ctx->reg_change = nrf_wifi_osal_mem_zalloc(sizeof(*reg_change_event));
252
253 if (!fmac_dev_ctx->reg_change) {
254 nrf_wifi_osal_log_err("%s: Failed to allocate memory for reg_change",
255 __func__);
256 goto out;
257 }
258
259 nrf_wifi_osal_mem_cpy(fmac_dev_ctx->reg_change,
260 reg_change_event,
261 sizeof(*reg_change_event));
262 fmac_dev_ctx->reg_set_status = true;
263 break;
264 default:
265 nrf_wifi_osal_log_dbg("%s: No callback registered for event %d",
266 __func__,
267 umac_hdr->cmd_evnt);
268 break;
269 }
270
271 nrf_wifi_osal_log_dbg("%s: Event %d processed",
272 __func__,
273 event_num);
274
275 out:
276 return status;
277 }
278
279
nrf_wifi_rt_fmac_event_callback(void * mac_dev_ctx,void * rpu_event_data,unsigned int rpu_event_len)280 enum nrf_wifi_status nrf_wifi_rt_fmac_event_callback(void *mac_dev_ctx,
281 void *rpu_event_data,
282 unsigned int rpu_event_len)
283 {
284 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
285 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
286 struct host_rpu_msg *rpu_msg = NULL;
287 struct nrf_wifi_umac_hdr *umac_hdr = NULL;
288 unsigned int umac_msg_len = 0;
289 int umac_msg_type = NRF_WIFI_UMAC_EVENT_UNSPECIFIED;
290
291 fmac_dev_ctx = (struct nrf_wifi_fmac_dev_ctx *)mac_dev_ctx;
292
293 rpu_msg = (struct host_rpu_msg *)rpu_event_data;
294 umac_hdr = (struct nrf_wifi_umac_hdr *)rpu_msg->msg;
295 umac_msg_len = rpu_msg->hdr.len;
296 umac_msg_type = umac_hdr->cmd_evnt;
297
298 #ifdef NRF_WIFI_CMD_EVENT_LOG
299 nrf_wifi_osal_log_info("%s: Event type %d recd\n",
300 __func__,
301 rpu_msg->type);
302 #else
303 nrf_wifi_osal_log_dbg("%s: Event type %d recd",
304 __func__,
305 rpu_msg->type);
306 #endif /* NRF_WIFI_CMD_EVENT_LOG */
307
308 switch (rpu_msg->type) {
309 case NRF_WIFI_HOST_RPU_MSG_TYPE_UMAC:
310 status = umac_event_ctrl_process(fmac_dev_ctx,
311 rpu_msg->msg,
312 rpu_msg->hdr.len);
313
314 if (status != NRF_WIFI_STATUS_SUCCESS) {
315 nrf_wifi_osal_log_err("%s: umac_event_ctrl_process failed",
316 __func__);
317 goto out;
318 }
319 break;
320 case NRF_WIFI_HOST_RPU_MSG_TYPE_SYSTEM:
321 status = umac_event_rt_proc_events(fmac_dev_ctx,
322 rpu_msg);
323 break;
324 default:
325 goto out;
326 }
327
328 out:
329 return status;
330 }
331
332