xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
1 /*
2  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: init_event_handler.c
21  *
22  * WMI common event handler implementation source file
23  */
24 
25 #include <qdf_status.h>
26 #include <wlan_objmgr_psoc_obj.h>
27 #include <wlan_objmgr_pdev_obj.h>
28 #include <target_if.h>
29 #include <target_if_reg.h>
30 #include <init_event_handler.h>
31 #include <service_ready_util.h>
32 #include <service_ready_param.h>
33 #include <init_cmd_api.h>
34 
35 static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle,
36 							uint8_t *event,
37 							uint32_t data_len)
38 {
39 	int err_code;
40 	struct wlan_objmgr_psoc *psoc;
41 	struct target_psoc_info *tgt_hdl;
42 	wmi_legacy_service_ready_callback legacy_callback;
43 	void *wmi_handle;
44 	QDF_STATUS ret_val;
45 
46 	if (!scn_handle) {
47 		target_if_err("scn handle NULL in service ready handler");
48 		return -EINVAL;
49 	}
50 
51 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
52 	if (!psoc) {
53 		target_if_err("psoc is null in service ready handler");
54 		return -EINVAL;
55 	}
56 
57 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
58 						psoc);
59 	if (!tgt_hdl) {
60 		target_if_err("target_psoc_info is null in service ready ev");
61 		return -EINVAL;
62 	}
63 
64 	ret_val = target_if_sw_version_check(psoc, tgt_hdl, event);
65 
66 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
67 
68 	err_code = init_deinit_populate_service_bitmap(wmi_handle, event,
69 			tgt_hdl->info.service_bitmap);
70 	if (err_code)
71 		goto exit;
72 
73 	err_code = init_deinit_populate_fw_version_cmd(wmi_handle, event);
74 	if (err_code)
75 		goto exit;
76 
77 	err_code = init_deinit_populate_target_cap(wmi_handle, event,
78 				   &(tgt_hdl->info.target_caps));
79 	if (err_code)
80 		goto exit;
81 
82 	err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle, event,
83 				    &(tgt_hdl->info), true);
84 	if (err_code)
85 		goto exit;
86 
87 	if (init_deinit_validate_160_80p80_fw_caps(psoc, tgt_hdl) !=
88 			QDF_STATUS_SUCCESS) {
89 		wlan_psoc_nif_op_flag_set(psoc, WLAN_SOC_OP_VHT_INVALID_CAP);
90 	}
91 
92 	target_if_ext_res_cfg_enable(psoc, tgt_hdl, event);
93 
94 	if (wmi_service_enabled(wmi_handle, wmi_service_tt))
95 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TT_SUPPORT);
96 
97 	if (wmi_service_enabled(wmi_handle, wmi_service_widebw_scan))
98 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN);
99 
100 	if (wmi_service_enabled(wmi_handle, wmi_service_check_cal_version))
101 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_SW_CAL);
102 
103 	target_if_info(" TT support %d, Wide BW Scan %d, SW cal %d",
104 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_TT_SUPPORT),
105 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN),
106 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_SW_CAL));
107 
108 	target_if_mesh_support_enable(psoc, tgt_hdl, event);
109 
110 	target_if_smart_antenna_enable(psoc, tgt_hdl, event);
111 
112 	target_if_peer_cfg_enable(psoc, tgt_hdl, event);
113 
114 	target_if_atf_cfg_enable(psoc, tgt_hdl, event);
115 
116 	target_if_qwrap_cfg_enable(psoc, tgt_hdl, event);
117 
118 	target_if_lteu_cfg_enable(psoc, tgt_hdl, event);
119 
120 	/* override derived value, if it exceeds max peer count */
121 	if ((wlan_psoc_get_max_peer_count(psoc) >
122 		tgt_hdl->info.wlan_res_cfg.num_active_peers) &&
123 		(wlan_psoc_get_max_peer_count(psoc) <
124 			(tgt_hdl->info.wlan_res_cfg.num_peers -
125 				tgt_hdl->info.wlan_res_cfg.num_vdevs))) {
126 		tgt_hdl->info.wlan_res_cfg.num_peers =
127 				wlan_psoc_get_max_peer_count(psoc) +
128 					tgt_hdl->info.wlan_res_cfg.num_vdevs;
129 	}
130 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
131 	if (!legacy_callback) {
132 		err_code = -EINVAL;
133 		goto exit;
134 	}
135 
136 	err_code = legacy_callback(wmi_service_ready_event_id,
137 				  scn_handle, event, data_len);
138 	init_deinit_chainmask_config(psoc, tgt_hdl);
139 
140 	if (wmi_service_enabled(wmi_handle, wmi_service_mgmt_tx_wmi)) {
141 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WMI_MGMT_REF);
142 		target_if_info("WMI mgmt service enabled");
143 	} else {
144 		wlan_psoc_nif_fw_ext_cap_clear(psoc,
145 					       WLAN_SOC_CEXT_WMI_MGMT_REF);
146 		target_if_info("WMI mgmt service disabled");
147 	}
148 
149 	err_code = init_deinit_handle_host_mem_req(psoc, tgt_hdl, event);
150 	if (err_code != QDF_STATUS_SUCCESS)
151 		goto exit;
152 
153 	target_if_reg_set_offloaded_info(psoc);
154 	if (!wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) {
155 		target_if_info("No EXT message, send init command");
156 		tgt_hdl->info.wmi_service_ready = TRUE;
157 		target_psoc_set_num_radios(tgt_hdl, 1);
158 		/* send init command */
159 		init_deinit_prepare_send_init_cmd(psoc, tgt_hdl);
160 	} else {
161 		target_if_info("Wait for EXT message");
162 	}
163 
164 exit:
165 	return err_code;
166 }
167 
168 static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle,
169 						uint8_t *event,
170 						uint32_t data_len)
171 {
172 	int err_code;
173 	struct wlan_objmgr_psoc *psoc;
174 	struct target_psoc_info *tgt_hdl;
175 	void *wmi_handle;
176 	struct tgt_info *info;
177 	wmi_legacy_service_ready_callback legacy_callback;
178 
179 	if (!scn_handle) {
180 		target_if_err("scn handle NULL in service ready handler");
181 		return -EINVAL;
182 	}
183 
184 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
185 	if (!psoc) {
186 		target_if_err("psoc is null in service ready handler");
187 		return -EINVAL;
188 	}
189 
190 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
191 						psoc);
192 	if (!tgt_hdl) {
193 		target_if_err("target_psoc_info is null in service ready ev");
194 		return -EINVAL;
195 	}
196 
197 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
198 	info = (&tgt_hdl->info);
199 
200 	err_code = init_deinit_populate_service_ready_ext_param(wmi_handle,
201 				event, &(info->service_ext_param));
202 	if (err_code)
203 		goto exit;
204 
205 	target_psoc_set_num_radios(tgt_hdl, 0);
206 	err_code =  init_deinit_populate_hw_mode_capability(wmi_handle,
207 					    event, tgt_hdl);
208 	if (err_code)
209 		goto exit;
210 
211 	if (init_deinit_is_preferred_hw_mode_supported(psoc, tgt_hdl)
212 			== FALSE)
213 		return -EINVAL;
214 
215 	target_if_print_service_ready_ext_param(psoc, tgt_hdl);
216 
217 	err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle,
218 					   event, info, false);
219 	if (err_code)
220 		goto exit;
221 
222 	target_if_add_11ax_modes(psoc, tgt_hdl);
223 
224 	if (init_deinit_chainmask_table_alloc(
225 				&(info->service_ext_param)) ==
226 							QDF_STATUS_SUCCESS) {
227 		err_code = init_deinit_populate_chainmask_tables(wmi_handle,
228 				event,
229 				&(info->service_ext_param.chainmask_table[0]));
230 		if (err_code)
231 			goto exit;
232 	}
233 
234 	err_code = init_deinit_populate_dbr_ring_cap(psoc, wmi_handle,
235 						event, info);
236 	if (err_code)
237 		goto exit;
238 
239 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
240 	if (legacy_callback)
241 		legacy_callback(wmi_service_ready_ext_event_id,
242 				scn_handle, event, data_len);
243 
244 	info->wlan_res_cfg.num_vdevs = (target_psoc_get_num_radios(tgt_hdl) *
245 					info->wlan_res_cfg.num_vdevs);
246 	info->wlan_res_cfg.beacon_tx_offload_max_vdev =
247 				(target_psoc_get_num_radios(tgt_hdl) *
248 				info->wlan_res_cfg.beacon_tx_offload_max_vdev);
249 
250 	info->wmi_service_ready = TRUE;
251 
252 	init_deinit_prepare_send_init_cmd(psoc, tgt_hdl);
253 
254 exit:
255 	return err_code;
256 }
257 
258 static int init_deinit_service_available_handler(ol_scn_t scn_handle,
259 						uint8_t *event,
260 						uint32_t data_len)
261 {
262 	struct wlan_objmgr_psoc *psoc;
263 	struct target_psoc_info *tgt_hdl;
264 	void *wmi_handle;
265 
266 	if (!scn_handle) {
267 		target_if_err("scn handle NULL");
268 		return -EINVAL;
269 	}
270 
271 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
272 	if (!psoc) {
273 		target_if_err("psoc is null");
274 		return -EINVAL;
275 	}
276 
277 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
278 						psoc);
279 	if (!tgt_hdl) {
280 		target_if_err("target_psoc_info is null");
281 		return -EINVAL;
282 	}
283 
284 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
285 
286 	if (wmi_save_ext_service_bitmap(wmi_handle, event, NULL) !=
287 					QDF_STATUS_SUCCESS) {
288 		target_if_err("Failed to save ext service bitmap");
289 		return -EINVAL;
290 	}
291 
292 	return 0;
293 }
294 
295 /* MAC address fourth byte index */
296 #define MAC_BYTE_4 4
297 
298 static int init_deinit_ready_event_handler(ol_scn_t scn_handle,
299 						uint8_t *event,
300 						uint32_t data_len)
301 {
302 	struct wlan_objmgr_psoc *psoc;
303 	struct wlan_objmgr_pdev *pdev;
304 	struct target_psoc_info *tgt_hdl;
305 	void *wmi_handle;
306 	struct wmi_host_fw_abi_ver fw_ver;
307 	uint8_t myaddr[QDF_MAC_ADDR_SIZE];
308 	struct tgt_info *info;
309 	struct wmi_host_ready_ev_param ready_ev;
310 	wmi_legacy_service_ready_callback legacy_callback;
311 	uint8_t num_radios, i;
312 
313 	if (!scn_handle) {
314 		target_if_err("scn handle NULL");
315 		return -EINVAL;
316 	}
317 
318 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
319 	if (!psoc) {
320 		target_if_err("psoc is null");
321 		return -EINVAL;
322 	}
323 
324 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
325 						psoc);
326 	if (!tgt_hdl) {
327 		target_if_err("target_psoc_info is null");
328 		return -EINVAL;
329 	}
330 
331 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
332 	info = (&tgt_hdl->info);
333 
334 	if (wmi_extract_fw_abi_version(wmi_handle, event, &fw_ver) ==
335 				QDF_STATUS_SUCCESS) {
336 		info->version.wlan_ver = fw_ver.sw_version;
337 		info->version.wlan_ver = fw_ver.abi_version;
338 	}
339 
340 	if (wmi_check_and_update_fw_version(wmi_handle, event) < 0) {
341 		target_if_err("Version mismatch with FW");
342 		return -EINVAL;
343 	}
344 
345 	if (wmi_extract_ready_event_params(wmi_handle, event, &ready_ev) !=
346 				QDF_STATUS_SUCCESS) {
347 		target_if_err("Failed to extract ready event");
348 		return -EINVAL;
349 	}
350 
351 	if ((ready_ev.num_total_peer != 0) &&
352 	    (info->wlan_res_cfg.num_peers != ready_ev.num_total_peer)) {
353 		/* FW allocated number of peers is different than host
354 		 * requested. Update host max with FW reported value.
355 		 */
356 		target_if_info("Host Requested %d peers. FW Supports %d peers",
357 			       info->wlan_res_cfg.num_peers,
358 			       ready_ev.num_total_peer);
359 		info->wlan_res_cfg.num_peers = ready_ev.num_total_peer;
360 	}
361 
362 	/* Indicate to the waiting thread that the ready
363 	 * event was received
364 	 */
365 	info->wlan_init_status = wmi_ready_extract_init_status(
366 						wmi_handle, event);
367 
368 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
369 	if (legacy_callback)
370 		legacy_callback(wmi_ready_event_id,
371 				scn_handle, event, data_len);
372 
373 	num_radios = target_psoc_get_num_radios(tgt_hdl);
374 	/*
375 	 * For non-legacy HW, MAC addr list is extracted.
376 	 */
377 	if (num_radios > 1) {
378 		uint8_t num_mac_addr;
379 		wmi_host_mac_addr *addr_list;
380 		int i;
381 
382 		addr_list = wmi_ready_extract_mac_addr_list(wmi_handle, event,
383 							    &num_mac_addr);
384 		if ((num_mac_addr >= num_radios) && (addr_list)) {
385 			for (i = 0; i < num_radios; i++) {
386 				WMI_HOST_MAC_ADDR_TO_CHAR_ARRAY(&addr_list[i],
387 								myaddr);
388 				pdev = wlan_objmgr_get_pdev_by_id(psoc, i,
389 								  WLAN_INIT_DEINIT_ID);
390 				if (!pdev) {
391 					target_if_err(" PDEV %d is NULL", i);
392 					return -EINVAL;
393 				}
394 				wlan_pdev_set_hw_macaddr(pdev, myaddr);
395 				wlan_objmgr_pdev_release_ref(pdev,
396 							WLAN_INIT_DEINIT_ID);
397 
398 				/* assign 1st radio addr to psoc */
399 				if (i == 0)
400 					wlan_psoc_set_hw_macaddr(psoc, myaddr);
401 			}
402 			goto out;
403 		} else {
404 			target_if_err("Using default MAC addr for all radios..");
405 		}
406 	}
407 
408 	/*
409 	 * We extract single MAC address in two scenarios:
410 	 * 1. In non-legacy case, if addr list is NULL or num_mac_addr < num_radios
411 	 * 2. In all legacy cases
412 	 */
413 	for (i = 0; i < num_radios; i++) {
414 		wmi_ready_extract_mac_addr(wmi_handle, event, myaddr);
415 		myaddr[MAC_BYTE_4] += i;
416 		pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_INIT_DEINIT_ID);
417 		if (!pdev) {
418 			target_if_err(" PDEV %d is NULL", i);
419 			return -EINVAL;
420 		}
421 		wlan_pdev_set_hw_macaddr(pdev, myaddr);
422 		wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID);
423 		/* assign 1st radio addr to psoc */
424 		if (i == 0)
425 			wlan_psoc_set_hw_macaddr(psoc, myaddr);
426 	}
427 
428 out:
429 	target_if_btcoex_cfg_enable(psoc, tgt_hdl, event);
430 	tgt_hdl->info.wmi_ready = TRUE;
431 	init_deinit_wakeup_host_wait(psoc, tgt_hdl);
432 
433 	return 0;
434 }
435 
436 
437 QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers(
438 				struct wlan_objmgr_psoc *psoc)
439 {
440 	struct target_psoc_info *tgt_hdl;
441 	void *wmi_handle;
442 	QDF_STATUS retval = QDF_STATUS_SUCCESS;
443 
444 	if (!psoc) {
445 		target_if_err("psoc is null in register wmi handler");
446 		return QDF_STATUS_E_FAILURE;
447 	}
448 
449 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
450 						psoc);
451 	if (!tgt_hdl) {
452 		target_if_err("target_psoc_info null in register wmi hadler");
453 		return QDF_STATUS_E_FAILURE;
454 	}
455 
456 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
457 
458 	retval = wmi_unified_register_event_handler(wmi_handle,
459 				wmi_service_ready_event_id,
460 				init_deinit_service_ready_event_handler,
461 				WMI_RX_WORK_CTX);
462 	retval = wmi_unified_register_event_handler(wmi_handle,
463 				wmi_service_ready_ext_event_id,
464 				init_deinit_service_ext_ready_event_handler,
465 				WMI_RX_WORK_CTX);
466 	retval = wmi_unified_register_event_handler(wmi_handle,
467 				wmi_service_available_event_id,
468 				init_deinit_service_available_handler,
469 				WMI_RX_UMAC_CTX);
470 	retval = wmi_unified_register_event_handler(wmi_handle,
471 				wmi_ready_event_id,
472 				init_deinit_ready_event_handler,
473 				WMI_RX_WORK_CTX);
474 
475 	return retval;
476 }
477 
478