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 ¶m);
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, ®_cap[0]);
896*5113495bSYour Name init_deinit_populate_tgt_ext_param(info, ®_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, ®_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, ®_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