xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
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 #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 QDF_STATUS init_deinit_dbr_ring_cap_free(
539 		struct target_psoc_info *tgt_psoc_info)
540 {
541 	QDF_STATUS status = QDF_STATUS_SUCCESS;
542 
543 	if (tgt_psoc_info->info.dbr_ring_cap) {
544 		qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap);
545 		tgt_psoc_info->info.dbr_ring_cap = NULL;
546 	}
547 
548 	return status;
549 }
550 qdf_export_symbol(init_deinit_dbr_ring_cap_free);
551 
552 QDF_STATUS init_deinit_spectral_scaling_params_free(
553 		struct target_psoc_info *tgt_psoc_info)
554 {
555 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
556 
557 	if (tgt_psoc_info->info.scaling_params) {
558 		qdf_mem_free(tgt_psoc_info->info.scaling_params);
559 		tgt_psoc_info->info.scaling_params = NULL;
560 		status = QDF_STATUS_SUCCESS;
561 	}
562 
563 	return status;
564 }
565 
566 qdf_export_symbol(init_deinit_spectral_scaling_params_free);
567 
568 #ifdef DBS_SBS_BAND_LIMITATION_WAR
569 #define phy0               0
570 #define phy2               2
571 #define NUM_RF_MODES       2 /* (DBS + DBS_SBS) */
572 /**
573  * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0.
574  * @psoc: PSOC common object
575  * @info: FW or lower layer related info
576  * @wlan_psoc_host_hal_reg_capabilities_ext: Reg caps per PHY
577  *
578  * For the DBS_SBS capable board, update the low or high frequency
579  * for phy0 by leveraging the frequency populated for phy2
580  * depending on whether it is mapped to upper or lower 5G band by
581  * FW/HAL-PHY.
582  */
583 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
584 					struct tgt_info *info,
585 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
586 {
587 	struct target_psoc_info *tgt_hdl;
588 	enum wmi_host_hw_mode_config_type mode;
589 	uint32_t num_hw_modes;
590 	uint8_t idx;
591 
592 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
593 						psoc);
594 	if (!tgt_hdl) {
595 		target_if_err("target_psoc_info is null in service ready ev");
596 		return;
597 	}
598 
599 	mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
600 
601 	num_hw_modes = info->hw_modes.num_modes;
602 
603 	if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES))
604 		return;
605 
606 	for (idx = 0; idx < num_hw_modes; idx++)
607 		if (info->hw_modes.hw_mode_ids[idx] ==
608 			WMI_HOST_HW_MODE_DBS_SBS) {
609 			if (reg_cap[phy0].low_5ghz_chan >
610 					reg_cap[phy2].low_5ghz_chan)
611 				reg_cap[phy0].low_5ghz_chan =
612 				    reg_cap[phy2].low_5ghz_chan;
613 			else if (reg_cap[phy0].high_5ghz_chan <
614 					reg_cap[phy2].high_5ghz_chan)
615 				reg_cap[phy0].high_5ghz_chan =
616 				    reg_cap[phy2].high_5ghz_chan;
617 			break;
618 		}
619 }
620 #else
621 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
622 					struct tgt_info *info,
623 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
624 {
625 }
626 #endif
627 
628 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
629 				     wmi_unified_t handle, uint8_t *event,
630 				     struct tgt_info *info,
631 				     bool service_ready)
632 {
633 	uint8_t reg_idx;
634 	uint32_t num_phy_reg_cap;
635 	QDF_STATUS status = QDF_STATUS_SUCCESS;
636 	struct wlan_psoc_hal_reg_capability cap;
637 	struct wlan_psoc_host_hal_reg_capabilities_ext
638 				reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
639 
640 	if (service_ready) {
641 		status = wmi_extract_hal_reg_cap(handle, event, &cap);
642 		if (QDF_IS_STATUS_ERROR(status)) {
643 			target_if_err("failed to parse hal reg cap");
644 			return qdf_status_to_os_return(status);
645 		}
646 		info->service_ext_param.num_phy = 1;
647 		num_phy_reg_cap = 1;
648 		reg_cap[0].phy_id = 0;
649 		qdf_mem_copy(&(reg_cap[0].eeprom_reg_domain), &cap,
650 			     sizeof(struct wlan_psoc_hal_reg_capability));
651 		target_if_debug("FW wireless modes 0x%x",
652 				reg_cap[0].wireless_modes);
653 	} else {
654 		num_phy_reg_cap = info->service_ext_param.num_phy;
655 		if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
656 			target_if_err("Invalid num_phy_reg_cap %d",
657 				      num_phy_reg_cap);
658 			return -EINVAL;
659 		}
660 		target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap);
661 
662 		for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
663 			status = wmi_extract_reg_cap_service_ready_ext(handle,
664 					event, reg_idx, &(reg_cap[reg_idx]));
665 			if (QDF_IS_STATUS_ERROR(status)) {
666 				target_if_err("failed to parse reg cap");
667 				return qdf_status_to_os_return(status);
668 			}
669 		}
670 	}
671 
672 	init_deinit_update_phy_reg_cap(psoc, info, reg_cap);
673 	status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap);
674 
675 	return qdf_status_to_os_return(status);
676 }
677 
678 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle,
679 					  uint8_t *event,
680 					  struct tgt_info *info)
681 {
682 	struct wlan_psoc_host_mac_phy_caps_ext2
683 		mac_phy_caps_ext2[PSOC_MAX_MAC_PHY_CAP] = {{0} };
684 	uint32_t num_hw_modes;
685 	uint8_t hw_idx;
686 	uint32_t hw_mode_id;
687 	uint32_t phy_bit_map;
688 	uint8_t phy_id;
689 	uint8_t mac_phy_count = 0;
690 	QDF_STATUS status = QDF_STATUS_SUCCESS;
691 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
692 
693 	if (!event)
694 		return -EINVAL;
695 
696 	num_hw_modes = info->hw_modes.num_modes;
697 
698 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
699 		hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx];
700 		phy_bit_map = info->hw_modes.phy_bit_map[hw_idx];
701 
702 		phy_id = info->mac_phy_cap[mac_phy_count].phy_id;
703 		while (phy_bit_map) {
704 			if (mac_phy_count >= info->total_mac_phy_cnt) {
705 				target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d",
706 					      info->total_mac_phy_cnt,
707 					      mac_phy_count);
708 				return -EINVAL;
709 			}
710 
711 			mac_phy_cap = &info->mac_phy_cap[mac_phy_count];
712 			status = wmi_extract_mac_phy_cap_service_ready_ext2(
713 					wmi_handle, event, hw_mode_id, phy_id,
714 					mac_phy_cap->phy_idx,
715 					&mac_phy_caps_ext2[mac_phy_count]);
716 
717 			if (QDF_IS_STATUS_ERROR(status)) {
718 				target_if_err("failed to parse mac phy capability ext2");
719 				return qdf_status_to_os_return(status);
720 			}
721 
722 			mac_phy_cap->reg_cap_ext.wireless_modes |=
723 				mac_phy_caps_ext2[phy_id].wireless_modes_ext;
724 
725 			mac_phy_count++;
726 			phy_bit_map &= (phy_bit_map - 1);
727 			phy_id++;
728 		}
729 	}
730 
731 	return 0;
732 }
733 
734 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle,
735 					  uint8_t *event,
736 					  struct tgt_info *info)
737 {
738 	struct wlan_psoc_host_hal_reg_capabilities_ext2
739 		reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
740 	struct wlan_objmgr_psoc *psoc;
741 	uint32_t num_phy_reg_cap;
742 	uint8_t reg_idx;
743 	QDF_STATUS status = QDF_STATUS_SUCCESS;
744 
745 	if (!event) {
746 		target_if_err("event buffer is null");
747 		return -EINVAL;
748 	}
749 
750 	psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle);
751 	if (!psoc) {
752 		target_if_err("psoc is null");
753 		return -EINVAL;
754 	}
755 
756 	num_phy_reg_cap = info->service_ext_param.num_phy;
757 	if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
758 		target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap);
759 		return -EINVAL;
760 	}
761 
762 	for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
763 		status = wmi_extract_hal_reg_cap_ext2(
764 				wmi_handle, event, reg_idx, &reg_cap[reg_idx]);
765 		if (QDF_IS_STATUS_ERROR(status)) {
766 			target_if_err("failed to parse hal reg cap ext2");
767 			return qdf_status_to_os_return(status);
768 		}
769 
770 		status = ucfg_reg_update_hal_reg_cap(
771 				psoc, reg_cap[reg_idx].wireless_modes_ext,
772 				reg_idx);
773 		if (QDF_IS_STATUS_ERROR(status)) {
774 			target_if_err("Failed to update hal reg cap");
775 			return qdf_status_to_os_return(status);
776 		}
777 	}
778 
779 	return 0;
780 }
781 
782 int init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle,
783 					     uint8_t *event,
784 					     struct tgt_info *info)
785 {
786 	struct wlan_psoc_host_scan_radio_caps *param;
787 	uint32_t num_scan_radio_caps;
788 	uint8_t cap_idx;
789 	QDF_STATUS status;
790 
791 	if (!event) {
792 		target_if_err("Invalid event buffer");
793 		return -EINVAL;
794 	}
795 
796 	num_scan_radio_caps = info->service_ext2_param.num_scan_radio_caps;
797 	target_if_debug("num scan radio capabilities = %d",
798 			num_scan_radio_caps);
799 
800 	if (!num_scan_radio_caps)
801 		return 0;
802 
803 	info->scan_radio_caps = qdf_mem_malloc(
804 				sizeof(struct wlan_psoc_host_scan_radio_caps) *
805 				num_scan_radio_caps);
806 
807 	if (!info->scan_radio_caps) {
808 		target_if_err("Failed to allocate memory for scan radio caps");
809 		return -EINVAL;
810 	}
811 
812 	for (cap_idx = 0; cap_idx < num_scan_radio_caps; cap_idx++) {
813 		param = &info->scan_radio_caps[cap_idx];
814 		status = wmi_extract_scan_radio_cap_service_ready_ext2(
815 				wmi_handle, event, cap_idx, param);
816 		if (QDF_IS_STATUS_ERROR(status)) {
817 			target_if_err("Extraction of scan radio cap failed");
818 			goto free_and_return;
819 		}
820 	}
821 
822 	return 0;
823 
824 free_and_return:
825 	qdf_mem_free(info->scan_radio_caps);
826 	info->scan_radio_caps = NULL;
827 
828 	return qdf_status_to_os_return(status);
829 }
830 
831 QDF_STATUS init_deinit_scan_radio_cap_free(
832 		struct target_psoc_info *tgt_psoc_info)
833 {
834 	qdf_mem_free(tgt_psoc_info->info.scan_radio_caps);
835 	tgt_psoc_info->info.scan_radio_caps = NULL;
836 
837 	return QDF_STATUS_SUCCESS;
838 }
839 
840 qdf_export_symbol(init_deinit_scan_radio_cap_free);
841 
842 static bool init_deinit_regdmn_160mhz_support(
843 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
844 {
845 	return ((hal_cap->wireless_modes &
846 		WMI_HOST_REGDMN_MODE_11AC_VHT160) != 0);
847 }
848 
849 static bool init_deinit_regdmn_80p80mhz_support(
850 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
851 {
852 	return ((hal_cap->wireless_modes &
853 			WMI_HOST_REGDMN_MODE_11AC_VHT80_80) != 0);
854 }
855 
856 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap)
857 {
858 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0);
859 }
860 
861 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap)
862 {
863 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0);
864 }
865 
866 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap)
867 {
868 	return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0);
869 }
870 
871 QDF_STATUS init_deinit_validate_160_80p80_fw_caps(
872 		 struct wlan_objmgr_psoc *psoc,
873 		 struct target_psoc_info *tgt_hdl)
874 {
875 	bool wireless_mode_160mhz = false;
876 	bool wireless_mode_80p80mhz = false;
877 	bool vhtcap_160mhz = false;
878 	bool vhtcap_80p80_160mhz = false;
879 	bool vhtcap_160mhz_sgi = false;
880 	bool valid = false;
881 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
882 	struct wmi_unified *wmi_handle;
883 
884 	if (!tgt_hdl) {
885 		target_if_err(
886 		"target_psoc_info is null in validate 160n80p80 cap check");
887 		return QDF_STATUS_E_INVAL;
888 	}
889 
890 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
891 
892 	if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) ||
893 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) ||
894 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290)) {
895 		/**
896 		 * Return true for now. This is not available in
897 		 * qca8074 fw yet
898 		 */
899 		return QDF_STATUS_SUCCESS;
900 	}
901 
902 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
903 	if (!reg_cap) {
904 		target_if_err("reg cap is NULL");
905 		return QDF_STATUS_E_FAILURE;
906 	}
907 
908 	/* NOTE: Host driver gets vht capability and supported channel
909 	 * width / channel frequency range from FW/HALPHY and obeys it.
910 	 * Host driver is unaware of any physical filters or any other
911 	 * hardware factors that can impact these capabilities.
912 	 * These need to be correctly determined by firmware.
913 	 */
914 
915 	/*This table lists all valid and invalid combinations
916 	 * WMODE160 WMODE80_80  VHTCAP_160 VHTCAP_80+80_160  IsCombinationvalid?
917 	 *      0         0           0              0                 YES
918 	 *      0         0           0              1                 NO
919 	 *      0         0           1              0                 NO
920 	 *      0         0           1              1                 NO
921 	 *      0         1           0              0                 NO
922 	 *      0         1           0              1                 NO
923 	 *      0         1           1              0                 NO
924 	 *      0         1           1              1                 NO
925 	 *      1         0           0              0                 NO
926 	 *      1         0           0              1                 NO
927 	 *      1         0           1              0                 YES
928 	 *      1         0           1              1                 NO
929 	 *      1         1           0              0                 NO
930 	 *      1         1           0              1                 YES
931 	 *      1         1           1              0                 NO
932 	 *      1         1           1              1                 NO
933 	 */
934 
935 	/* NOTE: Last row in above table is invalid because value corresponding
936 	 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per
937 	 * 802.11ac. Only one of them can be set at a time.
938 	 */
939 
940 	wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap);
941 	wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap);
942 	vhtcap_160mhz = init_deinit_vht_160mhz_is_supported(
943 				tgt_hdl->info.target_caps.vht_cap_info);
944 	vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported(
945 				tgt_hdl->info.target_caps.vht_cap_info);
946 	vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported(
947 				tgt_hdl->info.target_caps.vht_cap_info);
948 
949 	if (!(wireless_mode_160mhz || wireless_mode_80p80mhz ||
950 	      vhtcap_160mhz || vhtcap_80p80_160mhz)) {
951 		valid = QDF_STATUS_SUCCESS;
952 	} else if (wireless_mode_160mhz && !wireless_mode_80p80mhz &&
953 		   vhtcap_160mhz && !vhtcap_80p80_160mhz) {
954 		valid = QDF_STATUS_SUCCESS;
955 	} else if (wireless_mode_160mhz && wireless_mode_80p80mhz &&
956 		   !vhtcap_160mhz && vhtcap_160mhz_sgi) {
957 		valid = QDF_STATUS_SUCCESS;
958 	}
959 
960 	if (valid == QDF_STATUS_SUCCESS) {
961 		/*
962 		 * Ensure short GI for 160 MHz is enabled
963 		 * only if 160/80+80 is supported.
964 		 */
965 		if (vhtcap_160mhz_sgi &&
966 		    !(vhtcap_160mhz || vhtcap_80p80_160mhz)) {
967 			valid = QDF_STATUS_E_FAILURE;
968 		}
969 	}
970 
971 	/* Invalid config specified by FW */
972 	if (valid != QDF_STATUS_SUCCESS) {
973 		target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first");
974 		target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d",
975 			      wireless_mode_160mhz, wireless_mode_80p80mhz);
976 		target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d",
977 			      vhtcap_160mhz, vhtcap_80p80_160mhz,
978 			      vhtcap_160mhz_sgi);
979 	}
980 	return valid;
981 }
982 
983 void init_deinit_chainmask_config(
984 		 struct wlan_objmgr_psoc *psoc,
985 		 struct target_psoc_info *tgt_hdl)
986 {
987 	tgt_hdl->info.wlan_res_cfg.tx_chain_mask =
988 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
989 	tgt_hdl->info.wlan_res_cfg.rx_chain_mask =
990 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
991 }
992 
993 QDF_STATUS init_deinit_is_service_ext_msg(
994 		 struct wlan_objmgr_psoc *psoc,
995 		 struct target_psoc_info *tgt_hdl)
996 {
997 	struct wmi_unified *wmi_handle;
998 
999 	if (!tgt_hdl) {
1000 		target_if_err(
1001 			"psoc target_psoc_info is null in service ext msg");
1002 		return QDF_STATUS_E_INVAL;
1003 	}
1004 
1005 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
1006 
1007 	if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg))
1008 		return QDF_STATUS_SUCCESS;
1009 	else
1010 		return QDF_STATUS_E_FAILURE;
1011 }
1012 
1013 bool init_deinit_is_preferred_hw_mode_supported(
1014 		 struct wlan_objmgr_psoc *psoc,
1015 		 struct target_psoc_info *tgt_hdl)
1016 {
1017 	uint16_t i;
1018 	struct tgt_info *info;
1019 
1020 	if (!tgt_hdl) {
1021 		target_if_err(
1022 			"psoc target_psoc_info is null in service ext msg");
1023 		return FALSE;
1024 	}
1025 
1026 	info = &tgt_hdl->info;
1027 
1028 	if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
1029 		return TRUE;
1030 
1031 	if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) {
1032 		if (!wlan_psoc_nif_fw_ext_cap_get(psoc,
1033 					WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) {
1034 			target_if_err(
1035 			"WMI service bit for DYNAMIC HW mode is not set!");
1036 			return FALSE;
1037 		}
1038 	}
1039 
1040 	for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) {
1041 		if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode)
1042 			return TRUE;
1043 	}
1044 
1045 	return FALSE;
1046 }
1047 
1048 void init_deinit_wakeup_host_wait(
1049 		 struct wlan_objmgr_psoc *psoc,
1050 		 struct target_psoc_info *tgt_hdl)
1051 {
1052 	if (!tgt_hdl) {
1053 		target_if_err("psoc target_psoc_info is null in target ready");
1054 		return;
1055 	}
1056 	qdf_event_set(&tgt_hdl->info.event);
1057 }
1058