1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 /**
20  * DOC: service_ready_util.c
21  *
22  * Public APIs implementation source file for accessing (ext)service ready
23  * data from psoc object
24  */
25 #include "service_ready_util.h"
26 #include <wlan_reg_ucfg_api.h>
27 #include <target_type.h>
28 #include <qdf_module.h>
29 
init_deinit_chainmask_table_alloc(struct wlan_psoc_host_service_ext_param * ser_ext_par)30 QDF_STATUS init_deinit_chainmask_table_alloc(
31 		struct wlan_psoc_host_service_ext_param *ser_ext_par)
32 {
33 	int i;
34 	uint32_t alloc_size;
35 	QDF_STATUS status = QDF_STATUS_SUCCESS;
36 
37 	if (ser_ext_par->num_chainmask_tables == 0)
38 		return QDF_STATUS_E_NOSUPPORT;
39 
40 	for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) {
41 		if (ser_ext_par->chainmask_table[i].num_valid_chainmasks >
42 		    (UINT_MAX / sizeof(
43 		     struct wlan_psoc_host_chainmask_capabilities))) {
44 			target_if_err("invalid valid chanmask num %d",
45 				      ser_ext_par->chainmask_table[i].
46 				      num_valid_chainmasks);
47 			status = QDF_STATUS_E_FAILURE;
48 			break;
49 		}
50 		alloc_size =
51 			(sizeof(struct wlan_psoc_host_chainmask_capabilities) *
52 			 ser_ext_par->chainmask_table[i].num_valid_chainmasks);
53 
54 		ser_ext_par->chainmask_table[i].cap_list =
55 			qdf_mem_malloc(alloc_size);
56 		if (!ser_ext_par->chainmask_table[i].cap_list) {
57 			init_deinit_chainmask_table_free(ser_ext_par);
58 			status = QDF_STATUS_E_NOMEM;
59 			break;
60 		}
61 	}
62 
63 	return status;
64 }
65 
66 qdf_export_symbol(init_deinit_chainmask_table_alloc);
67 
init_deinit_chainmask_table_free(struct wlan_psoc_host_service_ext_param * ser_ext_par)68 QDF_STATUS init_deinit_chainmask_table_free(
69 		struct wlan_psoc_host_service_ext_param *ser_ext_par)
70 {
71 	struct wlan_psoc_host_chainmask_table *table;
72 	int i;
73 
74 	for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) {
75 		table =  &(ser_ext_par->chainmask_table[i]);
76 		if (table->cap_list) {
77 			qdf_mem_free(table->cap_list);
78 			table->cap_list = NULL;
79 		}
80 	}
81 
82 	return QDF_STATUS_SUCCESS;
83 }
84 
85 qdf_export_symbol(init_deinit_chainmask_table_free);
86 
init_deinit_populate_service_bitmap(wmi_unified_t wmi_handle,uint8_t * event,uint32_t * service_bitmap)87 int init_deinit_populate_service_bitmap(
88 		wmi_unified_t wmi_handle, uint8_t *event,
89 		uint32_t *service_bitmap)
90 {
91 	QDF_STATUS status;
92 
93 	status = wmi_save_service_bitmap(wmi_handle, event, service_bitmap);
94 	if (QDF_IS_STATUS_ERROR(status)) {
95 		target_if_err("failed to parse service bitmap");
96 		return qdf_status_to_os_return(status);
97 	}
98 
99 	return 0;
100 }
101 
init_deinit_populate_fw_version_cmd(wmi_unified_t wmi_handle,uint8_t * event)102 int init_deinit_populate_fw_version_cmd(wmi_unified_t wmi_handle,
103 					uint8_t *event)
104 {
105 	QDF_STATUS status;
106 
107 	status = wmi_unified_save_fw_version_cmd(wmi_handle, event);
108 	if (QDF_IS_STATUS_ERROR(status))
109 		target_if_err("failed to save fw version");
110 
111 	return 0;
112 }
113 
init_deinit_populate_target_cap(wmi_unified_t wmi_handle,uint8_t * event,struct wlan_psoc_target_capability_info * cap)114 int init_deinit_populate_target_cap(
115 		wmi_unified_t wmi_handle, uint8_t *event,
116 		struct wlan_psoc_target_capability_info *cap)
117 {
118 	QDF_STATUS status;
119 
120 	status = wmi_get_target_cap_from_service_ready(wmi_handle, event, cap);
121 	if (QDF_IS_STATUS_ERROR(status)) {
122 		target_if_err("failed to parse target cap");
123 		return qdf_status_to_os_return(status);
124 	}
125 
126 	return 0;
127 }
128 
init_deinit_populate_service_ready_ext_param(wmi_unified_t handle,uint8_t * evt,struct wlan_psoc_host_service_ext_param * param)129 int init_deinit_populate_service_ready_ext_param(
130 		wmi_unified_t handle, uint8_t *evt,
131 		struct wlan_psoc_host_service_ext_param *param)
132 {
133 	QDF_STATUS status;
134 
135 	status = wmi_extract_service_ready_ext(handle, evt, param);
136 	if (QDF_IS_STATUS_ERROR(status)) {
137 		target_if_err("failed to parse wmi service ready ext param");
138 		return qdf_status_to_os_return(status);
139 	}
140 
141 	return 0;
142 }
143 
init_deinit_populate_service_ready_ext2_param(wmi_unified_t handle,uint8_t * evt,struct tgt_info * info)144 int init_deinit_populate_service_ready_ext2_param(
145 		wmi_unified_t handle, uint8_t *evt,
146 		struct tgt_info *info)
147 {
148 	QDF_STATUS status;
149 
150 	status = wmi_extract_service_ready_ext2(handle, evt,
151 						&info->service_ext2_param);
152 	if (QDF_IS_STATUS_ERROR(status)) {
153 		target_if_err("failed to parse wmi service ready ext param");
154 		return qdf_status_to_os_return(status);
155 	}
156 
157 	return 0;
158 }
159 
init_deinit_populate_chainmask_tables(wmi_unified_t handle,uint8_t * evt,struct wlan_psoc_host_chainmask_table * param)160 int init_deinit_populate_chainmask_tables(
161 		wmi_unified_t handle, uint8_t *evt,
162 		struct wlan_psoc_host_chainmask_table *param)
163 {
164 	QDF_STATUS status;
165 
166 	status = wmi_extract_chainmask_tables(handle, evt, param);
167 	if (QDF_IS_STATUS_ERROR(status)) {
168 		target_if_err("failed to parse wmi service ready ext param");
169 		return qdf_status_to_os_return(status);
170 	}
171 
172 	return 0;
173 }
174 
init_deinit_populate_mac_phy_capability(wmi_unified_t handle,uint8_t * evt,struct wlan_psoc_host_hw_mode_caps * hw_cap,struct tgt_info * info)175 int init_deinit_populate_mac_phy_capability(
176 	wmi_unified_t handle, uint8_t *evt,
177 	struct wlan_psoc_host_hw_mode_caps *hw_cap, struct tgt_info *info)
178 {
179 	QDF_STATUS status;
180 	uint32_t hw_mode_id;
181 	uint32_t phy_bit_map;
182 	uint8_t mac_phy_id;
183 
184 	hw_mode_id = hw_cap->hw_mode_id;
185 	phy_bit_map = hw_cap->phy_id_map;
186 	target_if_debug("hw_mode_id %d phy_bit_map 0x%x",
187 			hw_mode_id, phy_bit_map);
188 
189 	mac_phy_id = 0;
190 	while (phy_bit_map) {
191 		if (info->total_mac_phy_cnt >= PSOC_MAX_MAC_PHY_CAP) {
192 			target_if_err("total mac phy exceeds max limit %d",
193 				      info->total_mac_phy_cnt);
194 			return -EINVAL;
195 		}
196 
197 		status = wmi_extract_mac_phy_cap_service_ready_ext(handle,
198 				evt, hw_mode_id, mac_phy_id,
199 				&(info->mac_phy_cap[info->total_mac_phy_cnt]));
200 		if (QDF_IS_STATUS_ERROR(status)) {
201 			target_if_err("failed to parse mac phy capability");
202 			return qdf_status_to_os_return(status);
203 		}
204 		info->mac_phy_cap[info->total_mac_phy_cnt].hw_mode_config_type
205 					= hw_cap->hw_mode_config_type;
206 		info->total_mac_phy_cnt++;
207 		phy_bit_map &= (phy_bit_map - 1);
208 		mac_phy_id++;
209 	}
210 	target_if_debug("total_mac_phy_cnt %d", info->total_mac_phy_cnt);
211 
212 	return 0;
213 }
214 
get_hw_mode(wmi_unified_t handle,uint8_t * evt,uint8_t hw_idx,struct wlan_psoc_host_hw_mode_caps * cap)215 static int get_hw_mode(wmi_unified_t handle, uint8_t *evt, uint8_t hw_idx,
216 		       struct wlan_psoc_host_hw_mode_caps *cap)
217 {
218 	QDF_STATUS status;
219 
220 	status = wmi_extract_hw_mode_cap_service_ready_ext(handle, evt,
221 					hw_idx, cap);
222 	if (QDF_IS_STATUS_ERROR(status)) {
223 		target_if_err("failed to parse hw mode capability");
224 		return qdf_status_to_os_return(status);
225 	}
226 
227 	return 0;
228 }
229 
get_sar_version(wmi_unified_t handle,uint8_t * evt,struct wlan_psoc_host_service_ext_param * ext_param)230 static int get_sar_version(wmi_unified_t handle, uint8_t *evt,
231 			   struct wlan_psoc_host_service_ext_param *ext_param)
232 {
233 	QDF_STATUS status;
234 
235 	status = wmi_extract_sar_cap_service_ready_ext(handle, evt, ext_param);
236 	if (QDF_IS_STATUS_ERROR(status)) {
237 		target_if_err("failed to parse sar capability");
238 		return qdf_status_to_os_return(status);
239 	}
240 
241 	return 0;
242 }
243 
new_hw_mode_preferred(uint32_t current_hw_mode,uint32_t new_hw_mode)244 static bool new_hw_mode_preferred(uint32_t current_hw_mode,
245 				  uint32_t new_hw_mode)
246 {
247 	uint8_t hw_mode_id_precedence[WMI_HOST_HW_MODE_MAX + 1] = { 6, 2, 5,
248 								    4, 1, 3,
249 								    7, 0, 8,
250 								    9, 10, 11};
251 
252 	if (current_hw_mode > WMI_HOST_HW_MODE_MAX ||
253 	    new_hw_mode > WMI_HOST_HW_MODE_MAX)
254 		return false;
255 
256 	/* Above precedence is defined by low to high, lower the value
257 	 * higher the precedence
258 	 */
259 	if (hw_mode_id_precedence[current_hw_mode] >
260 	    hw_mode_id_precedence[new_hw_mode])
261 		return true;
262 
263 	return false;
264 }
265 
266 /**
267  * select_preferred_hw_mode() - Select preferred hw mode based on current mode.
268  * @tgt_hdl: target_psoc_info object
269  * @hw_mode_caps: HW mode caps of new mode id that needs to checked for
270  *                selection.
271  * @current_mode: Current mode.
272  *
273  * API to select preferred hw mode based on the current config.
274  * Based on host config for preferred mode, final mode selected as follows-
275  * 1) If preferred_mode == WMI_HOST_HW_MODE_DETECT, Then select mode from FW
276  *    supported modes such that it is a super set of all modes FW advertises.
277  *    For e.g., If FW supports DBS(2 radio) and DBS_SBS(3 radio)- Choose DBS_SBS
278  * 2) If preferred_mode == WMI_HOST_HW_MODE_MAX, Then do not select any mode
279  *    from FW advertised modes. Host needs to maintain all modes supported in FW
280  *    and can switch dynamically.
281  * 3) Else, A valid preferred_mode is set, Hence check if this is part of FW
282  *    supported modes. If it is found, then use it to bring up the device.
283  *
284  * Return: selected_mode based on the above criteria.
285  */
286 static uint32_t
select_preferred_hw_mode(struct target_psoc_info * tgt_hdl,struct wlan_psoc_host_hw_mode_caps * hw_mode_caps,uint32_t current_mode)287 select_preferred_hw_mode(struct target_psoc_info *tgt_hdl,
288 			 struct wlan_psoc_host_hw_mode_caps *hw_mode_caps,
289 			 uint32_t current_mode)
290 {
291 	uint32_t preferred_mode, selected_mode = current_mode;
292 	struct tgt_info *info;
293 
294 	info = &tgt_hdl->info;
295 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
296 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
297 		uint32_t new_mode = hw_mode_caps->hw_mode_id;
298 
299 		/* Choose hw_mode_id based on precedence */
300 		if (new_hw_mode_preferred(selected_mode, new_mode)) {
301 			selected_mode = new_mode;
302 			qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps,
303 				     sizeof(info->hw_mode_cap));
304 		}
305 	} else if ((preferred_mode != WMI_HOST_HW_MODE_MAX) &&
306 		   (preferred_mode == hw_mode_caps->hw_mode_id)) {
307 		selected_mode = preferred_mode;
308 		qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps,
309 			     sizeof(info->hw_mode_cap));
310 	}
311 
312 	return selected_mode;
313 }
314 
315 #ifdef FEATURE_NO_DBS_INTRABAND_MCC_SUPPORT
init_deinit_change_def_hw_mode(struct target_psoc_info * tgt_hdl,struct wmi_unified * wmi_handle)316 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl,
317 					   struct wmi_unified *wmi_handle)
318 {
319 	struct tgt_info *info = &tgt_hdl->info;
320 
321 	if ((info->hw_modes.num_modes == 1) &&
322 	    (info->hw_modes.hw_mode_ids[0] == WMI_HOST_HW_MODE_DBS) &&
323 	    !wmi_service_enabled(wmi_handle,
324 				 wmi_service_dual_band_simultaneous_support))
325 		target_psoc_set_preferred_hw_mode(tgt_hdl,
326 						  WMI_HOST_HW_MODE_DETECT);
327 }
328 #else
init_deinit_change_def_hw_mode(struct target_psoc_info * tgt_hdl,struct wmi_unified * wmi_handle)329 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl,
330 					   struct wmi_unified *wmi_handle)
331 {
332 }
333 #endif
334 
init_deinit_populate_hw_mode_capability(wmi_unified_t wmi_handle,uint8_t * event,struct target_psoc_info * tgt_hdl)335 int init_deinit_populate_hw_mode_capability(
336 		wmi_unified_t wmi_handle, uint8_t *event,
337 		struct target_psoc_info *tgt_hdl)
338 {
339 	QDF_STATUS status = QDF_STATUS_SUCCESS;
340 	uint8_t hw_idx;
341 	uint32_t num_hw_modes;
342 	struct wlan_psoc_host_hw_mode_caps hw_mode_caps[PSOC_MAX_HW_MODE];
343 	uint32_t preferred_mode, selected_mode = WMI_HOST_HW_MODE_MAX;
344 	struct tgt_info *info;
345 
346 	info = &tgt_hdl->info;
347 	num_hw_modes = info->service_ext_param.num_hw_modes;
348 	if (num_hw_modes > PSOC_MAX_HW_MODE) {
349 		target_if_err("invalid num_hw_modes %d", num_hw_modes);
350 		return -EINVAL;
351 	}
352 	target_if_debug("num_hw_modes %d", num_hw_modes);
353 
354 	qdf_mem_zero(&hw_mode_caps, sizeof(hw_mode_caps));
355 	info->hw_modes.num_modes = 0;
356 	info->hw_mode_cap.hw_mode_id = WMI_HOST_HW_MODE_MAX;
357 
358 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
359 		status = get_hw_mode(wmi_handle, event, hw_idx,
360 						&hw_mode_caps[hw_idx]);
361 		if (status)
362 			goto return_exit;
363 
364 		if (hw_idx < WMI_HOST_HW_MODE_MAX) {
365 			info->hw_modes.hw_mode_ids[hw_idx] =
366 				hw_mode_caps[hw_idx].hw_mode_id;
367 			info->hw_modes.phy_bit_map[hw_idx] =
368 				hw_mode_caps[hw_idx].phy_id_map;
369 			info->hw_modes.num_modes++;
370 		}
371 
372 		status = init_deinit_populate_mac_phy_capability(wmi_handle,
373 				event, &hw_mode_caps[hw_idx], info);
374 		if (status)
375 			goto return_exit;
376 
377 		if (num_hw_modes == 1)
378 			init_deinit_change_def_hw_mode(tgt_hdl, wmi_handle);
379 
380 		selected_mode = select_preferred_hw_mode(tgt_hdl,
381 							 &hw_mode_caps[hw_idx],
382 							 selected_mode);
383 	}
384 
385 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
386 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
387 		target_if_info("Preferred mode is not set, use mode id %d\n",
388 			       selected_mode);
389 		target_psoc_set_preferred_hw_mode(tgt_hdl, selected_mode);
390 
391 		/* Change default DBS hw mode as per selected one */
392 		info->target_caps.default_dbs_hw_mode_index = selected_mode;
393 	}
394 
395 	status = get_sar_version(wmi_handle, event, &info->service_ext_param);
396 	target_if_debug("sar version %d", info->service_ext_param.sar_version);
397 
398 return_exit:
399 	return qdf_status_to_os_return(status);
400 }
401 
init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)402 int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc,
403 				      wmi_unified_t handle, uint8_t *event,
404 				      struct tgt_info *info)
405 
406 {
407 	uint8_t cap_idx;
408 	uint32_t num_dbr_ring_caps;
409 	QDF_STATUS status = QDF_STATUS_SUCCESS;
410 
411 	num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps;
412 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
413 
414 	if (!num_dbr_ring_caps)
415 		return 0;
416 
417 	info->dbr_ring_cap = qdf_mem_malloc(
418 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
419 				num_dbr_ring_caps);
420 
421 	if (!info->dbr_ring_cap)
422 		return -EINVAL;
423 
424 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
425 		status = wmi_extract_dbr_ring_cap_service_ready_ext(handle,
426 				event, cap_idx,
427 				&(info->dbr_ring_cap[cap_idx]));
428 		if (QDF_IS_STATUS_ERROR(status)) {
429 			target_if_err("Extraction of DMA cap failed");
430 			goto free_and_return;
431 		}
432 	}
433 
434 	return 0;
435 
436 free_and_return:
437 	qdf_mem_free(info->dbr_ring_cap);
438 	info->dbr_ring_cap = NULL;
439 
440 	return qdf_status_to_os_return(status);
441 }
442 
init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)443 int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc,
444 					   wmi_unified_t handle, uint8_t *event,
445 					   struct tgt_info *info)
446 
447 {
448 	uint8_t cap_idx;
449 	uint32_t num_dbr_ring_caps;
450 	QDF_STATUS status = QDF_STATUS_SUCCESS;
451 	struct wlan_psoc_host_dbr_ring_caps *param;
452 
453 	/*
454 	 * If FW had already sent this info as part of EXT event,
455 	 * we need to discard the same and use the info from EXT2.
456 	 */
457 	if (info->service_ext_param.num_dbr_ring_caps) {
458 		target_if_debug("dbr_ring_caps already populated");
459 		info->service_ext_param.num_dbr_ring_caps = 0;
460 		qdf_mem_free(info->dbr_ring_cap);
461 		info->dbr_ring_cap = NULL;
462 	}
463 
464 	num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps;
465 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
466 
467 	if (!num_dbr_ring_caps)
468 		return 0;
469 
470 	info->dbr_ring_cap = qdf_mem_malloc(
471 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
472 				num_dbr_ring_caps);
473 
474 	if (!info->dbr_ring_cap)
475 		return -EINVAL;
476 
477 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
478 		param = &info->dbr_ring_cap[cap_idx];
479 		status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle,
480 								     event,
481 								     cap_idx,
482 								     param);
483 		if (QDF_IS_STATUS_ERROR(status)) {
484 			target_if_err("Extraction of DMA cap failed");
485 			goto free_and_return;
486 		}
487 	}
488 
489 	return 0;
490 
491 free_and_return:
492 	qdf_mem_free(info->dbr_ring_cap);
493 	info->dbr_ring_cap = NULL;
494 
495 	return qdf_status_to_os_return(status);
496 }
init_deinit_populate_spectral_bin_scale_params(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)497 int init_deinit_populate_spectral_bin_scale_params(
498 			struct wlan_objmgr_psoc *psoc, wmi_unified_t handle,
499 			uint8_t *event, struct tgt_info *info)
500 
501 {
502 	uint8_t param_idx;
503 	uint32_t num_bin_scaling_params;
504 	QDF_STATUS status = QDF_STATUS_SUCCESS;
505 
506 	num_bin_scaling_params = info->service_ext_param.num_bin_scaling_params;
507 
508 	if (!num_bin_scaling_params)
509 		return 0;
510 
511 	info->scaling_params = qdf_mem_malloc(
512 		sizeof(struct wlan_psoc_host_spectral_scaling_params) *
513 		num_bin_scaling_params);
514 
515 	if (!info->scaling_params) {
516 		target_if_err("Mem alloc for bin scaling params failed");
517 		return -EINVAL;
518 	}
519 
520 	for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) {
521 		status = wmi_extract_spectral_scaling_params_service_ready_ext(
522 				handle,
523 				event, param_idx,
524 				&info->scaling_params[param_idx]);
525 		if (QDF_IS_STATUS_ERROR(status)) {
526 			target_if_err("Extraction of scaling params failed");
527 			goto free_and_return;
528 		}
529 	}
530 
531 	return 0;
532 
533 free_and_return:
534 	qdf_mem_free(info->scaling_params);
535 	info->scaling_params = NULL;
536 
537 	return qdf_status_to_os_return(status);
538 }
539 
540 #ifdef WLAN_SUPPORT_TWT
init_deinit_populate_twt_cap_ext2(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)541 int init_deinit_populate_twt_cap_ext2(struct wlan_objmgr_psoc *psoc,
542 				      wmi_unified_t handle, uint8_t *event,
543 				      struct tgt_info *info)
544 {
545 	struct wmi_twt_cap_bitmap_params param;
546 	struct target_psoc_info *psoc_info;
547 	QDF_STATUS status = QDF_STATUS_SUCCESS;
548 
549 	status = wmi_extract_twt_cap_service_ready_ext2(handle, event,
550 							&param);
551 	if (QDF_IS_STATUS_ERROR(status)) {
552 		target_if_err("Extraction of twt capability failed");
553 		goto exit;
554 	}
555 
556 	psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
557 
558 	target_psoc_set_twt_ack_cap(psoc_info, param.twt_ack_support_cap);
559 
560 exit:
561 	return qdf_status_to_os_return(status);
562 }
563 #endif
564 
565 #ifdef WLAN_RCC_ENHANCED_AOA_SUPPORT
init_deinit_populate_rcc_aoa_cap_ext2(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)566 int init_deinit_populate_rcc_aoa_cap_ext2(struct wlan_objmgr_psoc *psoc,
567 					  wmi_unified_t handle,
568 					  uint8_t *event,
569 					  struct tgt_info *info)
570 {
571 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
572 
573 	info->aoa_caps = qdf_mem_malloc(
574 		sizeof(struct wlan_psoc_host_rcc_enh_aoa_caps_ext2));
575 
576 	if (!info->aoa_caps) {
577 		target_if_err("Mem alloc for aoa cap failed");
578 		return -EINVAL;
579 	}
580 
581 	status = wmi_extract_aoa_caps_service_ready_ext2(
582 				handle, event,
583 				info->aoa_caps);
584 
585 	if (QDF_IS_STATUS_ERROR(status)) {
586 		target_if_err("Extraction of aoa caps failed");
587 		goto free_and_return;
588 	}
589 
590 	return 0;
591 
592 free_and_return:
593 	qdf_mem_free(info->aoa_caps);
594 	info->aoa_caps = NULL;
595 
596 	return qdf_status_to_os_return(status);
597 }
598 
init_deinit_rcc_aoa_cap_ext2_free(struct target_psoc_info * tgt_psoc_info)599 QDF_STATUS init_deinit_rcc_aoa_cap_ext2_free(
600 		struct target_psoc_info *tgt_psoc_info)
601 {
602 	qdf_mem_free(tgt_psoc_info->info.aoa_caps);
603 	tgt_psoc_info->info.aoa_caps = NULL;
604 
605 	return QDF_STATUS_SUCCESS;
606 }
607 #else
init_deinit_populate_rcc_aoa_cap_ext2(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)608 int init_deinit_populate_rcc_aoa_cap_ext2(struct wlan_objmgr_psoc *psoc,
609 					  wmi_unified_t handle,
610 					  uint8_t *event,
611 					  struct tgt_info *info)
612 {
613 	return 0;
614 }
615 
init_deinit_rcc_aoa_cap_ext2_free(struct target_psoc_info * tgt_psoc_info)616 QDF_STATUS init_deinit_rcc_aoa_cap_ext2_free(
617 		struct target_psoc_info *tgt_psoc_info)
618 {
619 	return QDF_STATUS_SUCCESS;
620 }
621 #endif /* WLAN_RCC_ENHANCED_AOA_SUPPORT */
622 
623 qdf_export_symbol(init_deinit_rcc_aoa_cap_ext2_free);
624 
init_deinit_populate_dbs_or_sbs_cap_ext2(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)625 int init_deinit_populate_dbs_or_sbs_cap_ext2(struct wlan_objmgr_psoc *psoc,
626 					     wmi_unified_t handle,
627 					     uint8_t *event,
628 					     struct tgt_info *info)
629 {
630 	uint32_t sbs_lower_band_end_freq;
631 	struct target_psoc_info *psoc_info;
632 	QDF_STATUS status = QDF_STATUS_SUCCESS;
633 
634 	status = wmi_extract_dbs_or_sbs_cap_service_ready_ext2(handle, event,
635 						&sbs_lower_band_end_freq);
636 	if (QDF_IS_STATUS_ERROR(status)) {
637 		target_if_err("Extraction of twt capability failed");
638 		goto exit;
639 	}
640 	psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
641 	target_psoc_set_sbs_lower_band_end(psoc_info, sbs_lower_band_end_freq);
642 
643 exit:
644 	return qdf_status_to_os_return(status);
645 }
646 
init_deinit_populate_sap_coex_capability(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event)647 int init_deinit_populate_sap_coex_capability(struct wlan_objmgr_psoc *psoc,
648 					     wmi_unified_t handle,
649 					     uint8_t *event)
650 {
651 	struct wmi_host_coex_fix_chan_cap sap_coex_fixed_chan_cap;
652 	struct target_psoc_info *psoc_info;
653 	QDF_STATUS status;
654 
655 	qdf_mem_zero(&sap_coex_fixed_chan_cap,
656 		     sizeof(struct wmi_host_coex_fix_chan_cap));
657 
658 	status = wmi_extract_sap_coex_cap_service_ready_ext2(handle, event,
659 					&sap_coex_fixed_chan_cap);
660 	if (QDF_IS_STATUS_ERROR(status)) {
661 		target_if_err("Extraction of sap_coex_chan_pref cap failed");
662 		goto exit;
663 	}
664 	psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
665 	target_psoc_set_sap_coex_fixed_chan_cap(psoc_info,
666 				!!sap_coex_fixed_chan_cap.fix_chan_priority);
667 exit:
668 	return qdf_status_to_os_return(status);
669 }
670 
init_deinit_populate_aux_dev_cap_ext2(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info)671 int init_deinit_populate_aux_dev_cap_ext2(struct wlan_objmgr_psoc *psoc,
672 					  wmi_unified_t handle, uint8_t *event,
673 					  struct tgt_info *info)
674 
675 {
676 	uint8_t cap_idx;
677 	uint32_t num_aux_dev_caps;
678 	QDF_STATUS status = QDF_STATUS_SUCCESS;
679 	struct wlan_psoc_host_aux_dev_caps *param;
680 
681 	num_aux_dev_caps = info->service_ext2_param.num_aux_dev_caps;
682 	target_if_info("num_aux_dev_caps = %d", num_aux_dev_caps);
683 
684 	if (!num_aux_dev_caps)
685 		return 0;
686 
687 	info->aux_dev_caps =
688 		qdf_mem_malloc(sizeof(struct wlan_psoc_host_aux_dev_caps) *
689 			       num_aux_dev_caps);
690 
691 	if (!info->aux_dev_caps)
692 		return -EINVAL;
693 
694 	for (cap_idx = 0; cap_idx < num_aux_dev_caps; cap_idx++) {
695 		param = &info->aux_dev_caps[cap_idx];
696 		status = wmi_extract_aux_dev_cap_service_ready_ext2(handle,
697 								    event,
698 								    cap_idx,
699 								    param);
700 		if (QDF_IS_STATUS_ERROR(status)) {
701 			target_if_err("Extraction of aux dev cap failed");
702 			goto free_and_return;
703 		}
704 	}
705 
706 	return 0;
707 
708 free_and_return:
709 	qdf_mem_free(info->aux_dev_caps);
710 	info->aux_dev_caps = NULL;
711 	/* Set to 0 in case some code later rely on that */
712 	info->service_ext2_param.num_aux_dev_caps = 0;
713 
714 	return qdf_status_to_os_return(status);
715 }
716 
init_deinit_dbr_ring_cap_free(struct target_psoc_info * tgt_psoc_info)717 QDF_STATUS init_deinit_dbr_ring_cap_free(
718 		struct target_psoc_info *tgt_psoc_info)
719 {
720 	QDF_STATUS status = QDF_STATUS_SUCCESS;
721 
722 	if (tgt_psoc_info->info.dbr_ring_cap) {
723 		qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap);
724 		tgt_psoc_info->info.dbr_ring_cap = NULL;
725 	}
726 
727 	return status;
728 }
729 qdf_export_symbol(init_deinit_dbr_ring_cap_free);
730 
init_deinit_spectral_scaling_params_free(struct target_psoc_info * tgt_psoc_info)731 QDF_STATUS init_deinit_spectral_scaling_params_free(
732 		struct target_psoc_info *tgt_psoc_info)
733 {
734 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
735 
736 	if (tgt_psoc_info->info.scaling_params) {
737 		qdf_mem_free(tgt_psoc_info->info.scaling_params);
738 		tgt_psoc_info->info.scaling_params = NULL;
739 		status = QDF_STATUS_SUCCESS;
740 	}
741 
742 	return status;
743 }
744 
745 qdf_export_symbol(init_deinit_spectral_scaling_params_free);
746 
init_deinit_aux_dev_cap_free(struct target_psoc_info * tgt_psoc_info)747 QDF_STATUS init_deinit_aux_dev_cap_free(
748 		struct target_psoc_info *tgt_psoc_info)
749 {
750 	QDF_STATUS status = QDF_STATUS_SUCCESS;
751 
752 	if (tgt_psoc_info->info.aux_dev_caps) {
753 		qdf_mem_free(tgt_psoc_info->info.aux_dev_caps);
754 		tgt_psoc_info->info.aux_dev_caps = NULL;
755 	}
756 
757 	return status;
758 }
759 
760 #ifdef DBS_SBS_BAND_LIMITATION_WAR
761 #define phy0               0
762 #define phy2               2
763 #define NUM_RF_MODES       2 /* (DBS + DBS_SBS) */
764 /**
765  * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0.
766  * @psoc: PSOC common object
767  * @info: FW or lower layer related info
768  * @reg_cap: Reg caps per PHY
769  *
770  * For the DBS_SBS capable board, update the low or high frequency
771  * for phy0 by leveraging the frequency populated for phy2
772  * depending on whether it is mapped to upper or lower 5G band by
773  * FW/HAL-PHY.
774  */
init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc * psoc,struct tgt_info * info,struct wlan_psoc_host_hal_reg_capabilities_ext * reg_cap)775 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
776 					struct tgt_info *info,
777 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
778 {
779 	struct target_psoc_info *tgt_hdl;
780 	enum wmi_host_hw_mode_config_type mode;
781 	uint32_t num_hw_modes;
782 	uint8_t idx;
783 
784 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
785 						psoc);
786 	if (!tgt_hdl) {
787 		target_if_err("target_psoc_info is null in service ready ev");
788 		return;
789 	}
790 
791 	mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
792 
793 	num_hw_modes = info->hw_modes.num_modes;
794 
795 	if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES))
796 		return;
797 
798 	for (idx = 0; idx < num_hw_modes; idx++)
799 		if (info->hw_modes.hw_mode_ids[idx] ==
800 			WMI_HOST_HW_MODE_DBS_SBS) {
801 			if (reg_cap[phy0].low_5ghz_chan >
802 					reg_cap[phy2].low_5ghz_chan)
803 				reg_cap[phy0].low_5ghz_chan =
804 				    reg_cap[phy2].low_5ghz_chan;
805 			else if (reg_cap[phy0].high_5ghz_chan <
806 					reg_cap[phy2].high_5ghz_chan)
807 				reg_cap[phy0].high_5ghz_chan =
808 				    reg_cap[phy2].high_5ghz_chan;
809 			break;
810 		}
811 }
812 #else
init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc * psoc,struct tgt_info * info,struct wlan_psoc_host_hal_reg_capabilities_ext * reg_cap)813 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
814 					struct tgt_info *info,
815 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
816 {
817 }
818 #endif
819 
820 /**
821  * init_deinit_fill_host_reg_cap() - Fill the host regulatory cap
822  * with target hal reg capabilities.
823  * @cap: Pointer to wlan_psoc_hal_reg_capability where FW capabilities
824  * are extracted.
825  * @reg_cap: Pointer to wlan_psoc_host_hal_reg_capabilities_ext, host reg
826  * capabilities to be filled.
827  *
828  * Return - None
829  */
830 static void
init_deinit_fill_host_reg_cap(struct wlan_psoc_hal_reg_capability * cap,struct wlan_psoc_host_hal_reg_capabilities_ext * reg_cap)831 init_deinit_fill_host_reg_cap(struct wlan_psoc_hal_reg_capability *cap,
832 			      struct wlan_psoc_host_hal_reg_capabilities_ext
833 			      *reg_cap)
834 {
835 	reg_cap->phy_id = 0;
836 	reg_cap->eeprom_reg_domain = cap->eeprom_rd;
837 	reg_cap->eeprom_reg_domain_ext = cap->eeprom_rd_ext;
838 	reg_cap->regcap1 = cap->regcap1;
839 	reg_cap->regcap2 = cap->regcap2;
840 	reg_cap->wireless_modes = (uint64_t)cap->wireless_modes;
841 	reg_cap->low_2ghz_chan = cap->low_2ghz_chan;
842 	reg_cap->high_2ghz_chan = cap->high_2ghz_chan;
843 	reg_cap->low_5ghz_chan = cap->low_5ghz_chan;
844 	reg_cap->high_5ghz_chan = cap->high_5ghz_chan;
845 }
846 
847 static void
init_deinit_populate_tgt_ext_param(struct tgt_info * info,struct wlan_psoc_host_hal_reg_capabilities_ext * cap)848 init_deinit_populate_tgt_ext_param(struct tgt_info *info,
849 			struct wlan_psoc_host_hal_reg_capabilities_ext *cap)
850 {
851 	struct wlan_psoc_host_service_ext_param *ext_param;
852 
853 	ext_param = &info->service_ext_param;
854 	ext_param->wireless_modes = cap->wireless_modes;
855 	ext_param->low_2ghz_chan = cap->low_2ghz_chan;
856 	ext_param->high_2ghz_chan = cap->high_2ghz_chan;
857 	ext_param->low_5ghz_chan = cap->low_5ghz_chan;
858 	ext_param->high_5ghz_chan = cap->high_5ghz_chan;
859 }
860 
861 static void
init_deinit_populate_tgt_ext2_param(struct tgt_info * info,struct wlan_psoc_host_hal_reg_capabilities_ext2 * cap)862 init_deinit_populate_tgt_ext2_param(struct tgt_info *info,
863 			struct wlan_psoc_host_hal_reg_capabilities_ext2 *cap)
864 {
865 	struct wlan_psoc_host_service_ext2_param *ext2_param;
866 
867 	ext2_param = &info->service_ext2_param;
868 	ext2_param->wireless_modes_ext = cap->wireless_modes_ext;
869 	ext2_param->low_2ghz_chan_ext = cap->low_2ghz_chan_ext;
870 	ext2_param->high_2ghz_chan_ext = cap->high_2ghz_chan_ext;
871 	ext2_param->low_5ghz_chan_ext = cap->low_5ghz_chan_ext;
872 	ext2_param->high_5ghz_chan_ext = cap->high_5ghz_chan_ext;
873 }
874 
init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc * psoc,wmi_unified_t handle,uint8_t * event,struct tgt_info * info,bool service_ready)875 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
876 				     wmi_unified_t handle, uint8_t *event,
877 				     struct tgt_info *info,
878 				     bool service_ready)
879 {
880 	uint8_t reg_idx;
881 	uint32_t num_phy_reg_cap;
882 	QDF_STATUS status = QDF_STATUS_SUCCESS;
883 	struct wlan_psoc_hal_reg_capability cap;
884 	struct wlan_psoc_host_hal_reg_capabilities_ext
885 				reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
886 
887 	if (service_ready) {
888 		status = wmi_extract_hal_reg_cap(handle, event, &cap);
889 		if (QDF_IS_STATUS_ERROR(status)) {
890 			target_if_err("failed to parse hal reg cap");
891 			return qdf_status_to_os_return(status);
892 		}
893 		info->service_ext_param.num_phy = 1;
894 		num_phy_reg_cap = 1;
895 		init_deinit_fill_host_reg_cap(&cap, &reg_cap[0]);
896 		init_deinit_populate_tgt_ext_param(info, &reg_cap[0]);
897 		target_if_debug("FW wireless modes 0x%llx",
898 				reg_cap[0].wireless_modes);
899 	} else {
900 		num_phy_reg_cap = info->service_ext_param.num_phy;
901 		if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
902 			target_if_err("Invalid num_phy_reg_cap %d",
903 				      num_phy_reg_cap);
904 			return -EINVAL;
905 		}
906 		target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap);
907 
908 		for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
909 			status = wmi_extract_reg_cap_service_ready_ext(handle,
910 					event, reg_idx, &(reg_cap[reg_idx]));
911 			if (QDF_IS_STATUS_ERROR(status)) {
912 				target_if_err("failed to parse reg cap");
913 				return qdf_status_to_os_return(status);
914 			}
915 		}
916 	}
917 
918 	init_deinit_update_phy_reg_cap(psoc, info, reg_cap);
919 	status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap);
920 
921 	return qdf_status_to_os_return(status);
922 }
923 
init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle,uint8_t * event,struct tgt_info * info)924 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle,
925 					  uint8_t *event,
926 					  struct tgt_info *info)
927 {
928 	uint32_t num_hw_modes;
929 	uint8_t hw_idx;
930 	uint32_t hw_mode_id;
931 	uint32_t phy_bit_map;
932 	uint8_t phy_id;
933 	uint8_t mac_phy_count = 0;
934 	QDF_STATUS status = QDF_STATUS_SUCCESS;
935 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
936 	struct wlan_psoc_host_mac_phy_caps_ext2 *mac_phy_caps_ext2;
937 
938 	if (!event)
939 		return -EINVAL;
940 
941 	num_hw_modes = info->hw_modes.num_modes;
942 
943 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
944 		hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx];
945 		phy_bit_map = info->hw_modes.phy_bit_map[hw_idx];
946 
947 		phy_id = info->mac_phy_cap[mac_phy_count].phy_id;
948 		while (phy_bit_map) {
949 			if (mac_phy_count >= info->total_mac_phy_cnt) {
950 				target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d",
951 					      info->total_mac_phy_cnt,
952 					      mac_phy_count);
953 				return -EINVAL;
954 			}
955 
956 			mac_phy_cap = &info->mac_phy_cap[mac_phy_count];
957 			mac_phy_caps_ext2 =
958 				&info->mac_phy_caps_ext2[mac_phy_count];
959 			status = wmi_extract_mac_phy_cap_service_ready_ext2(
960 					wmi_handle, event, hw_mode_id, phy_id,
961 					mac_phy_cap->phy_idx,
962 					mac_phy_caps_ext2);
963 
964 			if (QDF_IS_STATUS_ERROR(status)) {
965 				target_if_err("failed to parse mac phy capability ext2");
966 				return qdf_status_to_os_return(status);
967 			}
968 
969 			mac_phy_cap->reg_cap_ext.wireless_modes |=
970 				mac_phy_caps_ext2[phy_id].wireless_modes_ext;
971 
972 			mac_phy_count++;
973 			phy_bit_map &= (phy_bit_map - 1);
974 			phy_id++;
975 		}
976 	}
977 
978 	return 0;
979 }
980 
init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle,uint8_t * event,struct tgt_info * info)981 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle,
982 					  uint8_t *event,
983 					  struct tgt_info *info)
984 {
985 	struct wlan_psoc_host_hal_reg_capabilities_ext2
986 		reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
987 	struct wlan_objmgr_psoc *psoc;
988 	uint32_t num_phy_reg_cap;
989 	uint8_t reg_idx;
990 	QDF_STATUS status = QDF_STATUS_SUCCESS;
991 
992 	if (!event) {
993 		target_if_err("event buffer is null");
994 		return -EINVAL;
995 	}
996 
997 	psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle);
998 	if (!psoc) {
999 		target_if_err("psoc is null");
1000 		return -EINVAL;
1001 	}
1002 
1003 	num_phy_reg_cap = info->service_ext_param.num_phy;
1004 	if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
1005 		target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap);
1006 		return -EINVAL;
1007 	}
1008 
1009 	for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
1010 		status = wmi_extract_hal_reg_cap_ext2(
1011 				wmi_handle, event, reg_idx, &reg_cap[reg_idx]);
1012 		if (QDF_IS_STATUS_ERROR(status)) {
1013 			target_if_err("failed to parse hal reg cap ext2");
1014 			return qdf_status_to_os_return(status);
1015 		}
1016 
1017 		init_deinit_populate_tgt_ext2_param(info, &reg_cap[reg_idx]);
1018 		status = ucfg_reg_update_hal_cap_wireless_modes(psoc,
1019 				reg_cap[reg_idx].wireless_modes_ext,
1020 				reg_idx);
1021 		if (QDF_IS_STATUS_ERROR(status)) {
1022 			target_if_err("Failed to update hal reg cap");
1023 			return qdf_status_to_os_return(status);
1024 		}
1025 	}
1026 
1027 	return 0;
1028 }
1029 
init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle,uint8_t * event,struct tgt_info * info)1030 int init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle,
1031 					     uint8_t *event,
1032 					     struct tgt_info *info)
1033 {
1034 	struct wlan_psoc_host_scan_radio_caps *param;
1035 	uint32_t num_scan_radio_caps;
1036 	uint8_t cap_idx;
1037 	QDF_STATUS status;
1038 
1039 	if (!event) {
1040 		target_if_err("Invalid event buffer");
1041 		return -EINVAL;
1042 	}
1043 
1044 	num_scan_radio_caps = info->service_ext2_param.num_scan_radio_caps;
1045 	target_if_debug("num scan radio capabilities = %d",
1046 			num_scan_radio_caps);
1047 
1048 	if (!num_scan_radio_caps)
1049 		return 0;
1050 
1051 	info->scan_radio_caps = qdf_mem_malloc(
1052 				sizeof(struct wlan_psoc_host_scan_radio_caps) *
1053 				num_scan_radio_caps);
1054 
1055 	if (!info->scan_radio_caps) {
1056 		target_if_err("Failed to allocate memory for scan radio caps");
1057 		return -EINVAL;
1058 	}
1059 
1060 	for (cap_idx = 0; cap_idx < num_scan_radio_caps; cap_idx++) {
1061 		param = &info->scan_radio_caps[cap_idx];
1062 		status = wmi_extract_scan_radio_cap_service_ready_ext2(
1063 				wmi_handle, event, cap_idx, param);
1064 		if (QDF_IS_STATUS_ERROR(status)) {
1065 			target_if_err("Extraction of scan radio cap failed");
1066 			goto free_and_return;
1067 		}
1068 	}
1069 
1070 	return 0;
1071 
1072 free_and_return:
1073 	qdf_mem_free(info->scan_radio_caps);
1074 	info->scan_radio_caps = NULL;
1075 
1076 	return qdf_status_to_os_return(status);
1077 }
1078 
init_deinit_scan_radio_cap_free(struct target_psoc_info * tgt_psoc_info)1079 QDF_STATUS init_deinit_scan_radio_cap_free(
1080 		struct target_psoc_info *tgt_psoc_info)
1081 {
1082 	qdf_mem_free(tgt_psoc_info->info.scan_radio_caps);
1083 	tgt_psoc_info->info.scan_radio_caps = NULL;
1084 
1085 	return QDF_STATUS_SUCCESS;
1086 }
1087 
1088 qdf_export_symbol(init_deinit_scan_radio_cap_free);
1089 
init_deinit_populate_msdu_idx_qtype_map_ext2(wmi_unified_t wmi_handle,uint8_t * event,struct tgt_info * info)1090 int init_deinit_populate_msdu_idx_qtype_map_ext2(wmi_unified_t wmi_handle,
1091 						 uint8_t *event,
1092 						 struct tgt_info *info)
1093 {
1094 	uint8_t *msdu_qtype;
1095 	uint32_t num_msdu_idx_qtype_map;
1096 	uint8_t msdu_idx;
1097 	QDF_STATUS status;
1098 
1099 	if (!event) {
1100 		target_if_err("Invalid event buffer");
1101 		return -EINVAL;
1102 	}
1103 
1104 	num_msdu_idx_qtype_map =
1105 		info->service_ext2_param.num_msdu_idx_qtype_map;
1106 	target_if_debug("num msdu_idx to qtype map = %d",
1107 			num_msdu_idx_qtype_map);
1108 
1109 	if (!num_msdu_idx_qtype_map)
1110 		return 0;
1111 
1112 	info->msdu_idx_qtype_map = qdf_mem_malloc(sizeof(uint8_t) *
1113 						  num_msdu_idx_qtype_map);
1114 
1115 	if (!info->msdu_idx_qtype_map) {
1116 		target_if_err("Failed to allocate memory for msdu idx qtype map");
1117 		return -EINVAL;
1118 	}
1119 
1120 	for (msdu_idx = 0; msdu_idx < num_msdu_idx_qtype_map; msdu_idx++) {
1121 		msdu_qtype = &info->msdu_idx_qtype_map[msdu_idx];
1122 		status = wmi_extract_msdu_idx_qtype_map_service_ready_ext2(
1123 				wmi_handle, event, msdu_idx, msdu_qtype);
1124 		if (QDF_IS_STATUS_ERROR(status)) {
1125 			target_if_err("Extraction of msdu idx qtype map failed");
1126 			goto free_and_return;
1127 		}
1128 	}
1129 
1130 	return 0;
1131 
1132 free_and_return:
1133 	qdf_mem_free(info->msdu_idx_qtype_map);
1134 	info->msdu_idx_qtype_map = NULL;
1135 
1136 	return qdf_status_to_os_return(status);
1137 }
1138 
init_deinit_msdu_idx_qtype_map_free(struct target_psoc_info * tgt_psoc_info)1139 QDF_STATUS init_deinit_msdu_idx_qtype_map_free(
1140 		struct target_psoc_info *tgt_psoc_info)
1141 {
1142 	qdf_mem_free(tgt_psoc_info->info.msdu_idx_qtype_map);
1143 	tgt_psoc_info->info.msdu_idx_qtype_map = NULL;
1144 
1145 	return QDF_STATUS_SUCCESS;
1146 }
1147 
1148 qdf_export_symbol(init_deinit_msdu_idx_qtype_map_free);
1149 
init_deinit_regdmn_160mhz_support(struct wlan_psoc_host_hal_reg_capabilities_ext * hal_cap)1150 static bool init_deinit_regdmn_160mhz_support(
1151 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
1152 {
1153 	return ((hal_cap->wireless_modes &
1154 		HOST_REGDMN_MODE_11AC_VHT160) != 0);
1155 }
1156 
init_deinit_regdmn_80p80mhz_support(struct wlan_psoc_host_hal_reg_capabilities_ext * hal_cap)1157 static bool init_deinit_regdmn_80p80mhz_support(
1158 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
1159 {
1160 	return ((hal_cap->wireless_modes &
1161 			HOST_REGDMN_MODE_11AC_VHT80_80) != 0);
1162 }
1163 
init_deinit_vht_160mhz_is_supported(uint32_t vhtcap)1164 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap)
1165 {
1166 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0);
1167 }
1168 
init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap)1169 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap)
1170 {
1171 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0);
1172 }
1173 
init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap)1174 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap)
1175 {
1176 	return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0);
1177 }
1178 
init_deinit_validate_160_80p80_fw_caps(struct wlan_objmgr_psoc * psoc,struct target_psoc_info * tgt_hdl)1179 QDF_STATUS init_deinit_validate_160_80p80_fw_caps(
1180 		 struct wlan_objmgr_psoc *psoc,
1181 		 struct target_psoc_info *tgt_hdl)
1182 {
1183 	bool wireless_mode_160mhz = false;
1184 	bool wireless_mode_80p80mhz = false;
1185 	bool vhtcap_160mhz = false;
1186 	bool vhtcap_80p80_160mhz = false;
1187 	bool vhtcap_160mhz_sgi = false;
1188 	bool valid = false;
1189 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
1190 	struct wmi_unified *wmi_handle;
1191 
1192 	if (!tgt_hdl) {
1193 		target_if_err(
1194 		"target_psoc_info is null in validate 160n80p80 cap check");
1195 		return QDF_STATUS_E_INVAL;
1196 	}
1197 
1198 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
1199 
1200 	if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) ||
1201 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) ||
1202 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCN6122) ||
1203 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCN9160) ||
1204 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290) ||
1205 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCN6432)) {
1206 		/**
1207 		 * Return true for now. This is not available in
1208 		 * qca8074 fw yet
1209 		 */
1210 		return QDF_STATUS_SUCCESS;
1211 	}
1212 
1213 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
1214 	if (!reg_cap) {
1215 		target_if_err("reg cap is NULL");
1216 		return QDF_STATUS_E_FAILURE;
1217 	}
1218 
1219 	/* NOTE: Host driver gets vht capability and supported channel
1220 	 * width / channel frequency range from FW/HALPHY and obeys it.
1221 	 * Host driver is unaware of any physical filters or any other
1222 	 * hardware factors that can impact these capabilities.
1223 	 * These need to be correctly determined by firmware.
1224 	 */
1225 
1226 	/*This table lists all valid and invalid combinations
1227 	 * WMODE160 WMODE80_80  VHTCAP_160 VHTCAP_80+80_160  IsCombinationvalid?
1228 	 *      0         0           0              0                 YES
1229 	 *      0         0           0              1                 NO
1230 	 *      0         0           1              0                 NO
1231 	 *      0         0           1              1                 NO
1232 	 *      0         1           0              0                 NO
1233 	 *      0         1           0              1                 NO
1234 	 *      0         1           1              0                 NO
1235 	 *      0         1           1              1                 NO
1236 	 *      1         0           0              0                 NO
1237 	 *      1         0           0              1                 NO
1238 	 *      1         0           1              0                 YES
1239 	 *      1         0           1              1                 NO
1240 	 *      1         1           0              0                 NO
1241 	 *      1         1           0              1                 YES
1242 	 *      1         1           1              0                 NO
1243 	 *      1         1           1              1                 NO
1244 	 */
1245 
1246 	/* NOTE: Last row in above table is invalid because value corresponding
1247 	 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per
1248 	 * 802.11ac. Only one of them can be set at a time.
1249 	 */
1250 
1251 	wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap);
1252 	wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap);
1253 	vhtcap_160mhz = init_deinit_vht_160mhz_is_supported(
1254 				tgt_hdl->info.target_caps.vht_cap_info);
1255 	vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported(
1256 				tgt_hdl->info.target_caps.vht_cap_info);
1257 	vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported(
1258 				tgt_hdl->info.target_caps.vht_cap_info);
1259 
1260 	if (!(wireless_mode_160mhz || wireless_mode_80p80mhz ||
1261 	      vhtcap_160mhz || vhtcap_80p80_160mhz)) {
1262 		valid = QDF_STATUS_SUCCESS;
1263 	} else if (wireless_mode_160mhz && !wireless_mode_80p80mhz &&
1264 		   vhtcap_160mhz && !vhtcap_80p80_160mhz) {
1265 		valid = QDF_STATUS_SUCCESS;
1266 	} else if (wireless_mode_160mhz && wireless_mode_80p80mhz &&
1267 		   !vhtcap_160mhz && vhtcap_160mhz_sgi) {
1268 		valid = QDF_STATUS_SUCCESS;
1269 	}
1270 
1271 	if (valid == QDF_STATUS_SUCCESS) {
1272 		/*
1273 		 * Ensure short GI for 160 MHz is enabled
1274 		 * only if 160/80+80 is supported.
1275 		 */
1276 		if (vhtcap_160mhz_sgi &&
1277 		    !(vhtcap_160mhz || vhtcap_80p80_160mhz)) {
1278 			valid = QDF_STATUS_E_FAILURE;
1279 		}
1280 	}
1281 
1282 	/* Invalid config specified by FW */
1283 	if (valid != QDF_STATUS_SUCCESS) {
1284 		target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first");
1285 		target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d",
1286 			      wireless_mode_160mhz, wireless_mode_80p80mhz);
1287 		target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d",
1288 			      vhtcap_160mhz, vhtcap_80p80_160mhz,
1289 			      vhtcap_160mhz_sgi);
1290 	}
1291 	return valid;
1292 }
1293 
init_deinit_chainmask_config(struct wlan_objmgr_psoc * psoc,struct target_psoc_info * tgt_hdl)1294 void init_deinit_chainmask_config(
1295 		 struct wlan_objmgr_psoc *psoc,
1296 		 struct target_psoc_info *tgt_hdl)
1297 {
1298 	tgt_hdl->info.wlan_res_cfg.tx_chain_mask =
1299 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
1300 	tgt_hdl->info.wlan_res_cfg.rx_chain_mask =
1301 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
1302 }
1303 
init_deinit_is_service_ext_msg(struct wlan_objmgr_psoc * psoc,struct target_psoc_info * tgt_hdl)1304 QDF_STATUS init_deinit_is_service_ext_msg(
1305 		 struct wlan_objmgr_psoc *psoc,
1306 		 struct target_psoc_info *tgt_hdl)
1307 {
1308 	struct wmi_unified *wmi_handle;
1309 
1310 	if (!tgt_hdl) {
1311 		target_if_err(
1312 			"psoc target_psoc_info is null in service ext msg");
1313 		return QDF_STATUS_E_INVAL;
1314 	}
1315 
1316 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
1317 
1318 	if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg))
1319 		return QDF_STATUS_SUCCESS;
1320 	else
1321 		return QDF_STATUS_E_FAILURE;
1322 }
1323 
init_deinit_is_preferred_hw_mode_supported(struct wlan_objmgr_psoc * psoc,struct target_psoc_info * tgt_hdl)1324 bool init_deinit_is_preferred_hw_mode_supported(
1325 		 struct wlan_objmgr_psoc *psoc,
1326 		 struct target_psoc_info *tgt_hdl)
1327 {
1328 	uint16_t i;
1329 	struct tgt_info *info;
1330 
1331 	if (!tgt_hdl) {
1332 		target_if_err(
1333 			"psoc target_psoc_info is null in service ext msg");
1334 		return FALSE;
1335 	}
1336 
1337 	info = &tgt_hdl->info;
1338 
1339 	if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
1340 		return TRUE;
1341 
1342 	if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) {
1343 		if (!wlan_psoc_nif_fw_ext_cap_get(psoc,
1344 					WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) {
1345 			target_if_err(
1346 			"WMI service bit for DYNAMIC HW mode is not set!");
1347 			return FALSE;
1348 		}
1349 	}
1350 
1351 	for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) {
1352 		if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode)
1353 			return TRUE;
1354 	}
1355 
1356 	return FALSE;
1357 }
1358 
init_deinit_wakeup_host_wait(struct wlan_objmgr_psoc * psoc,struct target_psoc_info * tgt_hdl)1359 void init_deinit_wakeup_host_wait(
1360 		 struct wlan_objmgr_psoc *psoc,
1361 		 struct target_psoc_info *tgt_hdl)
1362 {
1363 	if (!tgt_hdl) {
1364 		target_if_err("psoc target_psoc_info is null in target ready");
1365 		return;
1366 	}
1367 	qdf_event_set(&tgt_hdl->info.event);
1368 }
1369