xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022, 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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
251 	if (current_hw_mode > WMI_HOST_HW_MODE_MAX ||
252 	    new_hw_mode > WMI_HOST_HW_MODE_MAX)
253 		return false;
254 
255 	/* Above precedence is defined by low to high, lower the value
256 	 * higher the precedence
257 	 */
258 	if (hw_mode_id_precedence[current_hw_mode] >
259 	    hw_mode_id_precedence[new_hw_mode])
260 		return true;
261 
262 	return false;
263 }
264 
265 /**
266  * select_preferred_mode() - Select preferred hw mode based on current mode.
267  * @tgt_hdl: target_psoc_info object
268  * @hw_mode_caps: HW mode caps of new mode id that needs to checked for
269  *                selection.
270  * @current_mode: Current mode.
271  *
272  * API to select preferred hw mode based on the current config.
273  * Based on host config for preferred mode, final mode selected as follows-
274  * 1) If preferred_mode == WMI_HOST_HW_MODE_DETECT, Then select mode from FW
275  *    supported modes such that it is a super set of all modes FW advertises.
276  *    For e.g., If FW supports DBS(2 radio) and DBS_SBS(3 radio)- Choose DBS_SBS
277  * 2) If preferred_mode == WMI_HOST_HW_MODE_MAX, Then do not select any mode
278  *    from FW advertised modes. Host needs to maintain all modes supported in FW
279  *    and can switch dynamically.
280  * 3) Else, A valid preferred_mode is set, Hence check if this is part of FW
281  *    supported modes. If it is found, then use it to bring up the device.
282  *
283  * Return: selected_mode based on the above criteria.
284  */
285 static uint32_t
286 select_preferred_hw_mode(struct target_psoc_info *tgt_hdl,
287 			 struct wlan_psoc_host_hw_mode_caps *hw_mode_caps,
288 			 uint32_t current_mode)
289 {
290 	uint32_t preferred_mode, selected_mode = current_mode;
291 	struct tgt_info *info;
292 
293 	info = &tgt_hdl->info;
294 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
295 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
296 		uint32_t new_mode = hw_mode_caps->hw_mode_id;
297 
298 		/* Choose hw_mode_id based on precedence */
299 		if (new_hw_mode_preferred(selected_mode, new_mode)) {
300 			selected_mode = new_mode;
301 			qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps,
302 				     sizeof(info->hw_mode_cap));
303 		}
304 	} else if ((preferred_mode != WMI_HOST_HW_MODE_MAX) &&
305 		   (preferred_mode == hw_mode_caps->hw_mode_id)) {
306 		selected_mode = preferred_mode;
307 		qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps,
308 			     sizeof(info->hw_mode_cap));
309 	}
310 
311 	return selected_mode;
312 }
313 
314 #ifdef FEATURE_NO_DBS_INTRABAND_MCC_SUPPORT
315 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl,
316 					   struct wmi_unified *wmi_handle)
317 {
318 	struct tgt_info *info = &tgt_hdl->info;
319 
320 	if ((info->hw_modes.num_modes == 1) &&
321 	    (info->hw_modes.hw_mode_ids[0] == WMI_HOST_HW_MODE_DBS) &&
322 	    !wmi_service_enabled(wmi_handle,
323 				 wmi_service_dual_band_simultaneous_support))
324 		target_psoc_set_preferred_hw_mode(tgt_hdl,
325 						  WMI_HOST_HW_MODE_DETECT);
326 }
327 #else
328 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl,
329 					   struct wmi_unified *wmi_handle)
330 {
331 }
332 #endif
333 
334 int init_deinit_populate_hw_mode_capability(
335 		wmi_unified_t wmi_handle, uint8_t *event,
336 		struct target_psoc_info *tgt_hdl)
337 {
338 	QDF_STATUS status = QDF_STATUS_SUCCESS;
339 	uint8_t hw_idx;
340 	uint32_t num_hw_modes;
341 	struct wlan_psoc_host_hw_mode_caps hw_mode_caps[PSOC_MAX_HW_MODE];
342 	uint32_t preferred_mode, selected_mode = WMI_HOST_HW_MODE_MAX;
343 	struct tgt_info *info;
344 
345 	info = &tgt_hdl->info;
346 	num_hw_modes = info->service_ext_param.num_hw_modes;
347 	if (num_hw_modes > PSOC_MAX_HW_MODE) {
348 		target_if_err("invalid num_hw_modes %d", num_hw_modes);
349 		return -EINVAL;
350 	}
351 	target_if_debug("num_hw_modes %d", num_hw_modes);
352 
353 	qdf_mem_zero(&hw_mode_caps, sizeof(hw_mode_caps));
354 	info->hw_modes.num_modes = 0;
355 	info->hw_mode_cap.hw_mode_id = WMI_HOST_HW_MODE_MAX;
356 
357 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
358 		status = get_hw_mode(wmi_handle, event, hw_idx,
359 						&hw_mode_caps[hw_idx]);
360 		if (status)
361 			goto return_exit;
362 
363 		if (hw_idx < WMI_HOST_HW_MODE_MAX) {
364 			info->hw_modes.hw_mode_ids[hw_idx] =
365 				hw_mode_caps[hw_idx].hw_mode_id;
366 			info->hw_modes.phy_bit_map[hw_idx] =
367 				hw_mode_caps[hw_idx].phy_id_map;
368 			info->hw_modes.num_modes++;
369 		}
370 
371 		status = init_deinit_populate_mac_phy_capability(wmi_handle,
372 				event, &hw_mode_caps[hw_idx], info);
373 		if (status)
374 			goto return_exit;
375 
376 		if (num_hw_modes == 1)
377 			init_deinit_change_def_hw_mode(tgt_hdl, wmi_handle);
378 
379 		selected_mode = select_preferred_hw_mode(tgt_hdl,
380 							 &hw_mode_caps[hw_idx],
381 							 selected_mode);
382 	}
383 
384 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
385 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
386 		target_if_info("Preferred mode is not set, use mode id %d\n",
387 			       selected_mode);
388 		target_psoc_set_preferred_hw_mode(tgt_hdl, selected_mode);
389 
390 		/* Change default DBS hw mode as per selected one */
391 		info->target_caps.default_dbs_hw_mode_index = selected_mode;
392 	}
393 
394 	status = get_sar_version(wmi_handle, event, &info->service_ext_param);
395 	target_if_debug("sar version %d", info->service_ext_param.sar_version);
396 
397 return_exit:
398 	return qdf_status_to_os_return(status);
399 }
400 
401 int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc,
402 				      wmi_unified_t handle, uint8_t *event,
403 				      struct tgt_info *info)
404 
405 {
406 	uint8_t cap_idx;
407 	uint32_t num_dbr_ring_caps;
408 	QDF_STATUS status = QDF_STATUS_SUCCESS;
409 
410 	num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps;
411 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
412 
413 	if (!num_dbr_ring_caps)
414 		return 0;
415 
416 	info->dbr_ring_cap = qdf_mem_malloc(
417 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
418 				num_dbr_ring_caps);
419 
420 	if (!info->dbr_ring_cap)
421 		return -EINVAL;
422 
423 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
424 		status = wmi_extract_dbr_ring_cap_service_ready_ext(handle,
425 				event, cap_idx,
426 				&(info->dbr_ring_cap[cap_idx]));
427 		if (QDF_IS_STATUS_ERROR(status)) {
428 			target_if_err("Extraction of DMA cap failed");
429 			goto free_and_return;
430 		}
431 	}
432 
433 	return 0;
434 
435 free_and_return:
436 	qdf_mem_free(info->dbr_ring_cap);
437 	info->dbr_ring_cap = NULL;
438 
439 	return qdf_status_to_os_return(status);
440 }
441 
442 int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc,
443 					   wmi_unified_t handle, uint8_t *event,
444 					   struct tgt_info *info)
445 
446 {
447 	uint8_t cap_idx;
448 	uint32_t num_dbr_ring_caps;
449 	QDF_STATUS status = QDF_STATUS_SUCCESS;
450 	struct wlan_psoc_host_dbr_ring_caps *param;
451 
452 	/*
453 	 * If FW had already sent this info as part of EXT event,
454 	 * we need to discard the same and use the info from EXT2.
455 	 */
456 	if (info->service_ext_param.num_dbr_ring_caps) {
457 		target_if_debug("dbr_ring_caps already populated");
458 		info->service_ext_param.num_dbr_ring_caps = 0;
459 		qdf_mem_free(info->dbr_ring_cap);
460 		info->dbr_ring_cap = NULL;
461 	}
462 
463 	num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps;
464 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
465 
466 	if (!num_dbr_ring_caps)
467 		return 0;
468 
469 	info->dbr_ring_cap = qdf_mem_malloc(
470 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
471 				num_dbr_ring_caps);
472 
473 	if (!info->dbr_ring_cap)
474 		return -EINVAL;
475 
476 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
477 		param = &info->dbr_ring_cap[cap_idx];
478 		status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle,
479 								     event,
480 								     cap_idx,
481 								     param);
482 		if (QDF_IS_STATUS_ERROR(status)) {
483 			target_if_err("Extraction of DMA cap failed");
484 			goto free_and_return;
485 		}
486 	}
487 
488 	return 0;
489 
490 free_and_return:
491 	qdf_mem_free(info->dbr_ring_cap);
492 	info->dbr_ring_cap = NULL;
493 
494 	return qdf_status_to_os_return(status);
495 }
496 int init_deinit_populate_spectral_bin_scale_params(
497 			struct wlan_objmgr_psoc *psoc, wmi_unified_t handle,
498 			uint8_t *event, struct tgt_info *info)
499 
500 {
501 	uint8_t param_idx;
502 	uint32_t num_bin_scaling_params;
503 	QDF_STATUS status = QDF_STATUS_SUCCESS;
504 
505 	num_bin_scaling_params = info->service_ext_param.num_bin_scaling_params;
506 
507 	if (!num_bin_scaling_params)
508 		return 0;
509 
510 	info->scaling_params = qdf_mem_malloc(
511 		sizeof(struct wlan_psoc_host_spectral_scaling_params) *
512 		num_bin_scaling_params);
513 
514 	if (!info->scaling_params) {
515 		target_if_err("Mem alloc for bin scaling params failed");
516 		return -EINVAL;
517 	}
518 
519 	for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) {
520 		status = wmi_extract_spectral_scaling_params_service_ready_ext(
521 				handle,
522 				event, param_idx,
523 				&info->scaling_params[param_idx]);
524 		if (QDF_IS_STATUS_ERROR(status)) {
525 			target_if_err("Extraction of scaling params failed");
526 			goto free_and_return;
527 		}
528 	}
529 
530 	return 0;
531 
532 free_and_return:
533 	qdf_mem_free(info->scaling_params);
534 	info->scaling_params = NULL;
535 
536 	return qdf_status_to_os_return(status);
537 }
538 
539 #ifdef WLAN_SUPPORT_TWT
540 int init_deinit_populate_twt_cap_ext2(struct wlan_objmgr_psoc *psoc,
541 				      wmi_unified_t handle, uint8_t *event,
542 				      struct tgt_info *info)
543 {
544 	struct wmi_twt_cap_bitmap_params param;
545 	struct target_psoc_info *psoc_info;
546 	QDF_STATUS status = QDF_STATUS_SUCCESS;
547 
548 	status = wmi_extract_twt_cap_service_ready_ext2(handle, event,
549 							&param);
550 	if (QDF_IS_STATUS_ERROR(status)) {
551 		target_if_err("Extraction of twt capability failed");
552 		goto exit;
553 	}
554 
555 	psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
556 
557 	target_psoc_set_twt_ack_cap(psoc_info, param.twt_ack_support_cap);
558 
559 exit:
560 	return qdf_status_to_os_return(status);
561 }
562 #endif
563 
564 int init_deinit_populate_dbs_or_sbs_cap_ext2(struct wlan_objmgr_psoc *psoc,
565 					     wmi_unified_t handle,
566 					     uint8_t *event,
567 					     struct tgt_info *info)
568 {
569 	uint32_t sbs_lower_band_end_freq;
570 	struct target_psoc_info *psoc_info;
571 	QDF_STATUS status = QDF_STATUS_SUCCESS;
572 
573 	status = wmi_extract_dbs_or_sbs_cap_service_ready_ext2(handle, event,
574 						&sbs_lower_band_end_freq);
575 	if (QDF_IS_STATUS_ERROR(status)) {
576 		target_if_err("Extraction of twt capability failed");
577 		goto exit;
578 	}
579 	psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
580 	target_psoc_set_sbs_lower_band_end(psoc_info, sbs_lower_band_end_freq);
581 
582 exit:
583 	return qdf_status_to_os_return(status);
584 }
585 
586 
587 QDF_STATUS init_deinit_dbr_ring_cap_free(
588 		struct target_psoc_info *tgt_psoc_info)
589 {
590 	QDF_STATUS status = QDF_STATUS_SUCCESS;
591 
592 	if (tgt_psoc_info->info.dbr_ring_cap) {
593 		qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap);
594 		tgt_psoc_info->info.dbr_ring_cap = NULL;
595 	}
596 
597 	return status;
598 }
599 qdf_export_symbol(init_deinit_dbr_ring_cap_free);
600 
601 QDF_STATUS init_deinit_spectral_scaling_params_free(
602 		struct target_psoc_info *tgt_psoc_info)
603 {
604 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
605 
606 	if (tgt_psoc_info->info.scaling_params) {
607 		qdf_mem_free(tgt_psoc_info->info.scaling_params);
608 		tgt_psoc_info->info.scaling_params = NULL;
609 		status = QDF_STATUS_SUCCESS;
610 	}
611 
612 	return status;
613 }
614 
615 qdf_export_symbol(init_deinit_spectral_scaling_params_free);
616 
617 #ifdef DBS_SBS_BAND_LIMITATION_WAR
618 #define phy0               0
619 #define phy2               2
620 #define NUM_RF_MODES       2 /* (DBS + DBS_SBS) */
621 /**
622  * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0.
623  * @psoc: PSOC common object
624  * @info: FW or lower layer related info
625  * @wlan_psoc_host_hal_reg_capabilities_ext: Reg caps per PHY
626  *
627  * For the DBS_SBS capable board, update the low or high frequency
628  * for phy0 by leveraging the frequency populated for phy2
629  * depending on whether it is mapped to upper or lower 5G band by
630  * FW/HAL-PHY.
631  */
632 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
633 					struct tgt_info *info,
634 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
635 {
636 	struct target_psoc_info *tgt_hdl;
637 	enum wmi_host_hw_mode_config_type mode;
638 	uint32_t num_hw_modes;
639 	uint8_t idx;
640 
641 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
642 						psoc);
643 	if (!tgt_hdl) {
644 		target_if_err("target_psoc_info is null in service ready ev");
645 		return;
646 	}
647 
648 	mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
649 
650 	num_hw_modes = info->hw_modes.num_modes;
651 
652 	if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES))
653 		return;
654 
655 	for (idx = 0; idx < num_hw_modes; idx++)
656 		if (info->hw_modes.hw_mode_ids[idx] ==
657 			WMI_HOST_HW_MODE_DBS_SBS) {
658 			if (reg_cap[phy0].low_5ghz_chan >
659 					reg_cap[phy2].low_5ghz_chan)
660 				reg_cap[phy0].low_5ghz_chan =
661 				    reg_cap[phy2].low_5ghz_chan;
662 			else if (reg_cap[phy0].high_5ghz_chan <
663 					reg_cap[phy2].high_5ghz_chan)
664 				reg_cap[phy0].high_5ghz_chan =
665 				    reg_cap[phy2].high_5ghz_chan;
666 			break;
667 		}
668 }
669 #else
670 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
671 					struct tgt_info *info,
672 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
673 {
674 }
675 #endif
676 
677 /**
678  * init_deinit_fill_host_reg_cap() - Fill the host regulatory cap
679  * with target hal reg capabilities.
680  * @cap: Pointer to wlan_psoc_hal_reg_capability where FW capabilities
681  * are extracted.
682  * @reg_cap: Pointer to wlan_psoc_host_hal_reg_capabilities_ext, host reg
683  * capabilities to be filled.
684  *
685  * Return - None
686  */
687 static void
688 init_deinit_fill_host_reg_cap(struct wlan_psoc_hal_reg_capability *cap,
689 			      struct wlan_psoc_host_hal_reg_capabilities_ext
690 			      *reg_cap)
691 {
692 	reg_cap->phy_id = 0;
693 	reg_cap->eeprom_reg_domain = cap->eeprom_rd;
694 	reg_cap->eeprom_reg_domain_ext = cap->eeprom_rd_ext;
695 	reg_cap->regcap1 = cap->regcap1;
696 	reg_cap->regcap2 = cap->regcap2;
697 	reg_cap->wireless_modes = (uint64_t)cap->wireless_modes;
698 	reg_cap->low_2ghz_chan = cap->low_2ghz_chan;
699 	reg_cap->high_2ghz_chan = cap->high_2ghz_chan;
700 	reg_cap->low_5ghz_chan = cap->low_5ghz_chan;
701 	reg_cap->high_5ghz_chan = cap->high_5ghz_chan;
702 }
703 
704 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
705 				     wmi_unified_t handle, uint8_t *event,
706 				     struct tgt_info *info,
707 				     bool service_ready)
708 {
709 	uint8_t reg_idx;
710 	uint32_t num_phy_reg_cap;
711 	QDF_STATUS status = QDF_STATUS_SUCCESS;
712 	struct wlan_psoc_hal_reg_capability cap;
713 	struct wlan_psoc_host_hal_reg_capabilities_ext
714 				reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
715 
716 	if (service_ready) {
717 		status = wmi_extract_hal_reg_cap(handle, event, &cap);
718 		if (QDF_IS_STATUS_ERROR(status)) {
719 			target_if_err("failed to parse hal reg cap");
720 			return qdf_status_to_os_return(status);
721 		}
722 		info->service_ext_param.num_phy = 1;
723 		num_phy_reg_cap = 1;
724 		init_deinit_fill_host_reg_cap(&cap, &reg_cap[0]);
725 		target_if_debug("FW wireless modes 0x%llx",
726 				reg_cap[0].wireless_modes);
727 	} else {
728 		num_phy_reg_cap = info->service_ext_param.num_phy;
729 		if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
730 			target_if_err("Invalid num_phy_reg_cap %d",
731 				      num_phy_reg_cap);
732 			return -EINVAL;
733 		}
734 		target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap);
735 
736 		for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
737 			status = wmi_extract_reg_cap_service_ready_ext(handle,
738 					event, reg_idx, &(reg_cap[reg_idx]));
739 			if (QDF_IS_STATUS_ERROR(status)) {
740 				target_if_err("failed to parse reg cap");
741 				return qdf_status_to_os_return(status);
742 			}
743 		}
744 	}
745 
746 	init_deinit_update_phy_reg_cap(psoc, info, reg_cap);
747 	status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap);
748 
749 	return qdf_status_to_os_return(status);
750 }
751 
752 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle,
753 					  uint8_t *event,
754 					  struct tgt_info *info)
755 {
756 	uint32_t num_hw_modes;
757 	uint8_t hw_idx;
758 	uint32_t hw_mode_id;
759 	uint32_t phy_bit_map;
760 	uint8_t phy_id;
761 	uint8_t mac_phy_count = 0;
762 	QDF_STATUS status = QDF_STATUS_SUCCESS;
763 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
764 	struct wlan_psoc_host_mac_phy_caps_ext2 *mac_phy_caps_ext2;
765 
766 	if (!event)
767 		return -EINVAL;
768 
769 	num_hw_modes = info->hw_modes.num_modes;
770 
771 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
772 		hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx];
773 		phy_bit_map = info->hw_modes.phy_bit_map[hw_idx];
774 
775 		phy_id = info->mac_phy_cap[mac_phy_count].phy_id;
776 		while (phy_bit_map) {
777 			if (mac_phy_count >= info->total_mac_phy_cnt) {
778 				target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d",
779 					      info->total_mac_phy_cnt,
780 					      mac_phy_count);
781 				return -EINVAL;
782 			}
783 
784 			mac_phy_cap = &info->mac_phy_cap[mac_phy_count];
785 			mac_phy_caps_ext2 =
786 				&info->mac_phy_caps_ext2[mac_phy_count];
787 			status = wmi_extract_mac_phy_cap_service_ready_ext2(
788 					wmi_handle, event, hw_mode_id, phy_id,
789 					mac_phy_cap->phy_idx,
790 					mac_phy_caps_ext2);
791 
792 			if (QDF_IS_STATUS_ERROR(status)) {
793 				target_if_err("failed to parse mac phy capability ext2");
794 				return qdf_status_to_os_return(status);
795 			}
796 
797 			mac_phy_cap->reg_cap_ext.wireless_modes |=
798 				mac_phy_caps_ext2[phy_id].wireless_modes_ext;
799 
800 			mac_phy_count++;
801 			phy_bit_map &= (phy_bit_map - 1);
802 			phy_id++;
803 		}
804 	}
805 
806 	return 0;
807 }
808 
809 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle,
810 					  uint8_t *event,
811 					  struct tgt_info *info)
812 {
813 	struct wlan_psoc_host_hal_reg_capabilities_ext2
814 		reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
815 	struct wlan_objmgr_psoc *psoc;
816 	uint32_t num_phy_reg_cap;
817 	uint8_t reg_idx;
818 	QDF_STATUS status = QDF_STATUS_SUCCESS;
819 
820 	if (!event) {
821 		target_if_err("event buffer is null");
822 		return -EINVAL;
823 	}
824 
825 	psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle);
826 	if (!psoc) {
827 		target_if_err("psoc is null");
828 		return -EINVAL;
829 	}
830 
831 	num_phy_reg_cap = info->service_ext_param.num_phy;
832 	if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
833 		target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap);
834 		return -EINVAL;
835 	}
836 
837 	for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
838 		status = wmi_extract_hal_reg_cap_ext2(
839 				wmi_handle, event, reg_idx, &reg_cap[reg_idx]);
840 		if (QDF_IS_STATUS_ERROR(status)) {
841 			target_if_err("failed to parse hal reg cap ext2");
842 			return qdf_status_to_os_return(status);
843 		}
844 
845 		status = ucfg_reg_update_hal_reg_cap(
846 				psoc, reg_cap[reg_idx].wireless_modes_ext,
847 				reg_idx);
848 		if (QDF_IS_STATUS_ERROR(status)) {
849 			target_if_err("Failed to update hal reg cap");
850 			return qdf_status_to_os_return(status);
851 		}
852 	}
853 
854 	return 0;
855 }
856 
857 int init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle,
858 					     uint8_t *event,
859 					     struct tgt_info *info)
860 {
861 	struct wlan_psoc_host_scan_radio_caps *param;
862 	uint32_t num_scan_radio_caps;
863 	uint8_t cap_idx;
864 	QDF_STATUS status;
865 
866 	if (!event) {
867 		target_if_err("Invalid event buffer");
868 		return -EINVAL;
869 	}
870 
871 	num_scan_radio_caps = info->service_ext2_param.num_scan_radio_caps;
872 	target_if_debug("num scan radio capabilities = %d",
873 			num_scan_radio_caps);
874 
875 	if (!num_scan_radio_caps)
876 		return 0;
877 
878 	info->scan_radio_caps = qdf_mem_malloc(
879 				sizeof(struct wlan_psoc_host_scan_radio_caps) *
880 				num_scan_radio_caps);
881 
882 	if (!info->scan_radio_caps) {
883 		target_if_err("Failed to allocate memory for scan radio caps");
884 		return -EINVAL;
885 	}
886 
887 	for (cap_idx = 0; cap_idx < num_scan_radio_caps; cap_idx++) {
888 		param = &info->scan_radio_caps[cap_idx];
889 		status = wmi_extract_scan_radio_cap_service_ready_ext2(
890 				wmi_handle, event, cap_idx, param);
891 		if (QDF_IS_STATUS_ERROR(status)) {
892 			target_if_err("Extraction of scan radio cap failed");
893 			goto free_and_return;
894 		}
895 	}
896 
897 	return 0;
898 
899 free_and_return:
900 	qdf_mem_free(info->scan_radio_caps);
901 	info->scan_radio_caps = NULL;
902 
903 	return qdf_status_to_os_return(status);
904 }
905 
906 QDF_STATUS init_deinit_scan_radio_cap_free(
907 		struct target_psoc_info *tgt_psoc_info)
908 {
909 	qdf_mem_free(tgt_psoc_info->info.scan_radio_caps);
910 	tgt_psoc_info->info.scan_radio_caps = NULL;
911 
912 	return QDF_STATUS_SUCCESS;
913 }
914 
915 qdf_export_symbol(init_deinit_scan_radio_cap_free);
916 
917 static bool init_deinit_regdmn_160mhz_support(
918 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
919 {
920 	return ((hal_cap->wireless_modes &
921 		HOST_REGDMN_MODE_11AC_VHT160) != 0);
922 }
923 
924 static bool init_deinit_regdmn_80p80mhz_support(
925 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
926 {
927 	return ((hal_cap->wireless_modes &
928 			HOST_REGDMN_MODE_11AC_VHT80_80) != 0);
929 }
930 
931 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap)
932 {
933 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0);
934 }
935 
936 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap)
937 {
938 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0);
939 }
940 
941 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap)
942 {
943 	return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0);
944 }
945 
946 QDF_STATUS init_deinit_validate_160_80p80_fw_caps(
947 		 struct wlan_objmgr_psoc *psoc,
948 		 struct target_psoc_info *tgt_hdl)
949 {
950 	bool wireless_mode_160mhz = false;
951 	bool wireless_mode_80p80mhz = false;
952 	bool vhtcap_160mhz = false;
953 	bool vhtcap_80p80_160mhz = false;
954 	bool vhtcap_160mhz_sgi = false;
955 	bool valid = false;
956 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
957 	struct wmi_unified *wmi_handle;
958 
959 	if (!tgt_hdl) {
960 		target_if_err(
961 		"target_psoc_info is null in validate 160n80p80 cap check");
962 		return QDF_STATUS_E_INVAL;
963 	}
964 
965 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
966 
967 	if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) ||
968 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) ||
969 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCN6122) ||
970 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCN9160) ||
971 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290)) {
972 		/**
973 		 * Return true for now. This is not available in
974 		 * qca8074 fw yet
975 		 */
976 		return QDF_STATUS_SUCCESS;
977 	}
978 
979 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
980 	if (!reg_cap) {
981 		target_if_err("reg cap is NULL");
982 		return QDF_STATUS_E_FAILURE;
983 	}
984 
985 	/* NOTE: Host driver gets vht capability and supported channel
986 	 * width / channel frequency range from FW/HALPHY and obeys it.
987 	 * Host driver is unaware of any physical filters or any other
988 	 * hardware factors that can impact these capabilities.
989 	 * These need to be correctly determined by firmware.
990 	 */
991 
992 	/*This table lists all valid and invalid combinations
993 	 * WMODE160 WMODE80_80  VHTCAP_160 VHTCAP_80+80_160  IsCombinationvalid?
994 	 *      0         0           0              0                 YES
995 	 *      0         0           0              1                 NO
996 	 *      0         0           1              0                 NO
997 	 *      0         0           1              1                 NO
998 	 *      0         1           0              0                 NO
999 	 *      0         1           0              1                 NO
1000 	 *      0         1           1              0                 NO
1001 	 *      0         1           1              1                 NO
1002 	 *      1         0           0              0                 NO
1003 	 *      1         0           0              1                 NO
1004 	 *      1         0           1              0                 YES
1005 	 *      1         0           1              1                 NO
1006 	 *      1         1           0              0                 NO
1007 	 *      1         1           0              1                 YES
1008 	 *      1         1           1              0                 NO
1009 	 *      1         1           1              1                 NO
1010 	 */
1011 
1012 	/* NOTE: Last row in above table is invalid because value corresponding
1013 	 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per
1014 	 * 802.11ac. Only one of them can be set at a time.
1015 	 */
1016 
1017 	wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap);
1018 	wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap);
1019 	vhtcap_160mhz = init_deinit_vht_160mhz_is_supported(
1020 				tgt_hdl->info.target_caps.vht_cap_info);
1021 	vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported(
1022 				tgt_hdl->info.target_caps.vht_cap_info);
1023 	vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported(
1024 				tgt_hdl->info.target_caps.vht_cap_info);
1025 
1026 	if (!(wireless_mode_160mhz || wireless_mode_80p80mhz ||
1027 	      vhtcap_160mhz || vhtcap_80p80_160mhz)) {
1028 		valid = QDF_STATUS_SUCCESS;
1029 	} else if (wireless_mode_160mhz && !wireless_mode_80p80mhz &&
1030 		   vhtcap_160mhz && !vhtcap_80p80_160mhz) {
1031 		valid = QDF_STATUS_SUCCESS;
1032 	} else if (wireless_mode_160mhz && wireless_mode_80p80mhz &&
1033 		   !vhtcap_160mhz && vhtcap_160mhz_sgi) {
1034 		valid = QDF_STATUS_SUCCESS;
1035 	}
1036 
1037 	if (valid == QDF_STATUS_SUCCESS) {
1038 		/*
1039 		 * Ensure short GI for 160 MHz is enabled
1040 		 * only if 160/80+80 is supported.
1041 		 */
1042 		if (vhtcap_160mhz_sgi &&
1043 		    !(vhtcap_160mhz || vhtcap_80p80_160mhz)) {
1044 			valid = QDF_STATUS_E_FAILURE;
1045 		}
1046 	}
1047 
1048 	/* Invalid config specified by FW */
1049 	if (valid != QDF_STATUS_SUCCESS) {
1050 		target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first");
1051 		target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d",
1052 			      wireless_mode_160mhz, wireless_mode_80p80mhz);
1053 		target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d",
1054 			      vhtcap_160mhz, vhtcap_80p80_160mhz,
1055 			      vhtcap_160mhz_sgi);
1056 	}
1057 	return valid;
1058 }
1059 
1060 void init_deinit_chainmask_config(
1061 		 struct wlan_objmgr_psoc *psoc,
1062 		 struct target_psoc_info *tgt_hdl)
1063 {
1064 	tgt_hdl->info.wlan_res_cfg.tx_chain_mask =
1065 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
1066 	tgt_hdl->info.wlan_res_cfg.rx_chain_mask =
1067 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
1068 }
1069 
1070 QDF_STATUS init_deinit_is_service_ext_msg(
1071 		 struct wlan_objmgr_psoc *psoc,
1072 		 struct target_psoc_info *tgt_hdl)
1073 {
1074 	struct wmi_unified *wmi_handle;
1075 
1076 	if (!tgt_hdl) {
1077 		target_if_err(
1078 			"psoc target_psoc_info is null in service ext msg");
1079 		return QDF_STATUS_E_INVAL;
1080 	}
1081 
1082 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
1083 
1084 	if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg))
1085 		return QDF_STATUS_SUCCESS;
1086 	else
1087 		return QDF_STATUS_E_FAILURE;
1088 }
1089 
1090 bool init_deinit_is_preferred_hw_mode_supported(
1091 		 struct wlan_objmgr_psoc *psoc,
1092 		 struct target_psoc_info *tgt_hdl)
1093 {
1094 	uint16_t i;
1095 	struct tgt_info *info;
1096 
1097 	if (!tgt_hdl) {
1098 		target_if_err(
1099 			"psoc target_psoc_info is null in service ext msg");
1100 		return FALSE;
1101 	}
1102 
1103 	info = &tgt_hdl->info;
1104 
1105 	if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
1106 		return TRUE;
1107 
1108 	if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) {
1109 		if (!wlan_psoc_nif_fw_ext_cap_get(psoc,
1110 					WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) {
1111 			target_if_err(
1112 			"WMI service bit for DYNAMIC HW mode is not set!");
1113 			return FALSE;
1114 		}
1115 	}
1116 
1117 	for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) {
1118 		if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode)
1119 			return TRUE;
1120 	}
1121 
1122 	return FALSE;
1123 }
1124 
1125 void init_deinit_wakeup_host_wait(
1126 		 struct wlan_objmgr_psoc *psoc,
1127 		 struct target_psoc_info *tgt_hdl)
1128 {
1129 	if (!tgt_hdl) {
1130 		target_if_err("psoc target_psoc_info is null in target ready");
1131 		return;
1132 	}
1133 	qdf_event_set(&tgt_hdl->info.event);
1134 }
1135