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