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