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