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