xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
1 /*
2  * Copyright (c) 2018-2019 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 	if (wmi_service_enabled(wmi_handle, wmi_service_ul_ru26_allowed))
114 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_OBSS_NBW_RU);
115 
116 	if (wmi_service_enabled(wmi_handle, wmi_service_infra_mbssid))
117 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_MBSS_IE);
118 
119 	target_if_debug(" TT support %d, Wide BW Scan %d, SW cal %d",
120 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_TT_SUPPORT),
121 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN),
122 		wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_SW_CAL));
123 
124 	target_if_mesh_support_enable(psoc, tgt_hdl, event);
125 
126 	target_if_eapol_minrate_enable(psoc, tgt_hdl, event);
127 
128 	target_if_smart_antenna_enable(psoc, tgt_hdl, event);
129 
130 	target_if_cfr_support_enable(psoc, tgt_hdl, event);
131 
132 	target_if_peer_cfg_enable(psoc, tgt_hdl, event);
133 
134 	target_if_atf_cfg_enable(psoc, tgt_hdl, event);
135 
136 	if (!wmi_service_enabled(wmi_handle, wmi_service_ext_msg))
137 		target_if_qwrap_cfg_enable(psoc, tgt_hdl, event);
138 
139 	target_if_lteu_cfg_enable(psoc, tgt_hdl, event);
140 
141 	/* override derived value, if it exceeds max peer count */
142 	if ((wlan_psoc_get_max_peer_count(psoc) >
143 		tgt_hdl->info.wlan_res_cfg.num_active_peers) &&
144 		(wlan_psoc_get_max_peer_count(psoc) <
145 			(tgt_hdl->info.wlan_res_cfg.num_peers -
146 				tgt_hdl->info.wlan_res_cfg.num_vdevs))) {
147 		tgt_hdl->info.wlan_res_cfg.num_peers =
148 				wlan_psoc_get_max_peer_count(psoc) +
149 					tgt_hdl->info.wlan_res_cfg.num_vdevs;
150 	}
151 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
152 	if (!legacy_callback) {
153 		err_code = -EINVAL;
154 		goto exit;
155 	}
156 
157 	err_code = legacy_callback(wmi_service_ready_event_id,
158 				  scn_handle, event, data_len);
159 	init_deinit_chainmask_config(psoc, tgt_hdl);
160 
161 	if (wmi_service_enabled(wmi_handle, wmi_service_mgmt_tx_wmi)) {
162 		wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WMI_MGMT_REF);
163 		target_if_debug("WMI mgmt service enabled");
164 	} else {
165 		wlan_psoc_nif_fw_ext_cap_clear(psoc,
166 					       WLAN_SOC_CEXT_WMI_MGMT_REF);
167 		target_if_debug("WMI mgmt service disabled");
168 	}
169 
170 	err_code = init_deinit_handle_host_mem_req(psoc, tgt_hdl, event);
171 	if (err_code != QDF_STATUS_SUCCESS)
172 		goto exit;
173 
174 	target_if_reg_set_offloaded_info(psoc);
175 	if (!wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) {
176 		target_if_debug("No EXT message, send init command");
177 		tgt_hdl->info.wmi_service_ready = TRUE;
178 		target_psoc_set_num_radios(tgt_hdl, 1);
179 		/* send init command */
180 		init_deinit_prepare_send_init_cmd(psoc, tgt_hdl);
181 	} else {
182 		target_if_debug("Wait for EXT message");
183 	}
184 
185 exit:
186 	return err_code;
187 }
188 
189 static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle,
190 						uint8_t *event,
191 						uint32_t data_len)
192 {
193 	int err_code;
194 	struct wlan_objmgr_psoc *psoc;
195 	struct target_psoc_info *tgt_hdl;
196 	struct common_wmi_handle *wmi_handle;
197 	struct tgt_info *info;
198 	wmi_legacy_service_ready_callback legacy_callback;
199 
200 	if (!scn_handle) {
201 		target_if_err("scn handle NULL in service ready handler");
202 		return -EINVAL;
203 	}
204 
205 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
206 	if (!psoc) {
207 		target_if_err("psoc is null in service ready handler");
208 		return -EINVAL;
209 	}
210 
211 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
212 						psoc);
213 	if (!tgt_hdl) {
214 		target_if_err("target_psoc_info is null in service ready ev");
215 		return -EINVAL;
216 	}
217 
218 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
219 	info = (&tgt_hdl->info);
220 
221 	err_code = init_deinit_populate_service_ready_ext_param(wmi_handle,
222 				event, &(info->service_ext_param));
223 	if (err_code)
224 		goto exit;
225 
226 	target_psoc_set_num_radios(tgt_hdl, 0);
227 	err_code =  init_deinit_populate_hw_mode_capability(wmi_handle,
228 					    event, tgt_hdl);
229 	if (err_code)
230 		goto exit;
231 
232 	if (init_deinit_is_preferred_hw_mode_supported(psoc, tgt_hdl)
233 			== FALSE) {
234 		target_if_err("Preferred mode %d not supported",
235 			      info->preferred_hw_mode);
236 		return -EINVAL;
237 	}
238 
239 	if (info->preferred_hw_mode != WMI_HOST_HW_MODE_MAX) {
240 		struct wlan_psoc_host_hw_mode_caps *hw_cap = &info->hw_mode_cap;
241 		/* prune info mac_phy cap to preferred/selected mode caps */
242 		info->total_mac_phy_cnt = 0;
243 		err_code = init_deinit_populate_mac_phy_capability(wmi_handle,
244 								   event,
245 								   hw_cap,
246 								   info);
247 		if (err_code)
248 			goto exit;
249 
250 		info->num_radios = info->total_mac_phy_cnt;
251 		target_if_debug("num radios is %d\n", info->num_radios);
252 	}
253 
254 	target_if_print_service_ready_ext_param(psoc, tgt_hdl);
255 
256 	err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle,
257 					   event, info, false);
258 	if (err_code)
259 		goto exit;
260 
261 	target_if_add_11ax_modes(psoc, tgt_hdl);
262 
263 	if (init_deinit_chainmask_table_alloc(
264 				&(info->service_ext_param)) ==
265 							QDF_STATUS_SUCCESS) {
266 		err_code = init_deinit_populate_chainmask_tables(wmi_handle,
267 				event,
268 				&(info->service_ext_param.chainmask_table[0]));
269 		if (err_code)
270 			goto exit;
271 	}
272 
273 	err_code = init_deinit_populate_dbr_ring_cap(psoc, wmi_handle,
274 						event, info);
275 	if (err_code)
276 		goto exit;
277 
278 	err_code = init_deinit_populate_spectral_bin_scale_params(psoc,
279 								  wmi_handle,
280 								  event, info);
281 	if (err_code)
282 		goto exit;
283 
284 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
285 	if (legacy_callback)
286 		legacy_callback(wmi_service_ready_ext_event_id,
287 				scn_handle, event, data_len);
288 
289 	target_if_qwrap_cfg_enable(psoc, tgt_hdl, event);
290 
291 	target_if_set_twt_ap_pdev_count(info, tgt_hdl);
292 
293 	info->wlan_res_cfg.num_vdevs = (target_psoc_get_num_radios(tgt_hdl) *
294 					info->wlan_res_cfg.num_vdevs);
295 	info->wlan_res_cfg.beacon_tx_offload_max_vdev =
296 				(target_psoc_get_num_radios(tgt_hdl) *
297 				info->wlan_res_cfg.beacon_tx_offload_max_vdev);
298 	info->wlan_res_cfg.max_bssid_indicator =
299 				info->service_ext_param.max_bssid_indicator;
300 
301 	info->wmi_service_ready = TRUE;
302 
303 	init_deinit_prepare_send_init_cmd(psoc, tgt_hdl);
304 
305 exit:
306 	return err_code;
307 }
308 
309 static int init_deinit_service_available_handler(ol_scn_t scn_handle,
310 						uint8_t *event,
311 						uint32_t data_len)
312 {
313 	struct wlan_objmgr_psoc *psoc;
314 	struct target_psoc_info *tgt_hdl;
315 	struct common_wmi_handle *wmi_handle;
316 
317 	if (!scn_handle) {
318 		target_if_err("scn handle NULL");
319 		return -EINVAL;
320 	}
321 
322 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
323 	if (!psoc) {
324 		target_if_err("psoc is null");
325 		return -EINVAL;
326 	}
327 
328 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
329 						psoc);
330 	if (!tgt_hdl) {
331 		target_if_err("target_psoc_info is null");
332 		return -EINVAL;
333 	}
334 
335 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
336 
337 	if (wmi_save_ext_service_bitmap(wmi_handle, event, NULL) !=
338 					QDF_STATUS_SUCCESS) {
339 		target_if_err("Failed to save ext service bitmap");
340 		return -EINVAL;
341 	}
342 
343 	return 0;
344 }
345 
346 /* MAC address fourth byte index */
347 #define MAC_BYTE_4 4
348 
349 static int init_deinit_ready_event_handler(ol_scn_t scn_handle,
350 						uint8_t *event,
351 						uint32_t data_len)
352 {
353 	struct wlan_objmgr_psoc *psoc;
354 	struct wlan_objmgr_pdev *pdev;
355 	struct target_psoc_info *tgt_hdl;
356 	struct common_wmi_handle *wmi_handle;
357 	struct wmi_host_fw_abi_ver fw_ver;
358 	uint8_t myaddr[QDF_MAC_ADDR_SIZE];
359 	struct tgt_info *info;
360 	struct wmi_host_ready_ev_param ready_ev;
361 	wmi_legacy_service_ready_callback legacy_callback;
362 	uint8_t num_radios, i;
363 	uint32_t max_peers;
364 	uint32_t max_ast_index;
365 	target_resource_config *tgt_cfg;
366 
367 	if (!scn_handle) {
368 		target_if_err("scn handle NULL");
369 		return -EINVAL;
370 	}
371 
372 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
373 	if (!psoc) {
374 		target_if_err("psoc is null");
375 		return -EINVAL;
376 	}
377 
378 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
379 						psoc);
380 	if (!tgt_hdl) {
381 		target_if_err("target_psoc_info is null");
382 		return -EINVAL;
383 	}
384 
385 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
386 	info = (&tgt_hdl->info);
387 
388 	if (wmi_extract_fw_abi_version(wmi_handle, event, &fw_ver) ==
389 				QDF_STATUS_SUCCESS) {
390 		info->version.wlan_ver = fw_ver.sw_version;
391 		info->version.wlan_ver = fw_ver.abi_version;
392 	}
393 
394 	if (wmi_check_and_update_fw_version(wmi_handle, event) < 0) {
395 		target_if_err("Version mismatch with FW");
396 		return -EINVAL;
397 	}
398 
399 	if (wmi_extract_ready_event_params(wmi_handle, event, &ready_ev) !=
400 				QDF_STATUS_SUCCESS) {
401 		target_if_err("Failed to extract ready event");
402 		return -EINVAL;
403 	}
404 
405 	if (!ready_ev.agile_capability)
406 		target_if_err("agile capability disabled in HW");
407 	else
408 		info->wlan_res_cfg.agile_capability = ready_ev.agile_capability;
409 
410 	if ((ready_ev.num_total_peer != 0) &&
411 	    (info->wlan_res_cfg.num_peers != ready_ev.num_total_peer)) {
412 		/* FW allocated number of peers is different than host
413 		 * requested. Update host max with FW reported value.
414 		 */
415 		target_if_err("Host Requested %d peers. FW Supports %d peers",
416 			       info->wlan_res_cfg.num_peers,
417 			       ready_ev.num_total_peer);
418 		info->wlan_res_cfg.num_peers = ready_ev.num_total_peer;
419 	}
420 
421 	/* for non legacy  num_total_peer will be non zero
422 	 * allocate peer memory in this case
423 	 */
424 	if (ready_ev.num_total_peer != 0) {
425 		tgt_cfg = &info->wlan_res_cfg;
426 		max_peers = tgt_cfg->num_peers + ready_ev.num_extra_peer + 1;
427 		max_ast_index = ready_ev.max_ast_index + 1;
428 
429 		if (cdp_peer_map_attach(wlan_psoc_get_dp_handle(psoc),
430 					max_peers, max_ast_index,
431 					tgt_cfg->peer_map_unmap_v2) !=
432 				QDF_STATUS_SUCCESS) {
433 			target_if_err("DP peer map attach failed");
434 			return -EINVAL;
435 		}
436 	}
437 
438 	/* Indicate to the waiting thread that the ready
439 	 * event was received
440 	 */
441 	info->wlan_init_status = wmi_ready_extract_init_status(
442 						wmi_handle, event);
443 
444 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
445 	if (legacy_callback)
446 		if (legacy_callback(wmi_ready_event_id,
447 				    scn_handle, event, data_len)) {
448 			target_if_err("Legacy callback returned error!");
449 			tgt_hdl->info.wmi_ready = FALSE;
450 			goto exit;
451 		}
452 
453 	num_radios = target_psoc_get_num_radios(tgt_hdl);
454 	/*
455 	 * For non-legacy HW, MAC addr list is extracted.
456 	 */
457 	if (num_radios > 1) {
458 		uint8_t num_mac_addr;
459 		wmi_host_mac_addr *addr_list;
460 		int i;
461 
462 		addr_list = wmi_ready_extract_mac_addr_list(wmi_handle, event,
463 							    &num_mac_addr);
464 		if ((num_mac_addr >= num_radios) && (addr_list)) {
465 			for (i = 0; i < num_radios; i++) {
466 				WMI_HOST_MAC_ADDR_TO_CHAR_ARRAY(&addr_list[i],
467 								myaddr);
468 				pdev = wlan_objmgr_get_pdev_by_id(psoc, i,
469 								  WLAN_INIT_DEINIT_ID);
470 				if (!pdev) {
471 					target_if_err(" PDEV %d is NULL", i);
472 					return -EINVAL;
473 				}
474 				wlan_pdev_set_hw_macaddr(pdev, myaddr);
475 				wlan_objmgr_pdev_release_ref(pdev,
476 							WLAN_INIT_DEINIT_ID);
477 
478 				/* assign 1st radio addr to psoc */
479 				if (i == 0)
480 					wlan_psoc_set_hw_macaddr(psoc, myaddr);
481 			}
482 			goto out;
483 		} else {
484 			target_if_err("Using default MAC addr for all radios..");
485 		}
486 	}
487 
488 	/*
489 	 * We extract single MAC address in two scenarios:
490 	 * 1. In non-legacy case, if addr list is NULL or num_mac_addr < num_radios
491 	 * 2. In all legacy cases
492 	 */
493 	for (i = 0; i < num_radios; i++) {
494 		wmi_ready_extract_mac_addr(wmi_handle, event, myaddr);
495 		myaddr[MAC_BYTE_4] += i;
496 		pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_INIT_DEINIT_ID);
497 		if (!pdev) {
498 			target_if_err(" PDEV %d is NULL", i);
499 			return -EINVAL;
500 		}
501 		wlan_pdev_set_hw_macaddr(pdev, myaddr);
502 		wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID);
503 		/* assign 1st radio addr to psoc */
504 		if (i == 0)
505 			wlan_psoc_set_hw_macaddr(psoc, myaddr);
506 	}
507 
508 out:
509 	target_if_btcoex_cfg_enable(psoc, tgt_hdl, event);
510 	tgt_hdl->info.wmi_ready = TRUE;
511 exit:
512 	init_deinit_wakeup_host_wait(psoc, tgt_hdl);
513 
514 	return 0;
515 }
516 
517 
518 QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers(
519 				struct wlan_objmgr_psoc *psoc)
520 {
521 	struct target_psoc_info *tgt_hdl;
522 	wmi_unified_t wmi_handle;
523 	QDF_STATUS retval = QDF_STATUS_SUCCESS;
524 
525 	if (!psoc) {
526 		target_if_err("psoc is null in register wmi handler");
527 		return QDF_STATUS_E_FAILURE;
528 	}
529 
530 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
531 						psoc);
532 	if (!tgt_hdl) {
533 		target_if_err("target_psoc_info null in register wmi hadler");
534 		return QDF_STATUS_E_FAILURE;
535 	}
536 
537 	wmi_handle = (wmi_unified_t)target_psoc_get_wmi_hdl(tgt_hdl);
538 
539 	retval = wmi_unified_register_event_handler(wmi_handle,
540 				wmi_service_ready_event_id,
541 				init_deinit_service_ready_event_handler,
542 				WMI_RX_WORK_CTX);
543 	retval = wmi_unified_register_event_handler(wmi_handle,
544 				wmi_service_ready_ext_event_id,
545 				init_deinit_service_ext_ready_event_handler,
546 				WMI_RX_WORK_CTX);
547 	retval = wmi_unified_register_event_handler(wmi_handle,
548 				wmi_service_available_event_id,
549 				init_deinit_service_available_handler,
550 				WMI_RX_UMAC_CTX);
551 	retval = wmi_unified_register_event_handler(wmi_handle,
552 				wmi_ready_event_id,
553 				init_deinit_ready_event_handler,
554 				WMI_RX_WORK_CTX);
555 
556 	return retval;
557 }
558 
559