xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c (revision 27d564647e9b50e713c60b0d7e5ea2a9b0a3ae74)
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 #include <cdp_txrx_cmn.h>
35 
36 static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle,
37 							uint8_t *event,
38 							uint32_t data_len)
39 {
40 	int err_code;
41 	struct wlan_objmgr_psoc *psoc;
42 	struct target_psoc_info *tgt_hdl;
43 	wmi_legacy_service_ready_callback legacy_callback;
44 	struct common_wmi_handle *wmi_handle;
45 	QDF_STATUS ret_val;
46 
47 	if (!scn_handle) {
48 		target_if_err("scn handle NULL in service ready handler");
49 		return -EINVAL;
50 	}
51 
52 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
53 	if (!psoc) {
54 		target_if_err("psoc is null in service ready handler");
55 		return -EINVAL;
56 	}
57 
58 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
59 						psoc);
60 	if (!tgt_hdl) {
61 		target_if_err("target_psoc_info is null in service ready ev");
62 		return -EINVAL;
63 	}
64 
65 	ret_val = target_if_sw_version_check(psoc, tgt_hdl, event);
66 
67 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
68 
69 	err_code = init_deinit_populate_service_bitmap(wmi_handle, event,
70 			tgt_hdl->info.service_bitmap);
71 	if (err_code)
72 		goto exit;
73 
74 	err_code = init_deinit_populate_fw_version_cmd(wmi_handle, event);
75 	if (err_code)
76 		goto exit;
77 
78 	err_code = init_deinit_populate_target_cap(wmi_handle, event,
79 				   &(tgt_hdl->info.target_caps));
80 	if (err_code)
81 		goto exit;
82 
83 	err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle, event,
84 				    &(tgt_hdl->info), true);
85 	if (err_code)
86 		goto exit;
87 
88 	if (init_deinit_validate_160_80p80_fw_caps(psoc, tgt_hdl) !=
89 			QDF_STATUS_SUCCESS) {
90 		wlan_psoc_nif_op_flag_set(psoc, WLAN_SOC_OP_VHT_INVALID_CAP);
91 	}
92 
93 	target_if_ext_res_cfg_enable(psoc, tgt_hdl, event);
94 
95 	if (wmi_service_enabled(wmi_handle, wmi_service_tt))
96 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TT_SUPPORT);
97 
98 	if (wmi_service_enabled(wmi_handle, wmi_service_widebw_scan))
99 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN);
100 
101 	if (wmi_service_enabled(wmi_handle, wmi_service_check_cal_version))
102 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_SW_CAL);
103 
104 	if (wmi_service_enabled(wmi_handle, wmi_service_twt_requestor))
105 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TWT_REQUESTER);
106 
107 	if (wmi_service_enabled(wmi_handle, wmi_service_twt_responder))
108 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TWT_RESPONDER);
109 
110 	if (wmi_service_enabled(wmi_handle, wmi_service_bss_color_offload))
111 		target_if_debug(" BSS COLOR OFFLOAD supported");
112 
113 	target_if_debug(" TT support %d, Wide BW Scan %d, SW cal %d",
114 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_TT_SUPPORT),
115 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN),
116 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_SW_CAL));
117 
118 	target_if_mesh_support_enable(psoc, tgt_hdl, event);
119 
120 	target_if_eapol_minrate_enable(psoc, tgt_hdl, event);
121 
122 	target_if_smart_antenna_enable(psoc, tgt_hdl, event);
123 
124 	target_if_peer_cfg_enable(psoc, tgt_hdl, event);
125 
126 	target_if_atf_cfg_enable(psoc, tgt_hdl, event);
127 
128 	target_if_qwrap_cfg_enable(psoc, tgt_hdl, event);
129 
130 	target_if_lteu_cfg_enable(psoc, tgt_hdl, event);
131 
132 	/* override derived value, if it exceeds max peer count */
133 	if ((wlan_psoc_get_max_peer_count(psoc) >
134 		tgt_hdl->info.wlan_res_cfg.num_active_peers) &&
135 		(wlan_psoc_get_max_peer_count(psoc) <
136 			(tgt_hdl->info.wlan_res_cfg.num_peers -
137 				tgt_hdl->info.wlan_res_cfg.num_vdevs))) {
138 		tgt_hdl->info.wlan_res_cfg.num_peers =
139 				wlan_psoc_get_max_peer_count(psoc) +
140 					tgt_hdl->info.wlan_res_cfg.num_vdevs;
141 	}
142 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
143 	if (!legacy_callback) {
144 		err_code = -EINVAL;
145 		goto exit;
146 	}
147 
148 	err_code = legacy_callback(wmi_service_ready_event_id,
149 				  scn_handle, event, data_len);
150 	init_deinit_chainmask_config(psoc, tgt_hdl);
151 
152 	if (wmi_service_enabled(wmi_handle, wmi_service_mgmt_tx_wmi)) {
153 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WMI_MGMT_REF);
154 		target_if_debug("WMI mgmt service enabled");
155 	} else {
156 		wlan_psoc_nif_fw_ext_cap_clear(psoc,
157 					       WLAN_SOC_CEXT_WMI_MGMT_REF);
158 		target_if_debug("WMI mgmt service disabled");
159 	}
160 
161 	err_code = init_deinit_handle_host_mem_req(psoc, tgt_hdl, event);
162 	if (err_code != QDF_STATUS_SUCCESS)
163 		goto exit;
164 
165 	target_if_reg_set_offloaded_info(psoc);
166 	if (!wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) {
167 		target_if_debug("No EXT message, send init command");
168 		tgt_hdl->info.wmi_service_ready = TRUE;
169 		target_psoc_set_num_radios(tgt_hdl, 1);
170 		/* send init command */
171 		init_deinit_prepare_send_init_cmd(psoc, tgt_hdl);
172 	} else {
173 		target_if_debug("Wait for EXT message");
174 	}
175 
176 	target_if_smart_log_enable(psoc, tgt_hdl, event);
177 exit:
178 	return err_code;
179 }
180 
181 static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle,
182 						uint8_t *event,
183 						uint32_t data_len)
184 {
185 	int err_code;
186 	struct wlan_objmgr_psoc *psoc;
187 	struct target_psoc_info *tgt_hdl;
188 	struct common_wmi_handle *wmi_handle;
189 	struct tgt_info *info;
190 	wmi_legacy_service_ready_callback legacy_callback;
191 
192 	if (!scn_handle) {
193 		target_if_err("scn handle NULL in service ready handler");
194 		return -EINVAL;
195 	}
196 
197 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
198 	if (!psoc) {
199 		target_if_err("psoc is null in service ready handler");
200 		return -EINVAL;
201 	}
202 
203 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
204 						psoc);
205 	if (!tgt_hdl) {
206 		target_if_err("target_psoc_info is null in service ready ev");
207 		return -EINVAL;
208 	}
209 
210 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
211 	info = (&tgt_hdl->info);
212 
213 	err_code = init_deinit_populate_service_ready_ext_param(wmi_handle,
214 				event, &(info->service_ext_param));
215 	if (err_code)
216 		goto exit;
217 
218 	target_psoc_set_num_radios(tgt_hdl, 0);
219 	err_code =  init_deinit_populate_hw_mode_capability(wmi_handle,
220 					    event, tgt_hdl);
221 	if (err_code)
222 		goto exit;
223 
224 	if (init_deinit_is_preferred_hw_mode_supported(psoc, tgt_hdl)
225 			== FALSE)
226 		return -EINVAL;
227 
228 	target_if_print_service_ready_ext_param(psoc, tgt_hdl);
229 
230 	err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle,
231 					   event, info, false);
232 	if (err_code)
233 		goto exit;
234 
235 	target_if_add_11ax_modes(psoc, tgt_hdl);
236 
237 	if (init_deinit_chainmask_table_alloc(
238 				&(info->service_ext_param)) ==
239 							QDF_STATUS_SUCCESS) {
240 		err_code = init_deinit_populate_chainmask_tables(wmi_handle,
241 				event,
242 				&(info->service_ext_param.chainmask_table[0]));
243 		if (err_code)
244 			goto exit;
245 	}
246 
247 	err_code = init_deinit_populate_dbr_ring_cap(psoc, wmi_handle,
248 						event, info);
249 	if (err_code)
250 		goto exit;
251 
252 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
253 	if (legacy_callback)
254 		legacy_callback(wmi_service_ready_ext_event_id,
255 				scn_handle, event, data_len);
256 
257 	info->wlan_res_cfg.num_vdevs = (target_psoc_get_num_radios(tgt_hdl) *
258 					info->wlan_res_cfg.num_vdevs);
259 	info->wlan_res_cfg.beacon_tx_offload_max_vdev =
260 				(target_psoc_get_num_radios(tgt_hdl) *
261 				info->wlan_res_cfg.beacon_tx_offload_max_vdev);
262 	info->wlan_res_cfg.max_bssid_indicator =
263 				info->service_ext_param.max_bssid_indicator;
264 
265 	info->wmi_service_ready = TRUE;
266 
267 	init_deinit_prepare_send_init_cmd(psoc, tgt_hdl);
268 
269 exit:
270 	return err_code;
271 }
272 
273 static int init_deinit_service_available_handler(ol_scn_t scn_handle,
274 						uint8_t *event,
275 						uint32_t data_len)
276 {
277 	struct wlan_objmgr_psoc *psoc;
278 	struct target_psoc_info *tgt_hdl;
279 	struct common_wmi_handle *wmi_handle;
280 
281 	if (!scn_handle) {
282 		target_if_err("scn handle NULL");
283 		return -EINVAL;
284 	}
285 
286 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
287 	if (!psoc) {
288 		target_if_err("psoc is null");
289 		return -EINVAL;
290 	}
291 
292 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
293 						psoc);
294 	if (!tgt_hdl) {
295 		target_if_err("target_psoc_info is null");
296 		return -EINVAL;
297 	}
298 
299 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
300 
301 	if (wmi_save_ext_service_bitmap(wmi_handle, event, NULL) !=
302 					QDF_STATUS_SUCCESS) {
303 		target_if_err("Failed to save ext service bitmap");
304 		return -EINVAL;
305 	}
306 
307 	return 0;
308 }
309 
310 /* MAC address fourth byte index */
311 #define MAC_BYTE_4 4
312 
313 static int init_deinit_ready_event_handler(ol_scn_t scn_handle,
314 						uint8_t *event,
315 						uint32_t data_len)
316 {
317 	struct wlan_objmgr_psoc *psoc;
318 	struct wlan_objmgr_pdev *pdev;
319 	struct target_psoc_info *tgt_hdl;
320 	struct common_wmi_handle *wmi_handle;
321 	struct wmi_host_fw_abi_ver fw_ver;
322 	uint8_t myaddr[QDF_MAC_ADDR_SIZE];
323 	struct tgt_info *info;
324 	struct wmi_host_ready_ev_param ready_ev;
325 	wmi_legacy_service_ready_callback legacy_callback;
326 	uint8_t num_radios, i;
327 	uint32_t max_peers;
328 	target_resource_config *tgt_cfg;
329 
330 	if (!scn_handle) {
331 		target_if_err("scn handle NULL");
332 		return -EINVAL;
333 	}
334 
335 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
336 	if (!psoc) {
337 		target_if_err("psoc is null");
338 		return -EINVAL;
339 	}
340 
341 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
342 						psoc);
343 	if (!tgt_hdl) {
344 		target_if_err("target_psoc_info is null");
345 		return -EINVAL;
346 	}
347 
348 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
349 	info = (&tgt_hdl->info);
350 
351 	if (wmi_extract_fw_abi_version(wmi_handle, event, &fw_ver) ==
352 				QDF_STATUS_SUCCESS) {
353 		info->version.wlan_ver = fw_ver.sw_version;
354 		info->version.wlan_ver = fw_ver.abi_version;
355 	}
356 
357 	if (wmi_check_and_update_fw_version(wmi_handle, event) < 0) {
358 		target_if_err("Version mismatch with FW");
359 		return -EINVAL;
360 	}
361 
362 	if (wmi_extract_ready_event_params(wmi_handle, event, &ready_ev) !=
363 				QDF_STATUS_SUCCESS) {
364 		target_if_err("Failed to extract ready event");
365 		return -EINVAL;
366 	}
367 
368 	if ((ready_ev.num_total_peer != 0) &&
369 	    (info->wlan_res_cfg.num_peers != ready_ev.num_total_peer)) {
370 		/* FW allocated number of peers is different than host
371 		 * requested. Update host max with FW reported value.
372 		 */
373 		target_if_err("Host Requested %d peers. FW Supports %d peers",
374 			       info->wlan_res_cfg.num_peers,
375 			       ready_ev.num_total_peer);
376 		info->wlan_res_cfg.num_peers = ready_ev.num_total_peer;
377 	}
378 
379 	/* for non legacy  num_total_peer will be non zero
380 	 * allocate peer memory in this case
381 	 */
382 	if (ready_ev.num_total_peer != 0) {
383 		tgt_cfg = &info->wlan_res_cfg;
384 		max_peers = tgt_cfg->num_peers + ready_ev.num_extra_peer + 1;
385 
386 		cdp_peer_map_attach(wlan_psoc_get_dp_handle(psoc), max_peers,
387 				    tgt_cfg->peer_map_unmap_v2);
388 	}
389 
390 	/* Indicate to the waiting thread that the ready
391 	 * event was received
392 	 */
393 	info->wlan_init_status = wmi_ready_extract_init_status(
394 						wmi_handle, event);
395 
396 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
397 	if (legacy_callback)
398 		legacy_callback(wmi_ready_event_id,
399 				scn_handle, event, data_len);
400 
401 	num_radios = target_psoc_get_num_radios(tgt_hdl);
402 	/*
403 	 * For non-legacy HW, MAC addr list is extracted.
404 	 */
405 	if (num_radios > 1) {
406 		uint8_t num_mac_addr;
407 		wmi_host_mac_addr *addr_list;
408 		int i;
409 
410 		addr_list = wmi_ready_extract_mac_addr_list(wmi_handle, event,
411 							    &num_mac_addr);
412 		if ((num_mac_addr >= num_radios) && (addr_list)) {
413 			for (i = 0; i < num_radios; i++) {
414 				WMI_HOST_MAC_ADDR_TO_CHAR_ARRAY(&addr_list[i],
415 								myaddr);
416 				pdev = wlan_objmgr_get_pdev_by_id(psoc, i,
417 								  WLAN_INIT_DEINIT_ID);
418 				if (!pdev) {
419 					target_if_err(" PDEV %d is NULL", i);
420 					return -EINVAL;
421 				}
422 				wlan_pdev_set_hw_macaddr(pdev, myaddr);
423 				wlan_objmgr_pdev_release_ref(pdev,
424 							WLAN_INIT_DEINIT_ID);
425 
426 				/* assign 1st radio addr to psoc */
427 				if (i == 0)
428 					wlan_psoc_set_hw_macaddr(psoc, myaddr);
429 			}
430 			goto out;
431 		} else {
432 			target_if_err("Using default MAC addr for all radios..");
433 		}
434 	}
435 
436 	/*
437 	 * We extract single MAC address in two scenarios:
438 	 * 1. In non-legacy case, if addr list is NULL or num_mac_addr < num_radios
439 	 * 2. In all legacy cases
440 	 */
441 	for (i = 0; i < num_radios; i++) {
442 		wmi_ready_extract_mac_addr(wmi_handle, event, myaddr);
443 		myaddr[MAC_BYTE_4] += i;
444 		pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_INIT_DEINIT_ID);
445 		if (!pdev) {
446 			target_if_err(" PDEV %d is NULL", i);
447 			return -EINVAL;
448 		}
449 		wlan_pdev_set_hw_macaddr(pdev, myaddr);
450 		wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID);
451 		/* assign 1st radio addr to psoc */
452 		if (i == 0)
453 			wlan_psoc_set_hw_macaddr(psoc, myaddr);
454 	}
455 
456 out:
457 	target_if_btcoex_cfg_enable(psoc, tgt_hdl, event);
458 	tgt_hdl->info.wmi_ready = TRUE;
459 	init_deinit_wakeup_host_wait(psoc, tgt_hdl);
460 
461 	return 0;
462 }
463 
464 
465 QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers(
466 				struct wlan_objmgr_psoc *psoc)
467 {
468 	struct target_psoc_info *tgt_hdl;
469 	wmi_unified_t wmi_handle;
470 	QDF_STATUS retval = QDF_STATUS_SUCCESS;
471 
472 	if (!psoc) {
473 		target_if_err("psoc is null in register wmi handler");
474 		return QDF_STATUS_E_FAILURE;
475 	}
476 
477 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
478 						psoc);
479 	if (!tgt_hdl) {
480 		target_if_err("target_psoc_info null in register wmi hadler");
481 		return QDF_STATUS_E_FAILURE;
482 	}
483 
484 	wmi_handle = (wmi_unified_t)target_psoc_get_wmi_hdl(tgt_hdl);
485 
486 	retval = wmi_unified_register_event_handler(wmi_handle,
487 				wmi_service_ready_event_id,
488 				init_deinit_service_ready_event_handler,
489 				WMI_RX_WORK_CTX);
490 	retval = wmi_unified_register_event_handler(wmi_handle,
491 				wmi_service_ready_ext_event_id,
492 				init_deinit_service_ext_ready_event_handler,
493 				WMI_RX_WORK_CTX);
494 	retval = wmi_unified_register_event_handler(wmi_handle,
495 				wmi_service_available_event_id,
496 				init_deinit_service_available_handler,
497 				WMI_RX_UMAC_CTX);
498 	retval = wmi_unified_register_event_handler(wmi_handle,
499 				wmi_ready_event_id,
500 				init_deinit_ready_event_handler,
501 				WMI_RX_WORK_CTX);
502 
503 	return retval;
504 }
505 
506