xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
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 	target_if_btcoex_cfg_enable(psoc, tgt_hdl, event);
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 	void *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 	void *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 	void *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 
314 	if (!scn_handle) {
315 		target_if_err("scn handle NULL");
316 		return -EINVAL;
317 	}
318 
319 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
320 	if (!psoc) {
321 		target_if_err("psoc is null");
322 		return -EINVAL;
323 	}
324 
325 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
326 						psoc);
327 	if (!tgt_hdl) {
328 		target_if_err("target_psoc_info is null");
329 		return -EINVAL;
330 	}
331 
332 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
333 	info = (&tgt_hdl->info);
334 
335 	if (wmi_extract_fw_abi_version(wmi_handle, event, &fw_ver) ==
336 				QDF_STATUS_SUCCESS) {
337 		info->version.wlan_ver = fw_ver.sw_version;
338 		info->version.wlan_ver = fw_ver.abi_version;
339 	}
340 
341 	if (wmi_check_and_update_fw_version(wmi_handle, event) < 0) {
342 		target_if_err("Version mismatch with FW");
343 		return -EINVAL;
344 	}
345 
346 	if (wmi_extract_ready_event_params(wmi_handle, event, &ready_ev) !=
347 				QDF_STATUS_SUCCESS) {
348 		target_if_err("Failed to extract ready event");
349 		return -EINVAL;
350 	}
351 
352 	if ((ready_ev.num_total_peer != 0) &&
353 	    (info->wlan_res_cfg.num_peers != ready_ev.num_total_peer)) {
354 		/* FW allocated number of peers is different than host
355 		 * requested. Update host max with FW reported value.
356 		 */
357 		target_if_info("Host Requested %d peers. FW Supports %d peers",
358 			       info->wlan_res_cfg.num_peers,
359 			       ready_ev.num_total_peer);
360 		info->wlan_res_cfg.num_peers = ready_ev.num_total_peer;
361 	}
362 
363 	/* Indicate to the waiting thread that the ready
364 	 * event was received
365 	 */
366 	info->wlan_init_status = wmi_ready_extract_init_status(
367 						wmi_handle, event);
368 
369 	legacy_callback = target_if_get_psoc_legacy_service_ready_cb();
370 	if (legacy_callback)
371 		legacy_callback(wmi_ready_event_id,
372 				scn_handle, event, data_len);
373 
374 	num_radios = target_psoc_get_num_radios(tgt_hdl);
375 	/*
376 	 * For non-legacy HW, MAC addr list is extracted.
377 	 */
378 	if (num_radios > 1) {
379 		uint8_t num_mac_addr;
380 		wmi_host_mac_addr *addr_list;
381 		int i;
382 
383 		addr_list = wmi_ready_extract_mac_addr_list(wmi_handle, event,
384 							    &num_mac_addr);
385 		if ((num_mac_addr >= num_radios) && (addr_list)) {
386 			for (i = 0; i < num_radios; i++) {
387 				WMI_HOST_MAC_ADDR_TO_CHAR_ARRAY(&addr_list[i],
388 								myaddr);
389 				pdev = wlan_objmgr_get_pdev_by_id(psoc, i,
390 								  WLAN_INIT_DEINIT_ID);
391 				if (!pdev) {
392 					target_if_err(" PDEV %d is NULL", i);
393 					return -EINVAL;
394 				}
395 				wlan_pdev_set_hw_macaddr(pdev, myaddr);
396 				wlan_objmgr_pdev_release_ref(pdev,
397 							WLAN_INIT_DEINIT_ID);
398 
399 				/* assign 1st radio addr to psoc */
400 				if (i == 0)
401 					wlan_psoc_set_hw_macaddr(psoc, myaddr);
402 			}
403 			goto out;
404 		} else {
405 			target_if_err("Using default MAC addr for all radios..");
406 		}
407 	}
408 
409 	/*
410 	 * We extract single MAC address in two scenarios:
411 	 * 1. In non-legacy case, if addr list is NULL or num_mac_addr < num_radios
412 	 * 2. In all legacy cases
413 	 */
414 	for (i = 0; i < num_radios; i++) {
415 		wmi_ready_extract_mac_addr(wmi_handle, event, myaddr);
416 		myaddr[MAC_BYTE_4] += i;
417 		pdev = wlan_objmgr_get_pdev_by_id(psoc, i, 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, WLAN_INIT_DEINIT_ID);
424 		/* assign 1st radio addr to psoc */
425 		if (i == 0)
426 			wlan_psoc_set_hw_macaddr(psoc, myaddr);
427 	}
428 
429 out:
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