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