xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c (revision 6d768494e5ce14eb1603a695c86739d12ecc6ec2)
1 /*
2  * Copyright (c) 2017-2020 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 int init_deinit_populate_hw_mode_capability(
314 		wmi_unified_t wmi_handle, uint8_t *event,
315 		struct target_psoc_info *tgt_hdl)
316 {
317 	QDF_STATUS status = QDF_STATUS_SUCCESS;
318 	uint8_t hw_idx;
319 	uint32_t num_hw_modes;
320 	struct wlan_psoc_host_hw_mode_caps hw_mode_caps[PSOC_MAX_HW_MODE];
321 	uint32_t preferred_mode, selected_mode = WMI_HOST_HW_MODE_MAX;
322 	struct tgt_info *info;
323 
324 	info = &tgt_hdl->info;
325 	num_hw_modes = info->service_ext_param.num_hw_modes;
326 	if (num_hw_modes > PSOC_MAX_HW_MODE) {
327 		target_if_err("invalid num_hw_modes %d", num_hw_modes);
328 		return -EINVAL;
329 	}
330 	target_if_debug("num_hw_modes %d", num_hw_modes);
331 
332 	qdf_mem_zero(&hw_mode_caps, sizeof(hw_mode_caps));
333 	info->hw_modes.num_modes = 0;
334 	info->hw_mode_cap.hw_mode_id = WMI_HOST_HW_MODE_MAX;
335 
336 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
337 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
338 		status = get_hw_mode(wmi_handle, event, hw_idx,
339 						&hw_mode_caps[hw_idx]);
340 		if (status)
341 			goto return_exit;
342 
343 		if (hw_idx < WMI_HOST_HW_MODE_MAX) {
344 			info->hw_modes.hw_mode_ids[hw_idx] =
345 				hw_mode_caps[hw_idx].hw_mode_id;
346 			info->hw_modes.phy_bit_map[hw_idx] =
347 				hw_mode_caps[hw_idx].phy_id_map;
348 			info->hw_modes.num_modes++;
349 		}
350 
351 		status = init_deinit_populate_mac_phy_capability(wmi_handle,
352 				event, &hw_mode_caps[hw_idx], info);
353 		if (status)
354 			goto return_exit;
355 
356 		selected_mode = select_preferred_hw_mode(tgt_hdl,
357 							 &hw_mode_caps[hw_idx],
358 							 selected_mode);
359 	}
360 
361 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
362 		target_if_info("Preferred mode is not set, use mode id %d\n",
363 			       selected_mode);
364 		target_psoc_set_preferred_hw_mode(tgt_hdl, selected_mode);
365 
366 		/* Change default DBS hw mode as per selected one */
367 		info->target_caps.default_dbs_hw_mode_index = selected_mode;
368 	}
369 
370 	status = get_sar_version(wmi_handle, event, &info->service_ext_param);
371 	target_if_debug("sar version %d", info->service_ext_param.sar_version);
372 
373 return_exit:
374 	return qdf_status_to_os_return(status);
375 }
376 
377 int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc,
378 				      wmi_unified_t handle, uint8_t *event,
379 				      struct tgt_info *info)
380 
381 {
382 	uint8_t cap_idx;
383 	uint32_t num_dbr_ring_caps;
384 	QDF_STATUS status = QDF_STATUS_SUCCESS;
385 
386 	num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps;
387 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
388 
389 	if (!num_dbr_ring_caps)
390 		return 0;
391 
392 	info->dbr_ring_cap = qdf_mem_malloc(
393 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
394 				num_dbr_ring_caps);
395 
396 	if (!info->dbr_ring_cap)
397 		return -EINVAL;
398 
399 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
400 		status = wmi_extract_dbr_ring_cap_service_ready_ext(handle,
401 				event, cap_idx,
402 				&(info->dbr_ring_cap[cap_idx]));
403 		if (QDF_IS_STATUS_ERROR(status)) {
404 			target_if_err("Extraction of DMA cap failed");
405 			goto free_and_return;
406 		}
407 	}
408 
409 	return 0;
410 
411 free_and_return:
412 	qdf_mem_free(info->dbr_ring_cap);
413 	info->dbr_ring_cap = NULL;
414 
415 	return qdf_status_to_os_return(status);
416 }
417 
418 int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc,
419 					   wmi_unified_t handle, uint8_t *event,
420 					   struct tgt_info *info)
421 
422 {
423 	uint8_t cap_idx;
424 	uint32_t num_dbr_ring_caps;
425 	QDF_STATUS status = QDF_STATUS_SUCCESS;
426 	struct wlan_psoc_host_dbr_ring_caps *param;
427 
428 	/*
429 	 * If FW had already sent this info as part of EXT event,
430 	 * we need to discard the same and use the info from EXT2.
431 	 */
432 	if (info->service_ext_param.num_dbr_ring_caps) {
433 		target_if_debug("dbr_ring_caps already populated");
434 		info->service_ext_param.num_dbr_ring_caps = 0;
435 		qdf_mem_free(info->dbr_ring_cap);
436 		info->dbr_ring_cap = NULL;
437 	}
438 
439 	num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps;
440 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
441 
442 	if (!num_dbr_ring_caps)
443 		return 0;
444 
445 	info->dbr_ring_cap = qdf_mem_malloc(
446 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
447 				num_dbr_ring_caps);
448 
449 	if (!info->dbr_ring_cap)
450 		return -EINVAL;
451 
452 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
453 		param = &info->dbr_ring_cap[cap_idx];
454 		status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle,
455 								     event,
456 								     cap_idx,
457 								     param);
458 		if (QDF_IS_STATUS_ERROR(status)) {
459 			target_if_err("Extraction of DMA cap failed");
460 			goto free_and_return;
461 		}
462 	}
463 
464 	return 0;
465 
466 free_and_return:
467 	qdf_mem_free(info->dbr_ring_cap);
468 	info->dbr_ring_cap = NULL;
469 
470 	return qdf_status_to_os_return(status);
471 }
472 int init_deinit_populate_spectral_bin_scale_params(
473 			struct wlan_objmgr_psoc *psoc, wmi_unified_t handle,
474 			uint8_t *event, struct tgt_info *info)
475 
476 {
477 	uint8_t param_idx;
478 	uint32_t num_bin_scaling_params;
479 	QDF_STATUS status = QDF_STATUS_SUCCESS;
480 
481 	num_bin_scaling_params = info->service_ext_param.num_bin_scaling_params;
482 
483 	if (!num_bin_scaling_params)
484 		return 0;
485 
486 	info->scaling_params = qdf_mem_malloc(
487 		sizeof(struct wlan_psoc_host_spectral_scaling_params) *
488 		num_bin_scaling_params);
489 
490 	if (!info->scaling_params) {
491 		target_if_err("Mem alloc for bin scaling params failed");
492 		return -EINVAL;
493 	}
494 
495 	for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) {
496 		status = wmi_extract_spectral_scaling_params_service_ready_ext(
497 				handle,
498 				event, param_idx,
499 				&info->scaling_params[param_idx]);
500 		if (QDF_IS_STATUS_ERROR(status)) {
501 			target_if_err("Extraction of scaling params failed");
502 			goto free_and_return;
503 		}
504 	}
505 
506 	return 0;
507 
508 free_and_return:
509 	qdf_mem_free(info->scaling_params);
510 	info->scaling_params = NULL;
511 
512 	return qdf_status_to_os_return(status);
513 }
514 
515 QDF_STATUS init_deinit_dbr_ring_cap_free(
516 		struct target_psoc_info *tgt_psoc_info)
517 {
518 	QDF_STATUS status = QDF_STATUS_SUCCESS;
519 
520 	if (tgt_psoc_info->info.dbr_ring_cap) {
521 		qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap);
522 		tgt_psoc_info->info.dbr_ring_cap = NULL;
523 	}
524 
525 	return status;
526 }
527 qdf_export_symbol(init_deinit_dbr_ring_cap_free);
528 
529 QDF_STATUS init_deinit_spectral_scaling_params_free(
530 		struct target_psoc_info *tgt_psoc_info)
531 {
532 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
533 
534 	if (tgt_psoc_info->info.scaling_params) {
535 		qdf_mem_free(tgt_psoc_info->info.scaling_params);
536 		tgt_psoc_info->info.scaling_params = NULL;
537 		status = QDF_STATUS_SUCCESS;
538 	}
539 
540 	return status;
541 }
542 
543 qdf_export_symbol(init_deinit_spectral_scaling_params_free);
544 
545 #ifdef DBS_SBS_BAND_LIMITATION_WAR
546 #define phy0               0
547 #define phy2               2
548 #define NUM_RF_MODES       2 /* (DBS + DBS_SBS) */
549 /**
550  * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0.
551  * @psoc: PSOC common object
552  * @info: FW or lower layer related info
553  * @wlan_psoc_host_hal_reg_capabilities_ext: Reg caps per PHY
554  *
555  * For the DBS_SBS capable board, update the low or high frequency
556  * for phy0 by leveraging the frequency populated for phy2
557  * depending on whether it is mapped to upper or lower 5G band by
558  * FW/HAL-PHY.
559  */
560 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
561 					struct tgt_info *info,
562 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
563 {
564 	struct target_psoc_info *tgt_hdl;
565 	enum wmi_host_hw_mode_config_type mode;
566 	uint32_t num_hw_modes;
567 	uint8_t idx;
568 
569 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
570 						psoc);
571 	if (!tgt_hdl) {
572 		target_if_err("target_psoc_info is null in service ready ev");
573 		return;
574 	}
575 
576 	mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
577 
578 	num_hw_modes = info->hw_modes.num_modes;
579 
580 	if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES))
581 		return;
582 
583 	for (idx = 0; idx < num_hw_modes; idx++)
584 		if (info->hw_modes.hw_mode_ids[idx] ==
585 			WMI_HOST_HW_MODE_DBS_SBS) {
586 			if (reg_cap[phy0].low_5ghz_chan >
587 					reg_cap[phy2].low_5ghz_chan)
588 				reg_cap[phy0].low_5ghz_chan =
589 				    reg_cap[phy2].low_5ghz_chan;
590 			else if (reg_cap[phy0].high_5ghz_chan <
591 					reg_cap[phy2].high_5ghz_chan)
592 				reg_cap[phy0].high_5ghz_chan =
593 				    reg_cap[phy2].high_5ghz_chan;
594 			break;
595 		}
596 }
597 #else
598 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
599 					struct tgt_info *info,
600 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
601 {
602 }
603 #endif
604 
605 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
606 				     wmi_unified_t handle, uint8_t *event,
607 				     struct tgt_info *info,
608 				     bool service_ready)
609 {
610 	uint8_t reg_idx;
611 	uint32_t num_phy_reg_cap;
612 	QDF_STATUS status = QDF_STATUS_SUCCESS;
613 	struct wlan_psoc_hal_reg_capability cap;
614 	struct wlan_psoc_host_hal_reg_capabilities_ext
615 				reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
616 
617 	if (service_ready) {
618 		status = wmi_extract_hal_reg_cap(handle, event, &cap);
619 		if (QDF_IS_STATUS_ERROR(status)) {
620 			target_if_err("failed to parse hal reg cap");
621 			return qdf_status_to_os_return(status);
622 		}
623 		info->service_ext_param.num_phy = 1;
624 		num_phy_reg_cap = 1;
625 		reg_cap[0].phy_id = 0;
626 		qdf_mem_copy(&(reg_cap[0].eeprom_reg_domain), &cap,
627 			     sizeof(struct wlan_psoc_hal_reg_capability));
628 		target_if_debug("FW wireless modes 0x%x",
629 				reg_cap[0].wireless_modes);
630 	} else {
631 		num_phy_reg_cap = info->service_ext_param.num_phy;
632 		if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
633 			target_if_err("Invalid num_phy_reg_cap %d",
634 				      num_phy_reg_cap);
635 			return -EINVAL;
636 		}
637 		target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap);
638 
639 		for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
640 			status = wmi_extract_reg_cap_service_ready_ext(handle,
641 					event, reg_idx, &(reg_cap[reg_idx]));
642 			if (QDF_IS_STATUS_ERROR(status)) {
643 				target_if_err("failed to parse reg cap");
644 				return qdf_status_to_os_return(status);
645 			}
646 		}
647 	}
648 
649 	init_deinit_update_phy_reg_cap(psoc, info, reg_cap);
650 	status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap);
651 
652 	return qdf_status_to_os_return(status);
653 }
654 
655 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle,
656 					  uint8_t *event,
657 					  struct tgt_info *info)
658 {
659 	struct wlan_psoc_host_mac_phy_caps_ext2
660 		mac_phy_caps_ext2[PSOC_MAX_MAC_PHY_CAP] = {{0} };
661 	uint32_t num_hw_modes;
662 	uint8_t hw_idx;
663 	uint32_t hw_mode_id;
664 	uint32_t phy_bit_map;
665 	uint8_t phy_id;
666 	uint8_t mac_phy_count = 0;
667 	QDF_STATUS status = QDF_STATUS_SUCCESS;
668 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
669 
670 	if (!event)
671 		return -EINVAL;
672 
673 	num_hw_modes = info->hw_modes.num_modes;
674 
675 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
676 		hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx];
677 		phy_bit_map = info->hw_modes.phy_bit_map[hw_idx];
678 
679 		phy_id = info->mac_phy_cap[mac_phy_count].phy_id;
680 		while (phy_bit_map) {
681 			if (mac_phy_count >= info->total_mac_phy_cnt) {
682 				target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d",
683 					      info->total_mac_phy_cnt,
684 					      mac_phy_count);
685 				return -EINVAL;
686 			}
687 
688 			mac_phy_cap = &info->mac_phy_cap[mac_phy_count];
689 			status = wmi_extract_mac_phy_cap_service_ready_ext2(
690 					wmi_handle, event, hw_mode_id, phy_id,
691 					mac_phy_cap->phy_idx,
692 					&mac_phy_caps_ext2[mac_phy_count]);
693 
694 			if (QDF_IS_STATUS_ERROR(status)) {
695 				target_if_err("failed to parse mac phy capability ext2");
696 				return qdf_status_to_os_return(status);
697 			}
698 
699 			mac_phy_cap->reg_cap_ext.wireless_modes |=
700 				mac_phy_caps_ext2[phy_id].wireless_modes_ext;
701 
702 			mac_phy_count++;
703 			phy_bit_map &= (phy_bit_map - 1);
704 			phy_id++;
705 		}
706 	}
707 
708 	return 0;
709 }
710 
711 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle,
712 					  uint8_t *event,
713 					  struct tgt_info *info)
714 {
715 	struct wlan_psoc_host_hal_reg_capabilities_ext2
716 		reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
717 	struct wlan_objmgr_psoc *psoc;
718 	uint32_t num_phy_reg_cap;
719 	uint8_t reg_idx;
720 	QDF_STATUS status = QDF_STATUS_SUCCESS;
721 
722 	if (!event) {
723 		target_if_err("event buffer is null");
724 		return -EINVAL;
725 	}
726 
727 	psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle);
728 	if (!psoc) {
729 		target_if_err("psoc is null");
730 		return -EINVAL;
731 	}
732 
733 	num_phy_reg_cap = info->service_ext_param.num_phy;
734 	if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
735 		target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap);
736 		return -EINVAL;
737 	}
738 
739 	for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
740 		status = wmi_extract_hal_reg_cap_ext2(
741 				wmi_handle, event, reg_idx, &reg_cap[reg_idx]);
742 		if (QDF_IS_STATUS_ERROR(status)) {
743 			target_if_err("failed to parse hal reg cap ext2");
744 			return qdf_status_to_os_return(status);
745 		}
746 
747 		status = ucfg_reg_update_hal_reg_cap(
748 				psoc, reg_cap[reg_idx].wireless_modes_ext,
749 				reg_idx);
750 		if (QDF_IS_STATUS_ERROR(status)) {
751 			target_if_err("Failed to update hal reg cap");
752 			return qdf_status_to_os_return(status);
753 		}
754 	}
755 
756 	return 0;
757 }
758 
759 static bool init_deinit_regdmn_160mhz_support(
760 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
761 {
762 	return ((hal_cap->wireless_modes &
763 		WMI_HOST_REGDMN_MODE_11AC_VHT160) != 0);
764 }
765 
766 static bool init_deinit_regdmn_80p80mhz_support(
767 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
768 {
769 	return ((hal_cap->wireless_modes &
770 			WMI_HOST_REGDMN_MODE_11AC_VHT80_80) != 0);
771 }
772 
773 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap)
774 {
775 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0);
776 }
777 
778 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap)
779 {
780 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0);
781 }
782 
783 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap)
784 {
785 	return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0);
786 }
787 
788 QDF_STATUS init_deinit_validate_160_80p80_fw_caps(
789 		 struct wlan_objmgr_psoc *psoc,
790 		 struct target_psoc_info *tgt_hdl)
791 {
792 	bool wireless_mode_160mhz = false;
793 	bool wireless_mode_80p80mhz = false;
794 	bool vhtcap_160mhz = false;
795 	bool vhtcap_80p80_160mhz = false;
796 	bool vhtcap_160mhz_sgi = false;
797 	bool valid = false;
798 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
799 	struct wmi_unified *wmi_handle;
800 
801 	if (!tgt_hdl) {
802 		target_if_err(
803 		"target_psoc_info is null in validate 160n80p80 cap check");
804 		return QDF_STATUS_E_INVAL;
805 	}
806 
807 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
808 
809 	if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) ||
810 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) ||
811 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290)) {
812 		/**
813 		 * Return true for now. This is not available in
814 		 * qca8074 fw yet
815 		 */
816 		return QDF_STATUS_SUCCESS;
817 	}
818 
819 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
820 	if (!reg_cap) {
821 		target_if_err("reg cap is NULL");
822 		return QDF_STATUS_E_FAILURE;
823 	}
824 
825 	/* NOTE: Host driver gets vht capability and supported channel
826 	 * width / channel frequency range from FW/HALPHY and obeys it.
827 	 * Host driver is unaware of any physical filters or any other
828 	 * hardware factors that can impact these capabilities.
829 	 * These need to be correctly determined by firmware.
830 	 */
831 
832 	/*This table lists all valid and invalid combinations
833 	 * WMODE160 WMODE80_80  VHTCAP_160 VHTCAP_80+80_160  IsCombinationvalid?
834 	 *      0         0           0              0                 YES
835 	 *      0         0           0              1                 NO
836 	 *      0         0           1              0                 NO
837 	 *      0         0           1              1                 NO
838 	 *      0         1           0              0                 NO
839 	 *      0         1           0              1                 NO
840 	 *      0         1           1              0                 NO
841 	 *      0         1           1              1                 NO
842 	 *      1         0           0              0                 NO
843 	 *      1         0           0              1                 NO
844 	 *      1         0           1              0                 YES
845 	 *      1         0           1              1                 NO
846 	 *      1         1           0              0                 NO
847 	 *      1         1           0              1                 YES
848 	 *      1         1           1              0                 NO
849 	 *      1         1           1              1                 NO
850 	 */
851 
852 	/* NOTE: Last row in above table is invalid because value corresponding
853 	 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per
854 	 * 802.11ac. Only one of them can be set at a time.
855 	 */
856 
857 	wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap);
858 	wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap);
859 	vhtcap_160mhz = init_deinit_vht_160mhz_is_supported(
860 				tgt_hdl->info.target_caps.vht_cap_info);
861 	vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported(
862 				tgt_hdl->info.target_caps.vht_cap_info);
863 	vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported(
864 				tgt_hdl->info.target_caps.vht_cap_info);
865 
866 	if (!(wireless_mode_160mhz || wireless_mode_80p80mhz ||
867 	      vhtcap_160mhz || vhtcap_80p80_160mhz)) {
868 		valid = QDF_STATUS_SUCCESS;
869 	} else if (wireless_mode_160mhz && !wireless_mode_80p80mhz &&
870 		   vhtcap_160mhz && !vhtcap_80p80_160mhz) {
871 		valid = QDF_STATUS_SUCCESS;
872 	} else if (wireless_mode_160mhz && wireless_mode_80p80mhz &&
873 		   !vhtcap_160mhz && vhtcap_160mhz_sgi) {
874 		valid = QDF_STATUS_SUCCESS;
875 	}
876 
877 	if (valid == QDF_STATUS_SUCCESS) {
878 		/*
879 		 * Ensure short GI for 160 MHz is enabled
880 		 * only if 160/80+80 is supported.
881 		 */
882 		if (vhtcap_160mhz_sgi &&
883 		    !(vhtcap_160mhz || vhtcap_80p80_160mhz)) {
884 			valid = QDF_STATUS_E_FAILURE;
885 		}
886 	}
887 
888 	/* Invalid config specified by FW */
889 	if (valid != QDF_STATUS_SUCCESS) {
890 		target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first");
891 		target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d",
892 			      wireless_mode_160mhz, wireless_mode_80p80mhz);
893 		target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d",
894 			      vhtcap_160mhz, vhtcap_80p80_160mhz,
895 			      vhtcap_160mhz_sgi);
896 	}
897 	return valid;
898 }
899 
900 void init_deinit_chainmask_config(
901 		 struct wlan_objmgr_psoc *psoc,
902 		 struct target_psoc_info *tgt_hdl)
903 {
904 	tgt_hdl->info.wlan_res_cfg.tx_chain_mask =
905 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
906 	tgt_hdl->info.wlan_res_cfg.rx_chain_mask =
907 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
908 }
909 
910 QDF_STATUS init_deinit_is_service_ext_msg(
911 		 struct wlan_objmgr_psoc *psoc,
912 		 struct target_psoc_info *tgt_hdl)
913 {
914 	struct wmi_unified *wmi_handle;
915 
916 	if (!tgt_hdl) {
917 		target_if_err(
918 			"psoc target_psoc_info is null in service ext msg");
919 		return QDF_STATUS_E_INVAL;
920 	}
921 
922 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
923 
924 	if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg))
925 		return QDF_STATUS_SUCCESS;
926 	else
927 		return QDF_STATUS_E_FAILURE;
928 }
929 
930 bool init_deinit_is_preferred_hw_mode_supported(
931 		 struct wlan_objmgr_psoc *psoc,
932 		 struct target_psoc_info *tgt_hdl)
933 {
934 	uint16_t i;
935 	struct tgt_info *info;
936 
937 	if (!tgt_hdl) {
938 		target_if_err(
939 			"psoc target_psoc_info is null in service ext msg");
940 		return FALSE;
941 	}
942 
943 	info = &tgt_hdl->info;
944 
945 	if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
946 		return TRUE;
947 
948 	if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) {
949 		if (!wlan_psoc_nif_fw_ext_cap_get(psoc,
950 					WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) {
951 			target_if_err(
952 			"WMI service bit for DYNAMIC HW mode is not set!");
953 			return FALSE;
954 		}
955 	}
956 
957 	for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) {
958 		if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode)
959 			return TRUE;
960 	}
961 
962 	return FALSE;
963 }
964 
965 void init_deinit_wakeup_host_wait(
966 		 struct wlan_objmgr_psoc *psoc,
967 		 struct target_psoc_info *tgt_hdl)
968 {
969 	if (!tgt_hdl) {
970 		target_if_err("psoc target_psoc_info is null in target ready");
971 		return;
972 	}
973 	qdf_event_set(&tgt_hdl->info.event);
974 }
975